Skip to content

Commit

Permalink
Merge pull request stleary#58 from johnjaylward/SimplifyNumberWrap
Browse files Browse the repository at this point in the history
Adds tests for numbers
  • Loading branch information
stleary authored Aug 17, 2016
2 parents c400de3 + 0b1dbe9 commit 59761f6
Show file tree
Hide file tree
Showing 4 changed files with 339 additions and 2 deletions.
180 changes: 180 additions & 0 deletions src/test/java/org/json/junit/Fraction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
package org.json.junit;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;

/**
* basic fraction class, no frills.
* @author John Aylward
*
*/
public class Fraction extends Number implements Comparable<Fraction> {
/**
* serial id.
*/
private static final long serialVersionUID = 1L;

/**
* value as a big decimal.
*/
private final BigDecimal bigDecimal;

/**
* value of the denominator.
*/
private final BigInteger denominator;
/**
* value of the numerator.
*/
private final BigInteger numerator;

/**
* @param numerator
* numerator
* @param denominator
* denominator
*/
public Fraction(final BigInteger numerator, final BigInteger denominator) {
super();
if (numerator == null || denominator == null) {
throw new IllegalArgumentException("All values must be non-null");
}
if (denominator.compareTo(BigInteger.ZERO)==0) {
throw new IllegalArgumentException("Divide by zero");
}

final BigInteger n;
final BigInteger d;
// normalize fraction
if (denominator.signum()<0) {
n = numerator.negate();
d = denominator.negate();
} else {
n = numerator;
d = denominator;
}
this.numerator = n;
this.denominator = d;
if (n.compareTo(BigInteger.ZERO)==0) {
this.bigDecimal = BigDecimal.ZERO;
} else if (n.compareTo(d)==0) {// i.e. 4/4, 10/10
this.bigDecimal = BigDecimal.ONE;
} else {
this.bigDecimal = new BigDecimal(this.numerator).divide(new BigDecimal(this.denominator),
RoundingMode.HALF_EVEN);
}
}

/**
* @param numerator
* numerator
* @param denominator
* denominator
*/
public Fraction(final long numerator, final long denominator) {
this(BigInteger.valueOf(numerator),BigInteger.valueOf(denominator));
}

/**
* @return the decimal
*/
public BigDecimal bigDecimalValue() {
return this.bigDecimal;
}

@Override
public int compareTo(final Fraction o) {
// .equals call this, so no .equals compare allowed

// if they are the same reference, just return equals
if (this == o) {
return 0;
}

// if my denominators are already equal, just compare the numerators
if (this.denominator.compareTo(o.denominator)==0) {
return this.numerator.compareTo(o.numerator);
}

// get numerators of common denominators
// a x ay xb
// --- --- = ---- ----
// b y by yb
final BigInteger thisN = this.numerator.multiply(o.denominator);
final BigInteger otherN = o.numerator.multiply(this.denominator);

return thisN.compareTo(otherN);
}

@Override
public double doubleValue() {
return this.bigDecimal.doubleValue();
}

/**
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (this.getClass() != obj.getClass()) {
return false;
}
final Fraction other = (Fraction) obj;
return this.compareTo(other) == 0;
}

@Override
public float floatValue() {
return this.bigDecimal.floatValue();
}

/**
* @return the denominator
*/
public BigInteger getDenominator() {
return this.denominator;
}

/**
* @return the numerator
*/
public BigInteger getNumerator() {
return this.numerator;
}

/**
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (this.bigDecimal == null ? 0 : this.bigDecimal.hashCode());
return result;
}

@Override
public int intValue() {
return this.bigDecimal.intValue();
}

@Override
public long longValue() {
return this.bigDecimal.longValue();
}

/**
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return this.numerator + "/" + this.denominator;
}
}
51 changes: 49 additions & 2 deletions src/test/java/org/json/junit/JSONObjectTest.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package org.json.junit;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

Expand All @@ -20,6 +20,7 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

import org.json.CDL;
import org.json.JSONArray;
Expand Down Expand Up @@ -49,7 +50,7 @@ public void jsonObjectByNullBean() {
MyBean myBean = null;
new JSONObject(myBean);
}

/**
* A JSONObject can be created with no content
*/
Expand Down Expand Up @@ -165,6 +166,52 @@ public void verifyConstructor() {
expected.similar(jaObjObj));
}

