aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-testing-harness
diff options
context:
space:
mode:
authorSimon Brandhof <simon.brandhof@sonarsource.com>2015-03-19 14:46:58 +0100
committerSimon Brandhof <simon.brandhof@sonarsource.com>2015-03-20 11:07:24 +0100
commit88219ea163c159be7d16203be32d8f0b3d7e7d0a (patch)
treeef96d6c0860ebac6b53ff6f39d521a733c14c25b /sonar-testing-harness
parent1af9a73913f04992e8a9033b29980dd74c6f0a22 (diff)
downloadsonarqube-88219ea163c159be7d16203be32d8f0b3d7e7d0a.tar.gz
sonarqube-88219ea163c159be7d16203be32d8f0b3d7e7d0a.zip
Replace lib org.skyscreamer.jsonassert by org.sonar.test.JsonAssert.
This class supports lenient comparison of datetime values.
Diffstat (limited to 'sonar-testing-harness')
-rw-r--r--sonar-testing-harness/pom.xml8
-rw-r--r--sonar-testing-harness/src/main/java/org/sonar/test/JsonAssert.java100
-rw-r--r--sonar-testing-harness/src/main/java/org/sonar/test/JsonComparison.java198
-rw-r--r--sonar-testing-harness/src/test/java/org/sonar/test/JsonAssertTest.java97
-rw-r--r--sonar-testing-harness/src/test/java/org/sonar/test/JsonComparisonTest.java178
-rw-r--r--sonar-testing-harness/src/test/resources/org/sonar/test/JsonAssertTest/sample1.json1
-rw-r--r--sonar-testing-harness/src/test/resources/org/sonar/test/JsonAssertTest/sample2.json1
7 files changed, 581 insertions, 2 deletions
diff --git a/sonar-testing-harness/pom.xml b/sonar-testing-harness/pom.xml
index a0af4198337..11126f3cbe4 100644
--- a/sonar-testing-harness/pom.xml
+++ b/sonar-testing-harness/pom.xml
@@ -16,8 +16,12 @@
<artifactId>assertj-core</artifactId>
</dependency>
<dependency>
- <groupId>org.skyscreamer</groupId>
- <artifactId>jsonassert</artifactId>
+ <groupId>com.googlecode.json-simple</groupId>
+ <artifactId>json-simple</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
diff --git a/sonar-testing-harness/src/main/java/org/sonar/test/JsonAssert.java b/sonar-testing-harness/src/main/java/org/sonar/test/JsonAssert.java
new file mode 100644
index 00000000000..ac9f2470da6
--- /dev/null
+++ b/sonar-testing-harness/src/main/java/org/sonar/test/JsonAssert.java
@@ -0,0 +1,100 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.test;
+
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParser;
+import org.apache.commons.io.Charsets;
+import org.apache.commons.io.IOUtils;
+import org.junit.ComparisonFailure;
+
+import java.io.IOException;
+import java.net.URL;
+
+/**
+ * Assertion to compare JSON documents. Comparison is not strict:
+ * <ul>
+ * <li>formatting differences are ignored</li>
+ * <li>order of elements in objects <code>{}</code> is not verified</li>
+ * <li>objects can contain more elements than expected, for example <code>{"one":1, "two":2}</code>
+ * matches <code>{"one":1}</code></li>
+ * <li>order of elements in arrays <code>[]</code> is not verified by default, for example <code>[1, 2]</code>
+ * matches <code>[2, 1]</code>. This mode can be disabled with {@link #setStrictArrayOrder(boolean)}</li>
+ * <li>timezones in datetime values are not strictly verified, for example <code>{"foo": "2015-01-01T13:00:00+2000"}</code>
+ * matches <code>{"foo": "2015-01-01T10:00:00-1000"}</code>. This feature can be disabled with
+ * {@link #setStrictTimezone(boolean)}
+ * </li>
+ * </ul>
+ *
+ * @since 5.2
+ */
+public class JsonAssert {
+
+ private final String actualJson;
+ private final JsonComparison comparison = new JsonComparison();
+
+ private JsonAssert(String actualJson) {
+ this.actualJson = actualJson;
+ }
+
+ public JsonAssert setStrictTimezone(boolean b) {
+ comparison.setStrictTimezone(b);
+ return this;
+ }
+
+ public JsonAssert setStrictArrayOrder(boolean b) {
+ comparison.setStrictArrayOrder(b);
+ return this;
+ }
+
+ public JsonAssert isSimilarTo(String expected) {
+ boolean similar = comparison.areSimilar(expected, actualJson);
+ if (!similar) {
+ throw new ComparisonFailure("Not a super-set of expected JSON -", pretty(expected), pretty(actualJson));
+ }
+ return this;
+ }
+
+ public JsonAssert isSimilarTo(URL expected) {
+ return isSimilarTo(urlToString(expected));
+ }
+
+ public static JsonAssert assertJson(String actualJson) {
+ return new JsonAssert(actualJson);
+ }
+
+ public static JsonAssert assertJson(URL actualJson) {
+ return new JsonAssert(urlToString(actualJson));
+ }
+
+ private static String urlToString(URL url) {
+ try {
+ return IOUtils.toString(url, Charsets.UTF_8);
+ } catch (IOException e) {
+ throw new IllegalStateException("Fail to load JSON from " + url, e);
+ }
+ }
+
+ private static String pretty(String json) {
+ JsonElement gson = new JsonParser().parse(json);
+ return new GsonBuilder().setPrettyPrinting().serializeNulls().create().toJson(gson);
+ }
+}
diff --git a/sonar-testing-harness/src/main/java/org/sonar/test/JsonComparison.java b/sonar-testing-harness/src/main/java/org/sonar/test/JsonComparison.java
new file mode 100644
index 00000000000..1a437f5daad
--- /dev/null
+++ b/sonar-testing-harness/src/main/java/org/sonar/test/JsonComparison.java
@@ -0,0 +1,198 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.test;
+
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.json.simple.parser.JSONParser;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Not thread-safe because of field datetimeFormat which is SimpleDateFormat.
+ */
+class JsonComparison {
+
+ private static final SimpleDateFormat datetimeFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
+
+ private boolean strictTimezone = false;
+ private boolean strictArrayOrder = false;
+
+ boolean isStrictTimezone() {
+ return strictTimezone;
+ }
+
+ JsonComparison setStrictTimezone(boolean b) {
+ this.strictTimezone = b;
+ return this;
+ }
+
+ boolean isStrictArrayOrder() {
+ return strictArrayOrder;
+ }
+
+ JsonComparison setStrictArrayOrder(boolean b) {
+ this.strictArrayOrder = b;
+ return this;
+ }
+
+ boolean areSimilar(String expected, String actual) {
+ Object expectedJson = parse(expected);
+ Object actualJson = parse(actual);
+ return compare(expectedJson, actualJson);
+ }
+
+ private Object parse(String s) {
+ try {
+ JSONParser parser = new JSONParser();
+ return parser.parse(s);
+ } catch (Exception e) {
+ throw new IllegalStateException("Invalid JSON: " + s, e);
+ }
+ }
+
+ private boolean compare(@Nullable Object expectedObject, @Nullable Object actualObject) {
+ if (expectedObject == null) {
+ return actualObject == null;
+ }
+ if (actualObject == null) {
+ return false;
+ }
+ if (expectedObject.getClass() != actualObject.getClass()) {
+ return false;
+ }
+ if (expectedObject instanceof JSONArray) {
+ return compareArrays((JSONArray) expectedObject, (JSONArray) actualObject);
+ }
+ if (expectedObject instanceof JSONObject) {
+ return compareMaps((JSONObject) expectedObject, (JSONObject) actualObject);
+ }
+ if (expectedObject instanceof String) {
+ return compareStrings((String) expectedObject, (String) actualObject);
+ }
+ if (expectedObject instanceof Number) {
+ return compareNumbers((Number) expectedObject, (Number) actualObject);
+ }
+ return compareBooleans((Boolean) expectedObject, (Boolean) actualObject);
+ }
+
+ private boolean compareBooleans(Boolean expected, Boolean actual) {
+ return expected.equals(actual);
+ }
+
+ private boolean compareNumbers(Number expected, Number actual) {
+ double d1 = expected.doubleValue();
+ double d2 = actual.doubleValue();
+ if (Double.compare(d1, d2) == 0) {
+ return true;
+ }
+ return (Math.abs(d1 - d2) <= 0.0000001);
+ }
+
+ private boolean compareStrings(String expected, String actual) {
+ if (!strictTimezone) {
+ // two instants with different timezones are considered as identical (2015-01-01T13:00:00+0100 and 2015-01-01T12:00:00+0000)
+ Date expectedDate = tryParseDate(expected);
+ Date actualDate = tryParseDate(actual);
+ if (expectedDate != null && actualDate != null) {
+ return expectedDate.getTime() == actualDate.getTime();
+ }
+ }
+ return expected.equals(actual);
+ }
+
+ private boolean compareArrays(JSONArray expected, JSONArray actual) {
+ if (strictArrayOrder) {
+ return compareArraysByStrictOrder(expected, actual);
+ }
+ return compareArraysByLenientOrder(expected, actual);
+ }
+
+ private boolean compareArraysByStrictOrder(JSONArray expected, JSONArray actual) {
+ if (expected.size() != actual.size()) {
+ return false;
+ }
+
+ for (int index = 0; index < expected.size(); index++) {
+ Object expectedElt = expected.get(index);
+ Object actualElt = actual.get(index);
+ if (!compare(expectedElt, actualElt)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private boolean compareArraysByLenientOrder(JSONArray expected, JSONArray actual) {
+ if (expected.size() > actual.size()) {
+ return false;
+ }
+
+ List remainingActual = new ArrayList(actual);
+ for (Object expectedElement : expected) {
+ // element can be null
+ boolean found = false;
+ for (Object actualElement : remainingActual) {
+ if (compare(expectedElement, actualElement)) {
+ found = true;
+ remainingActual.remove(actualElement);
+ break;
+ }
+ }
+ if (!found) {
+ return false;
+ }
+ }
+ if (!remainingActual.isEmpty()) {
+ return false;
+ }
+ return true;
+ }
+
+ private boolean compareMaps(JSONObject expectedMap, JSONObject actualMap) {
+ // each key-value of expected map must exist in actual map
+ for (Object expectedKey : expectedMap.keySet()) {
+ if (!actualMap.containsKey(expectedKey)) {
+ return false;
+ }
+ if (!compare(expectedMap.get(expectedKey), actualMap.get(expectedKey))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @CheckForNull
+ Date tryParseDate(String s) {
+ try {
+ return datetimeFormat.parse(s);
+ } catch (ParseException ignored) {
+ // not a datetime
+ return null;
+ }
+ }
+}
diff --git a/sonar-testing-harness/src/test/java/org/sonar/test/JsonAssertTest.java b/sonar-testing-harness/src/test/java/org/sonar/test/JsonAssertTest.java
new file mode 100644
index 00000000000..59a05d6506f
--- /dev/null
+++ b/sonar-testing-harness/src/test/java/org/sonar/test/JsonAssertTest.java
@@ -0,0 +1,97 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.test;
+
+import org.junit.ComparisonFailure;
+import org.junit.Test;
+
+import java.io.File;
+import java.net.URL;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.fail;
+import static org.sonar.test.JsonAssert.assertJson;
+
+public class JsonAssertTest {
+
+ @Test
+ public void isSimilarAs_strings() throws Exception {
+ assertJson("{}").isSimilarTo("{}");
+
+ try {
+ assertJson("{}").isSimilarTo("[]");
+ fail();
+ } catch (ComparisonFailure error) {
+ assertThat(error.getMessage()).isEqualTo("Not a super-set of expected JSON - expected:<[[]]> but was:<[{}]>");
+ assertThat(error.getActual()).isEqualTo("{}");
+ assertThat(error.getExpected()).isEqualTo("[]");
+ }
+ }
+
+ @Test
+ public void isSimilarAs_urls() throws Exception {
+ URL url1 = getClass().getResource("JsonAssertTest/sample1.json");
+ URL url2 = getClass().getResource("JsonAssertTest/sample2.json");
+ assertJson(url1).isSimilarTo(url1);
+
+ try {
+ assertJson(url1).isSimilarTo(url2);
+ fail();
+ } catch (AssertionError error) {
+ // ok
+ }
+ }
+
+ @Test
+ public void actual_can_be_superset_of_expected() throws Exception {
+ assertJson("{\"foo\": \"bar\"}").isSimilarTo("{}");
+ try {
+ assertJson("{}").isSimilarTo("{\"foo\": \"bar\"}");
+ fail();
+ } catch (AssertionError error) {
+ // ok
+ }
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void fail_to_load_url() throws Exception {
+ assertJson(new File("target/missing").toURL());
+ }
+
+ @Test
+ public void enable_strict_order_of_arrays() throws Exception {
+ try {
+ assertJson("[1,2]").setStrictArrayOrder(true).isSimilarTo("[2, 1]");
+ fail();
+ } catch (AssertionError error) {
+ // ok
+ }
+ }
+
+ @Test
+ public void enable_strict_timezone() throws Exception {
+ try {
+ assertJson("[\"2010-05-18T15:50:45+0100\"]").setStrictTimezone(true).isSimilarTo("[\"2010-05-18T16:50:45+0200\"]");
+ fail();
+ } catch (AssertionError error) {
+ // ok
+ }
+ }
+}
diff --git a/sonar-testing-harness/src/test/java/org/sonar/test/JsonComparisonTest.java b/sonar-testing-harness/src/test/java/org/sonar/test/JsonComparisonTest.java
new file mode 100644
index 00000000000..6dc57199a7c
--- /dev/null
+++ b/sonar-testing-harness/src/test/java/org/sonar/test/JsonComparisonTest.java
@@ -0,0 +1,178 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.test;
+
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class JsonComparisonTest {
+
+ @Test(expected = IllegalStateException.class)
+ public void fail_if_invalid_json() {
+ areSimilar("{]", "");
+ }
+
+ @Test
+ public void syntax_agnostic() throws Exception {
+ assertThat(areSimilar("{}", " { } ")).isTrue();
+ assertThat(areSimilar("{\"foo\":\"bar\"}", "{\"foo\": \"bar\" \n }")).isTrue();
+ }
+
+ @Test
+ public void object() throws Exception {
+ assertThat(areSimilar("{}", "{}")).isTrue();
+
+ // exactly the same
+ assertThat(areSimilar("{\"foo\":\"bar\"}", "{\"foo\":\"bar\"}")).isTrue();
+
+ // same key but different value
+ assertThat(areSimilar("{\"foo\":\"bar\"}", "{\"foo\":\"baz\"}")).isFalse();
+
+ // missing key
+ assertThat(areSimilar("{\"foo\":\"bar\"}", "{\"xxx\":\"bar\"}")).isFalse();
+
+ // expected json can be a subset of actual json
+ assertThat(areSimilar("{\"foo\":\"bar\"}", "{\"xxx\":\"bar\", \"foo\": \"bar\"}")).isTrue();
+ }
+
+ @Test
+ public void strict_order_of_array() throws Exception {
+ assertThat(isSimilar_strict_array_order("[]", "[]")).isTrue();
+ assertThat(isSimilar_strict_array_order("[1, 2]", "[1, 2]")).isTrue();
+
+ assertThat(isSimilar_strict_array_order("[1, 2]", "[1]")).isFalse();
+ assertThat(isSimilar_strict_array_order("[1, 2]", "[2, 1]")).isFalse();
+ assertThat(isSimilar_strict_array_order("[1, 2]", "[1 , 2, 3]")).isFalse();
+ assertThat(isSimilar_strict_array_order("[1, 2]", "[1 , false]")).isFalse();
+ assertThat(isSimilar_strict_array_order("[1, 2]", "[1 , 3.14]")).isFalse();
+ }
+
+ @Test
+ public void lenient_order_of_array() throws Exception {
+ assertThat(areSimilar("[]", "[]")).isTrue();
+ assertThat(areSimilar("[1, 2]", "[1, 2]")).isTrue();
+ assertThat(areSimilar("[1, 2]", "[1]")).isFalse();
+ assertThat(areSimilar("[1, 2]", "[2, 1]")).isTrue();
+ assertThat(areSimilar("[1, 2]", "[1 , 2, 3]")).isFalse();
+ assertThat(areSimilar("[1, 2]", "[1 , false]")).isFalse();
+ assertThat(areSimilar("[1, 2]", "[1 , 3.14]")).isFalse();
+ }
+
+ @Test
+ public void lenient_order_of_arrays_by_default() throws Exception {
+ assertThat(new JsonComparison().isStrictArrayOrder()).isFalse();
+ }
+
+ @Test
+ public void null_value() throws Exception {
+ assertThat(areSimilar("[null]", "[null]")).isTrue();
+ assertThat(areSimilar("[null]", "[]")).isFalse();
+
+ assertThat(areSimilar("{\"foo\": null}", "{\"foo\": null}")).isTrue();
+ assertThat(areSimilar("{\"foo\": null}", "{\"foo\": \"bar\"}")).isFalse();
+ assertThat(areSimilar("{\"foo\": 3}", "{\"foo\": null}")).isFalse();
+ assertThat(areSimilar("{\"foo\": 3.14}", "{\"foo\": null}")).isFalse();
+ assertThat(areSimilar("{\"foo\": false}", "{\"foo\": null}")).isFalse();
+ assertThat(areSimilar("{\"foo\": true}", "{\"foo\": null}")).isFalse();
+ assertThat(areSimilar("{\"foo\": null}", "{\"foo\": 3}")).isFalse();
+ assertThat(areSimilar("{\"foo\": null}", "{\"foo\": 3.14}")).isFalse();
+ assertThat(areSimilar("{\"foo\": null}", "{\"foo\": false}")).isFalse();
+ assertThat(areSimilar("{\"foo\": null}", "{\"foo\": true}")).isFalse();
+ }
+
+ @Test
+ public void maps_and_arrays() throws Exception {
+ assertThat(areSimilar("[]", "{}")).isFalse();
+ assertThat(areSimilar("{}", "[]")).isFalse();
+
+ // map of array
+ assertThat(areSimilar("{\"foo\": []}", "{\"foo\": []}")).isTrue();
+ assertThat(areSimilar("{\"foo\": [1, 3]}", "{\"foo\": [1, 3], \"bar\": [1, 3]}")).isTrue();
+ assertThat(areSimilar("{\"foo\": []}", "{\"foo\": []}")).isTrue();
+ assertThat(areSimilar("{\"foo\": [1, 2]}", "{\"foo\": [1, 3]}")).isFalse();
+
+ // array of maps
+ assertThat(areSimilar("[{}]", "[{}]")).isTrue();
+ assertThat(areSimilar("[{}]", "[{\"foo\": 1}]")).isTrue();
+ // exactly the sames
+ assertThat(areSimilar("[{\"1\": \"3\"}, {\"2\":\"4\"}]", "[{\"1\": \"3\"}, {\"2\":\"4\"}]")).isTrue();
+ // different value
+ assertThat(areSimilar("[{\"1\": \"3\"}, {\"2\":\"4\"}]", "[{\"1\": \"3\"}, {\"2\":\"3\"}]")).isFalse();
+ // missing key
+ assertThat(areSimilar("[{\"1\": \"3\"}, {\"2\":\"4\"}]", "[{\"1\": \"3\"}, {\"5\":\"10\"}]")).isFalse();
+ }
+
+ @Test
+ public void lenient_timezone() throws Exception {
+ // lenient mode by default
+ assertThat(new JsonComparison().isStrictTimezone()).isFalse();
+
+ // same instant, same timezone
+ assertThat(areSimilar("{\"foo\": \"2010-05-18T15:50:45+0100\"}", "{\"foo\": \"2010-05-18T15:50:45+0100\"}")).isTrue();
+
+ // same instant, but different timezone
+ assertThat(areSimilar("{\"foo\": \"2010-05-18T15:50:45+0100\"}", "{\"foo\": \"2010-05-18T18:50:45+0400\"}")).isTrue();
+
+ // different time
+ assertThat(areSimilar("{\"foo\": \"2010-05-18T15:50:45+0100\"}", "{\"foo\": \"2010-05-18T15:51:45+0100\"}")).isFalse();
+ }
+
+ @Test
+ public void strict_timezone() throws Exception {
+ assertThat(new JsonComparison().setStrictTimezone(true).isStrictTimezone()).isTrue();
+
+ // same instant, same timezone
+ assertThat(isSimilar_strict_timezone("{\"foo\": \"2010-05-18T15:50:45+0100\"}", "{\"foo\": \"2010-05-18T15:50:45+0100\"}")).isTrue();
+ assertThat(isSimilar_strict_timezone("[\"2010-05-18T15:50:45+0100\"]", "[\"2010-05-18T15:50:45+0100\"]")).isTrue();
+
+ // same instant, but different timezone
+ assertThat(isSimilar_strict_timezone("{\"foo\": \"2010-05-18T15:50:45+0100\"}", "{\"foo\": \"2010-05-18T18:50:45+0400\"}")).isFalse();
+
+ // different time
+ assertThat(isSimilar_strict_timezone("{\"foo\": \"2010-05-18T15:50:45+0100\"}", "{\"foo\": \"2010-05-18T15:51:45+0100\"}")).isFalse();
+ }
+
+ @Test
+ public void compare_doubles() throws Exception {
+ assertThat(areSimilar("{\"foo\": true}", "{\"foo\": false}")).isFalse();
+ assertThat(areSimilar("{\"foo\": true}", "{\"foo\": true}")).isTrue();
+ assertThat(areSimilar("{\"foo\": true}", "{\"foo\": \"true\"}")).isFalse();
+ assertThat(areSimilar("{\"foo\": true}", "{\"foo\": 1}")).isFalse();
+ }
+
+ @Test
+ public void compare_booleans() throws Exception {
+ assertThat(areSimilar("{\"foo\": 3.14}", "{\"foo\": 3.14000000}")).isTrue();
+ assertThat(areSimilar("{\"foo\": 3.14}", "{\"foo\": 3.1400001}")).isTrue();
+ }
+
+ private boolean areSimilar(String expected, String actual) {
+ return new JsonComparison().areSimilar(expected, actual);
+ }
+
+ private boolean isSimilar_strict_timezone(String expected, String actual) {
+ return new JsonComparison().setStrictTimezone(true).areSimilar(expected, actual);
+ }
+
+ private boolean isSimilar_strict_array_order(String expected, String actual) {
+ return new JsonComparison().setStrictArrayOrder(true).areSimilar(expected, actual);
+ }
+}
diff --git a/sonar-testing-harness/src/test/resources/org/sonar/test/JsonAssertTest/sample1.json b/sonar-testing-harness/src/test/resources/org/sonar/test/JsonAssertTest/sample1.json
new file mode 100644
index 00000000000..0967ef424bc
--- /dev/null
+++ b/sonar-testing-harness/src/test/resources/org/sonar/test/JsonAssertTest/sample1.json
@@ -0,0 +1 @@
+{}
diff --git a/sonar-testing-harness/src/test/resources/org/sonar/test/JsonAssertTest/sample2.json b/sonar-testing-harness/src/test/resources/org/sonar/test/JsonAssertTest/sample2.json
new file mode 100644
index 00000000000..fe51488c706
--- /dev/null
+++ b/sonar-testing-harness/src/test/resources/org/sonar/test/JsonAssertTest/sample2.json
@@ -0,0 +1 @@
+[]