diff --git a/extensions/pom.xml b/extensions/pom.xml new file mode 100644 index 000000000..64c872308 --- /dev/null +++ b/extensions/pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + + com.google.truth + truth-parent + 1.0-SNAPSHOT + + com.google.truth.extensions + truth-extensions-parent + pom + Truth Extensions (Parent) + + Parent metdata for a collection of Truth extensions, Subjects, utilities for + the Truth assertion framework. + + + re2j + + diff --git a/extensions/re2j/pom.xml b/extensions/re2j/pom.xml new file mode 100644 index 000000000..34582a776 --- /dev/null +++ b/extensions/re2j/pom.xml @@ -0,0 +1,31 @@ + + + 4.0.0 + + com.google.truth.extensions + truth-extensions-parent + 1.0-SNAPSHOT + + truth-re2j-extension + Truth Extension for RE2J + + An extension for the Truth test assertion framework supporting RE2J patterns + + + + com.google.truth + truth + 1.0-SNAPSHOT + + + com.google.re2j + re2j + 1.0 + + + + + diff --git a/extensions/re2j/src/main/java/com/google/common/truth/extensions/re2j/Re2jSubjects.java b/extensions/re2j/src/main/java/com/google/common/truth/extensions/re2j/Re2jSubjects.java new file mode 100644 index 000000000..bdee8d796 --- /dev/null +++ b/extensions/re2j/src/main/java/com/google/common/truth/extensions/re2j/Re2jSubjects.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2015 Google, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.common.truth.extensions.re2j; + +import com.google.common.annotations.GwtIncompatible; +import com.google.common.truth.FailureStrategy; +import com.google.common.truth.Subject; +import com.google.common.truth.SubjectFactory; +import com.google.re2j.Pattern; + +/** + * Truth subjects for re2j regular expressions. + * + *

Truth natively provides subjects for dealing with {@code java.util.regex} based regular + * expressions. This class is intended to provide {@code com.google.re2j} analogues to those + * methods. + */ +public final class Re2jSubjects { + /** + * Returns a subject factory for {@link String} subjects which you can use to assert things about + * {@link com.google.re2j.Pattern} regexes. + * + *

This subject does not replace Truth's built-in {@link com.google.common.truth.StringSubject} + * but instead provides only the methods needed to deal with regular expressions. + * + * @see com.google.common.truth.StringSubject + */ + public static SubjectFactory re2jString() { + return Re2jStringSubject.FACTORY; + } + + /** + * Subject for {@link String} subjects which you can use to assert things about + * {@link com.google.re2j.Pattern} regexes. + * + * @see #re2jString + */ + public static final class Re2jStringSubject extends Subject { + private static final SubjectFactory FACTORY = + new SubjectFactory() { + @Override + public Re2jStringSubject getSubject(FailureStrategy fs, String target) { + return new Re2jStringSubject(fs, target); + } + }; + + private Re2jStringSubject(FailureStrategy failureStrategy, String subject) { + super(failureStrategy, subject); + } + + @Override + protected String getDisplaySubject() { + if (internalCustomName() != null) { + return internalCustomName() + " (<" + quote(getSubject()) + ">)"; + } else { + return "<" + quote(getSubject()) + ">"; + } + } + + /** + * Fails if the string does not match the given regex. + */ + public void matches(String regex) { + if (!Pattern.matches(regex, getSubject())) { + fail("matches", regex); + } + } + + /** + * Fails if the string does not match the given regex. + */ + @GwtIncompatible("com.google.re2j.Pattern") + public void matches(Pattern regex) { + if (!regex.matcher(getSubject()).matches()) { + fail("matches", regex); + } + } + + /** + * Fails if the string matches the given regex. + */ + public void doesNotMatch(String regex) { + if (Pattern.matches(regex, getSubject())) { + fail("fails to match", regex); + } + } + + /** + * Fails if the string matches the given regex. + */ + @GwtIncompatible("com.google.re2j.Pattern") + public void doesNotMatch(Pattern regex) { + if (regex.matcher(getSubject()).matches()) { + fail("fails to match", regex); + } + } + + /** + * Fails if the string does not contain a match on the given regex. + */ + @GwtIncompatible("com.google.re2j.Pattern") + public void containsMatch(Pattern pattern) { + if (!pattern.matcher(getSubject()).find()) { + failWithRawMessage( + "%s should have contained a match for <%s>", + getDisplaySubject(), + pattern); + } + } + + /** + * Fails if the string does not contain a match on the given regex. + */ + public void containsMatch(String regex) { + if (!containsMatch(getSubject(), regex)) { + failWithRawMessage("%s should have contained a match for <%s>", getDisplaySubject(), regex); + } + } + + /** + * Fails if the string contains a match on the given regex. + */ + @GwtIncompatible("com.google.re2j.Pattern") + public void doesNotContainMatch(Pattern pattern) { + if (pattern.matcher(getSubject()).find()) { + failWithRawMessage("%s should not have contained a match for <%s>", + getDisplaySubject(), pattern); + } + } + + /** + * Fails if the string contains a match on the given regex. + */ + public void doesNotContainMatch(String regex) { + if (containsMatch(getSubject(), regex)) { + failWithRawMessage("%s should not have contained a match for <%s>", + getDisplaySubject(), regex); + } + } + + private static String quote(CharSequence toBeWrapped) { + return "\"" + toBeWrapped + "\""; + } + + private static boolean containsMatch(String subject, String regex) { + return Pattern.compile(regex).matcher(subject).find(); + } + } + + private Re2jSubjects() {} +} diff --git a/extensions/re2j/src/test/java/com/google/common/truth/extensions/re2j/Re2jSubjectsTest.java b/extensions/re2j/src/test/java/com/google/common/truth/extensions/re2j/Re2jSubjectsTest.java new file mode 100644 index 000000000..9b19a2d9c --- /dev/null +++ b/extensions/re2j/src/test/java/com/google/common/truth/extensions/re2j/Re2jSubjectsTest.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2015 Google, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.common.truth.extensions.re2j; + +import static com.google.common.truth.extensions.re2j.Re2jSubjects.re2jString; +import static com.google.common.truth.Truth.assertAbout; + +import com.google.re2j.Pattern; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Re2jSubjects}. */ +@RunWith(JUnit4.class) +public class Re2jSubjectsTest { + private static final String PATTERN_STR = "(?:hello )+world"; + private static final Pattern PATTERN = Pattern.compile(PATTERN_STR); + + @Test + public void matches_string_succeeds() { + assertAbout(re2jString()).that("hello world").matches(PATTERN_STR); + } + + @Test + public void matches_pattern_succeeds() { + assertAbout(re2jString()).that("hello world").matches(PATTERN); + } + + @Test + public void doesNotMatch_string_succeeds() { + assertAbout(re2jString()).that("world").doesNotMatch(PATTERN_STR); + } + + @Test + public void doesNotMatch_pattern_succeeds() { + assertAbout(re2jString()).that("world").doesNotMatch(PATTERN); + } + + @Test + public void containsMatch_string_succeeds() { + assertAbout(re2jString()).that("this is a hello world").containsMatch(PATTERN_STR); + } + + @Test + public void containsMatch_pattern_succeeds() { + assertAbout(re2jString()).that("this is a hello world").containsMatch(PATTERN); + } + + @Test + public void doesNotContainMatch_string_succeeds() { + assertAbout(re2jString()).that("hello cruel world").doesNotContainMatch(PATTERN_STR); + } + + @Test + public void doesNotContainMatch_pattern_succeeds() { + assertAbout(re2jString()).that("hello cruel world").doesNotContainMatch(PATTERN); + } +} diff --git a/pom.xml b/pom.xml index 0de255118..e444d7873 100644 --- a/pom.xml +++ b/pom.xml @@ -17,6 +17,7 @@ core + extensions 3.0.3