/**
* Tests Number serialization.
*/
@Test
public void verifyNumberOutput(){
JSONObject jsonObject = new JSONObject(new MyNumberContainer());
String actual = jsonObject.toString();

// before wrapping of Number is allowed the number was converted as a bean
String expected = "{\"myNumber\":{\"number\":42}}";
//String expected = "{\"myNumber\":42}";
assertEquals("Not Equal", expected , actual);

// put handles objects differently than the constructor.
jsonObject = new JSONObject();
jsonObject.put("myNumber", new MyNumber());
actual = jsonObject.toString();
// the output is the toString of the number as a number.
expected = "{\"myNumber\":42}";
assertEquals("Not Equal", expected , actual);

jsonObject = new JSONObject(Collections.singletonMap("myNumber", new AtomicInteger(42)));
actual = jsonObject.toString();
// before wrapping of Number is allowed the number was converted to a string
expected = "{\"myNumber\":\"42\"}";
assertEquals("Not Equal", expected , actual);

// put handles objects differently than the constructor.
jsonObject = new JSONObject();
jsonObject.put("myNumber", new AtomicInteger(42));
actual = jsonObject.toString();
expected = "{\"myNumber\":42}";
assertEquals("Not Equal", expected , actual);

// verify Fraction output
jsonObject = new JSONObject(Collections.singletonMap("myNumber", new Fraction(4,2)));
assertEquals("Numerator", BigInteger.valueOf(4) , jsonObject.query("/myNumber/numerator"));
assertEquals("Denominator", BigInteger.valueOf(2) , jsonObject.query("/myNumber/denominator"));

jsonObject = new JSONObject();
jsonObject.put("myNumber", new Fraction(4,2));
actual = jsonObject.toString();
expected = "{\"myNumber\":4/2}"; // this is NOT valid JSON!!!!!!!!!!! BUG!
assertEquals("Not Equal", expected , actual);
}

/**
* Verifies that the put Collection has backwards compatability with RAW types pre-java5.
*/
Expand Down
97 changes: 97 additions & 0 deletions src/test/java/org/json/junit/MyNumber.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package org.json.junit;

import java.math.BigDecimal;

/**
* Number override for testing. Number overrides should always override
* toString, hashCode, and Equals.
*
* @see <a
* href="https://docs.oracle.com/javase/tutorial/java/data/numberclasses.html">The
* Numbers Classes</a>
* @see <a
* href="https://docs.oracle.com/javase/tutorial/java/data/numberformat.html">Formatting
* Numeric Print Output</a>
*
* @author John Aylward
*/
public class MyNumber extends Number {
private Number number = BigDecimal.valueOf(42);
/**
*/
private static final long serialVersionUID = 1L;

/**
* @return number!
*/
public Number getNumber() {
return this.number;
}

@Override
public int intValue() {
return getNumber().intValue();
}

@Override
public long longValue() {
return getNumber().longValue();
}

@Override
public float floatValue() {
return getNumber().floatValue();
}

@Override
public double doubleValue() {
return getNumber().doubleValue();
}

/* (non-Javadoc)
* @see java.lang.Object#toString()
*
* Number overrides should in general always override the toString method.
*/
@Override
public String toString() {
return getNumber().toString();
}

/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((this.number == null) ? 0 : this.number.hashCode());
return result;
}

/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof MyNumber)) {
return false;
}
MyNumber other = (MyNumber) obj;
if (this.number == null) {
if (other.number != null) {
return false;
}
} else if (!this.number.equals(other.number)) {
return false;
}
return true;
}

}
13 changes: 13 additions & 0 deletions src/test/java/org/json/junit/MyNumberContainer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.json.junit;

/**
* Class that holds our MyNumber override as a property.
* @author John Aylward
*/
public class MyNumberContainer {
private MyNumber myNumber = new MyNumber();
/**
* @return a MyNumber.
*/
public Number getMyNumber() {return this.myNumber;}
}

0 comments on commit 59761f6

Please sign in to comment.