Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CS304 Fixed issue #113 #140

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
55 changes: 34 additions & 21 deletions src/main/java/org/skyscreamer/jsonassert/JSONCompare.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
* 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 org.skyscreamer.jsonassert;

Expand All @@ -37,39 +37,51 @@ private static JSONComparator getComparatorForMode(JSONCompareMode mode) {
/**
* Compares JSON string provided to the expected JSON string using provided comparator, and returns the results of
* the comparison.
*
* @param expectedStr Expected JSON string
* @param actualStr JSON string to compare
* @param comparator Comparator to use
* @param actualStr JSON string to compare
* @param comparator Comparator to use
* @return result of the comparison
* @throws JSONException JSON parsing error
* @throws JSONException JSON parsing error
* @throws IllegalArgumentException when type of expectedStr doesn't match the type of actualStr
*/
public static JSONCompareResult compareJSON(String expectedStr, String actualStr, JSONComparator comparator)
throws JSONException {
SpecialCompareChange scc = new SpecialCompareChange();

expectedStr = scc.change(expectedStr);
actualStr = scc.change(actualStr);
Object expected = JSONParser.parseJSON(expectedStr);
Object actual = JSONParser.parseJSON(actualStr);
if ((expected instanceof JSONObject) && (actual instanceof JSONObject)) {
return compareJSON((JSONObject) expected, (JSONObject) actual, comparator);
}
else if ((expected instanceof JSONArray) && (actual instanceof JSONArray)) {
return compareJSON((JSONArray)expected, (JSONArray)actual, comparator);
}
else if (expected instanceof JSONString && actual instanceof JSONString) {
String eStrNoSpace = expectedStr.replaceAll(" ", "");
String aStrNoSpace = actualStr.replaceAll(" ", "");
if((expected instanceof JSONObject) && (actual instanceof JSONObject)){
if ( eStrNoSpace.charAt(0) != '{' || eStrNoSpace.charAt(eStrNoSpace.length() - 1) != '}') {
return new JSONCompareResult().fail("Invalid JSON object with extra character in head or tail in expected", expected, actual);
}else{
return compareJSON((JSONObject) expected, (JSONObject) actual, comparator);
}
} else if((expected instanceof JSONArray) && (actual instanceof JSONArray)){
if (aStrNoSpace.charAt(0) != '[' || aStrNoSpace.charAt(aStrNoSpace.length() - 1) != ']') {
return new JSONCompareResult().fail("Invalid JSON object with extra character in head or tail in actual", expected, actual);
}else{
return compareJSON((JSONArray) expected, (JSONArray) actual, comparator);
}
} else if (expected instanceof JSONString && actual instanceof JSONString) {
return compareJson((JSONString) expected, (JSONString) actual);
}
else if (expected instanceof JSONObject) {
} else if (expected instanceof JSONObject) {
return new JSONCompareResult().fail("", expected, actual);
}
else {
} else {
return new JSONCompareResult().fail("", expected, actual);
}
}

/**
/**
* Compares JSON object provided to the expected JSON object using provided comparator, and returns the results of
* the comparison.
* @param expected expected json object
* @param actual actual json object
*
* @param expected expected json object
* @param actual actual json object
* @param comparator comparator to use
* @return result of the comparison
* @throws JSONException JSON parsing error
Expand All @@ -82,8 +94,9 @@ public static JSONCompareResult compareJSON(JSONObject expected, JSONObject actu
/**
* Compares JSON object provided to the expected JSON object using provided comparator, and returns the results of
* the comparison.
* @param expected expected json array
* @param actual actual json array
*
* @param expected expected json array
* @param actual actual json array
* @param comparator comparator to use
* @return result of the comparison
* @throws JSONException JSON parsing error
Expand All @@ -106,7 +119,7 @@ public static JSONCompareResult compareJson(final JSONString expected, final JSO
final String expectedJson = expected.toJSONString();
final String actualJson = actual.toJSONString();
if (!expectedJson.equals(actualJson)) {
result.fail("");
result.fail("");
}
return result;
}
Expand Down
113 changes: 113 additions & 0 deletions src/main/java/org/skyscreamer/jsonassert/SpecialCompareChange.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package org.skyscreamer.jsonassert;

import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
* Class SpecialCompareChange
* Use to handle the out of bound number comparation
* @author Maijie Xie
* @version 1.0
* Created on 23/4/2021
*/



public class SpecialCompareChange {
public SpecialCompareChange() {
}
/**
* Find the JsonObject's number and replace the number which is out of bound to the string.
* @param expectedStr Expected JSON string
* @return result of the replacement
*/
public String change(String expectedStr) {
String regEx = ":\\s*([1-9]\\d*.\\d*|0\\.?\\d*[1-9]\\d*)\\s*}";
Pattern p = Pattern.compile(regEx);
Matcher exp = p.matcher(expectedStr);
ArrayList<String> exp_num = new ArrayList<String>();
while (exp.find()) {
exp_num.add(exp.group(0).replace(":", "").replaceAll(" ", "").replace("}", ""));
}
ArrayList<String> exp_newNum = pretreatBigNumber((ArrayList<String>) exp_num.clone());
return replaceNum(expectedStr, exp_num, exp_newNum);
}
/**
* Check the number in the JsonObject wither out of bound.
* @param num numbers find in the sonObject
* @return result of the num wither out of bound
*/
static ArrayList<String> pretreatBigNumber(ArrayList<String> num) {
ArrayList<String> pretreat = new ArrayList<String>();
for (String i : num) {
i = removeEndZero(i);
try {
if ((!(String.valueOf(Double.parseDouble(i)).equals(i))) && (!(String.valueOf(Long.parseLong(i)).equals(i)))) {
pretreat.add(i);
}
pretreat.add(i);
} catch (NumberFormatException e) {
i = "a" + i;
pretreat.add(i);
}
}
return pretreat;
}
/**
* Remove the zero at the end of the decimal point.
* @param num number find in the JsonObject
* @return result of the number after remove the zero at the end of the decimal point.
*/
static String removeEndZero(String num) {
if (!isInteger(num)) {
StringBuffer newNum = new StringBuffer(num);
for (int i = num.length() - 1; i >= 0; i--) {
if (num.charAt(i) != '0') {
if (i < num.length() - 1) {
if (num.charAt(i) != '.') {
newNum.replace(i + 1, num.length(), "");
}else{
newNum.replace(i, num.length(), "");
}
break;
} else {
break;
}
}
}
return newNum.toString();
} else {
return num;
}
}
/**
* replace number which is out of bound in the JasonObject as a string formate.
* @param str string of the JasonObject.
* @param num number need to replace as string.
* @param newNum strings the number need to replace to.
* @return result of the string after replace.
*/
static String replaceNum(String str, ArrayList<String> num, ArrayList<String> newNum) {
for (int i = 0; i < num.size(); i++) {
str = str.replace(num.get(i), newNum.get(i));
}
return str;
}
/**
* Judge whether the string is a number
* @param str The string in the JasonObject.
* @return result of whether the string is anumber
*/
public static boolean isInteger(String str) {

for (int i = str.length(); --i >= 0; ) {
if (!Character.isDigit(str.charAt(i))) {
return false;
}
}
return true;

}
}
73 changes: 73 additions & 0 deletions src/test/java/org/skyscreamer/jsonassert/BigNumberTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package org.skyscreamer.jsonassert;

import org.json.JSONException;
import org.junit.Test;

public class BigNumberTest {
// This test fails
@Test
public void testBigDecimalDifferent() throws JSONException {
JSONAssert.assertNotEquals(
"{ \"value\": 1234567890.1234567890123456 }",
"{ \"value\": 1234567890.12345678900000 }",
true
);

}


@Test
public void testBigDecimalEqual() throws JSONException {
JSONAssert.assertEquals(
"{ \"value\": 1234567890.1234567890123456 }",
"{ \"value\": 1234567890.1234567890123456 }",
true
);
}

@Test
public void testBigNumberDifferent() throws JSONException {
JSONAssert.assertNotEquals(
"{ \"value\": 12345678901234567890123456 }",
"{ \"value\": 12345678901234567800000000 }",
true
);
}

@Test
public void testBigNumberEqual() throws JSONException {
JSONAssert.assertEquals(
"{ \"value\": 12345678901234567890123456 }",
"{ \"value\": 12345678901234567890123456 }",
true
);
}

@Test
public void testNumberDemicalEqual() throws JSONException {
JSONAssert.assertEquals(
"{ \"value\": 12345678901234567890123456 }",
"{ \"value\": 12345678901234567890123456.0000000000000 }",
true
);
}

@Test
public void testSmallNumberDemicalEqual1() throws JSONException {
JSONAssert.assertEquals(
"{ \"value\": 1.23 }",
"{ \"value\": 1.2300000000 }",
true
);
}

@Test
public void testSmallNumberDemicalEqual2() throws JSONException {
JSONAssert.assertEquals(
"{ \"value\": 1 }",
"{ \"value\": 1.00000000 }",
true
);
}

}
63 changes: 63 additions & 0 deletions src/test/java/org/skyscreamer/jsonassert/JSONOverCharTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package org.skyscreamer.jsonassert;

import org.json.JSONException;
import org.junit.Test;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Assert;
import org.junit.Test;
import org.skyscreamer.jsonassert.comparator.CustomComparator;
import org.skyscreamer.jsonassert.comparator.JSONComparator;

import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.skyscreamer.jsonassert.JSONCompare.compareJSON;
import static org.skyscreamer.jsonassert.JSONCompareMode.LENIENT;
import static org.skyscreamer.jsonassert.JSONCompareMode.NON_EXTENSIBLE;

import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.skyscreamer.jsonassert.JSONCompare.compareJSON;
import static org.skyscreamer.jsonassert.JSONCompareMode.LENIENT;
import static org.skyscreamer.jsonassert.JSONCompareMode.NON_EXTENSIBLE;

import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.json.JSONException;
import org.junit.Test;
import org.junit.internal.matchers.TypeSafeMatcher;
public class JSONOverCharTest
{
//CS304 (manually written) Issue link: https://github.com/skyscreamer/JSONassert/issues/113
@Test
public void testWithObjectEmpty() throws JSONException {
JSONAssert.assertEquals("{}", "{}", JSONCompareMode.STRICT);
}
//CS304 (manually written) Issue link: https://github.com/skyscreamer/JSONassert/issues/113
@Test
public void testWithArrayEmpty() throws JSONException {
JSONAssert.assertEquals("[]", "[]", JSONCompareMode.STRICT);
}
//CS304 (manually written) Issue link: https://github.com/skyscreamer/JSONassert/issues/113
@Test(expected = AssertionError.class)
public void testWithArrayLeftWord() throws JSONException {
JSONAssert.assertEquals("[]", "[]a", LENIENT);
JSONAssert.assertEquals("[]b", "[]a", LENIENT);
JSONAssert.assertEquals("[]b", "[]a", LENIENT);
JSONAssert.assertEquals("[{'a': 1}]", "[{'a': 1}]a", LENIENT);
}
//CS304 (manually written) Issue link: https://github.com/skyscreamer/JSONassert/issues/113
@Test(expected = AssertionError.class)
public void testWithObjectLeftword() throws JSONException {
JSONAssert.assertEquals("{}", "{}a", LENIENT);
JSONAssert.assertEquals("{}b", "{}a", LENIENT);
JSONAssert.assertEquals("{}b", "a{}", LENIENT);
JSONAssert.assertEquals("{'a': 1}", "{'a': 1}a", LENIENT);
}

}