Home | History | Annotate | Download | only in unit
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.mediaframeworktest.unit;
     18 
     19 import android.test.suitebuilder.annotation.SmallTest;
     20 import android.util.Rational;
     21 
     22 import java.io.ByteArrayInputStream;
     23 import java.io.ByteArrayOutputStream;
     24 import java.io.IOException;
     25 import java.io.InvalidObjectException;
     26 import java.io.ObjectInputStream;
     27 import java.io.ObjectOutputStream;
     28 import java.io.Serializable;
     29 import java.lang.reflect.Field;
     30 
     31 import static android.util.Rational.*;
     32 
     33 /**
     34  * <pre>
     35  * adb shell am instrument \
     36  *      -e class 'com.android.mediaframeworktest.unit.RationalTest' \
     37  *      -w com.android.mediaframeworktest/.MediaFrameworkUnitTestRunner
     38  * </pre>
     39  */
     40 public class RationalTest extends junit.framework.TestCase {
     41 
     42     /** (1,1) */
     43     private static final Rational UNIT = new Rational(1, 1);
     44 
     45     /**
     46      * Test @hide greatest common divisior functionality that cannot be tested in CTS.
     47      */
     48     @SmallTest
     49     public void testGcd() {
     50         assertEquals(1, Rational.gcd(1, 2));
     51         assertEquals(1, Rational.gcd(2, 3));
     52         assertEquals(78, Rational.gcd(5*78, 7*78));
     53         assertEquals(1, Rational.gcd(-1, 2));
     54         assertEquals(1, Rational.gcd(-2, 3));
     55     }
     56 
     57     @SmallTest
     58     public void testConstructor() {
     59 
     60         // Simple case
     61         Rational r = new Rational(1, 2);
     62         assertEquals(1, r.getNumerator());
     63         assertEquals(2, r.getDenominator());
     64 
     65         // Denominator negative
     66         r = new Rational(-1, 2);
     67         assertEquals(-1, r.getNumerator());
     68         assertEquals(2, r.getDenominator());
     69 
     70         // Numerator negative
     71         r = new Rational(1, -2);
     72         assertEquals(-1, r.getNumerator());
     73         assertEquals(2, r.getDenominator());
     74 
     75         // Both negative
     76         r = new Rational(-1, -2);
     77         assertEquals(1, r.getNumerator());
     78         assertEquals(2, r.getDenominator());
     79 
     80         // Infinity.
     81         r = new Rational(1, 0);
     82         assertEquals(1, r.getNumerator());
     83         assertEquals(0, r.getDenominator());
     84 
     85         // Negative infinity.
     86         r = new Rational(-1, 0);
     87         assertEquals(-1, r.getNumerator());
     88         assertEquals(0, r.getDenominator());
     89 
     90         // NaN.
     91         r = new Rational(0, 0);
     92         assertEquals(0, r.getNumerator());
     93         assertEquals(0, r.getDenominator());
     94     }
     95 
     96     @SmallTest
     97     public void testEquals() {
     98         Rational r = new Rational(1, 2);
     99         assertEquals(1, r.getNumerator());
    100         assertEquals(2, r.getDenominator());
    101 
    102         assertEquals(r, r);
    103         assertFalse(r.equals(null));
    104         assertFalse(r.equals(new Object()));
    105 
    106         Rational twoThirds = new Rational(2, 3);
    107         assertFalse(r.equals(twoThirds));
    108         assertFalse(twoThirds.equals(r));
    109 
    110         Rational fourSixths = new Rational(4, 6);
    111         assertEquals(twoThirds, fourSixths);
    112         assertEquals(fourSixths, twoThirds);
    113 
    114         Rational moreComplicated = new Rational(5*6*7*8*9, 1*2*3*4*5);
    115         Rational moreComplicated2 = new Rational(5*6*7*8*9*78, 1*2*3*4*5*78);
    116         assertEquals(moreComplicated, moreComplicated2);
    117         assertEquals(moreComplicated2, moreComplicated);
    118 
    119         // Ensure negatives are fine
    120         twoThirds = new Rational(-2, 3);
    121         fourSixths = new Rational(-4, 6);
    122         assertEquals(twoThirds, fourSixths);
    123         assertEquals(fourSixths, twoThirds);
    124 
    125         moreComplicated = new Rational(-5*6*7*8*9, 1*2*3*4*5);
    126         moreComplicated2 = new Rational(-5*6*7*8*9*78, 1*2*3*4*5*78);
    127         assertEquals(moreComplicated, moreComplicated2);
    128         assertEquals(moreComplicated2, moreComplicated);
    129 
    130         // Zero is always equal to itself
    131         Rational zero2 = new Rational(0, 100);
    132         assertEquals(ZERO, zero2);
    133         assertEquals(zero2, ZERO);
    134 
    135         // NaN is always equal to itself
    136         Rational nan = NaN;
    137         Rational nan2 = new Rational(0, 0);
    138         assertTrue(nan.equals(nan));
    139         assertTrue(nan.equals(nan2));
    140         assertTrue(nan2.equals(nan));
    141         assertFalse(nan.equals(r));
    142         assertFalse(r.equals(nan));
    143 
    144         // Infinities of the same sign are equal.
    145         Rational posInf = POSITIVE_INFINITY;
    146         Rational posInf2 = new Rational(2, 0);
    147         Rational negInf = NEGATIVE_INFINITY;
    148         Rational negInf2 = new Rational(-2, 0);
    149         assertEquals(posInf, posInf);
    150         assertEquals(negInf, negInf);
    151         assertEquals(posInf, posInf2);
    152         assertEquals(negInf, negInf2);
    153 
    154         // Infinities aren't equal to anything else.
    155         assertFalse(posInf.equals(negInf));
    156         assertFalse(negInf.equals(posInf));
    157         assertFalse(negInf.equals(r));
    158         assertFalse(posInf.equals(r));
    159         assertFalse(r.equals(negInf));
    160         assertFalse(r.equals(posInf));
    161         assertFalse(posInf.equals(nan));
    162         assertFalse(negInf.equals(nan));
    163         assertFalse(nan.equals(posInf));
    164         assertFalse(nan.equals(negInf));
    165     }
    166 
    167     @SmallTest
    168     public void testReduction() {
    169         Rational moreComplicated = new Rational(5 * 78, 7 * 78);
    170         assertEquals(new Rational(5, 7), moreComplicated);
    171         assertEquals(5, moreComplicated.getNumerator());
    172         assertEquals(7, moreComplicated.getDenominator());
    173 
    174         Rational posInf = new Rational(5, 0);
    175         assertEquals(1, posInf.getNumerator());
    176         assertEquals(0, posInf.getDenominator());
    177         assertEquals(POSITIVE_INFINITY, posInf);
    178 
    179         Rational negInf = new Rational(-100, 0);
    180         assertEquals(-1, negInf.getNumerator());
    181         assertEquals(0, negInf.getDenominator());
    182         assertEquals(NEGATIVE_INFINITY, negInf);
    183 
    184         Rational zero = new Rational(0, -100);
    185         assertEquals(0, zero.getNumerator());
    186         assertEquals(1, zero.getDenominator());
    187         assertEquals(ZERO, zero);
    188 
    189         Rational flipSigns = new Rational(1, -1);
    190         assertEquals(-1, flipSigns.getNumerator());
    191         assertEquals(1, flipSigns.getDenominator());
    192 
    193         Rational flipAndReduce = new Rational(100, -200);
    194         assertEquals(-1, flipAndReduce.getNumerator());
    195         assertEquals(2, flipAndReduce.getDenominator());
    196     }
    197 
    198     @SmallTest
    199     public void testCompareTo() {
    200         // unit is equal to itself
    201         assertCompareEquals(UNIT, new Rational(1, 1));
    202 
    203         // NaN is greater than anything but NaN
    204         assertCompareEquals(NaN, new Rational(0, 0));
    205         assertGreaterThan(NaN, UNIT);
    206         assertGreaterThan(NaN, POSITIVE_INFINITY);
    207         assertGreaterThan(NaN, NEGATIVE_INFINITY);
    208         assertGreaterThan(NaN, ZERO);
    209 
    210         // Positive infinity is greater than any other non-NaN
    211         assertCompareEquals(POSITIVE_INFINITY, new Rational(1, 0));
    212         assertGreaterThan(POSITIVE_INFINITY, UNIT);
    213         assertGreaterThan(POSITIVE_INFINITY, NEGATIVE_INFINITY);
    214         assertGreaterThan(POSITIVE_INFINITY, ZERO);
    215 
    216         // Negative infinity is smaller than any other non-NaN
    217         assertCompareEquals(NEGATIVE_INFINITY, new Rational(-1, 0));
    218         assertLessThan(NEGATIVE_INFINITY, UNIT);
    219         assertLessThan(NEGATIVE_INFINITY, POSITIVE_INFINITY);
    220         assertLessThan(NEGATIVE_INFINITY, ZERO);
    221 
    222         // A finite number with the same denominator is trivially comparable
    223         assertGreaterThan(new Rational(3, 100), new Rational(1, 100));
    224         assertGreaterThan(new Rational(3, 100), ZERO);
    225 
    226         // Compare finite numbers with different divisors
    227         assertGreaterThan(new Rational(5, 25), new Rational(1, 10));
    228         assertGreaterThan(new Rational(5, 25), ZERO);
    229 
    230         // Compare finite numbers with different signs
    231         assertGreaterThan(new Rational(5, 25), new Rational(-1, 10));
    232         assertLessThan(new Rational(-5, 25), ZERO);
    233     }
    234 
    235     @SmallTest
    236     public void testConvenienceMethods() {
    237         // isFinite
    238         assertFinite(ZERO, true);
    239         assertFinite(NaN, false);
    240         assertFinite(NEGATIVE_INFINITY, false);
    241         assertFinite(POSITIVE_INFINITY, false);
    242         assertFinite(UNIT, true);
    243 
    244         // isInfinite
    245         assertInfinite(ZERO, false);
    246         assertInfinite(NaN, false);
    247         assertInfinite(NEGATIVE_INFINITY, true);
    248         assertInfinite(POSITIVE_INFINITY, true);
    249         assertInfinite(UNIT, false);
    250 
    251         // isNaN
    252         assertNaN(ZERO, false);
    253         assertNaN(NaN, true);
    254         assertNaN(NEGATIVE_INFINITY, false);
    255         assertNaN(POSITIVE_INFINITY, false);
    256         assertNaN(UNIT, false);
    257 
    258         // isZero
    259         assertZero(ZERO, true);
    260         assertZero(NaN, false);
    261         assertZero(NEGATIVE_INFINITY, false);
    262         assertZero(POSITIVE_INFINITY, false);
    263         assertZero(UNIT, false);
    264     }
    265 
    266     @SmallTest
    267     public void testValueConversions() {
    268         // Unit, simple case
    269         assertValueEquals(UNIT, 1.0f);
    270         assertValueEquals(UNIT, 1.0);
    271         assertValueEquals(UNIT, 1L);
    272         assertValueEquals(UNIT, 1);
    273         assertValueEquals(UNIT, (short)1);
    274 
    275         // Zero, simple case
    276         assertValueEquals(ZERO, 0.0f);
    277         assertValueEquals(ZERO, 0.0);
    278         assertValueEquals(ZERO, 0L);
    279         assertValueEquals(ZERO, 0);
    280         assertValueEquals(ZERO, (short)0);
    281 
    282         // NaN is 0 for integers, not-a-number for floating point
    283         assertValueEquals(NaN, Float.NaN);
    284         assertValueEquals(NaN, Double.NaN);
    285         assertValueEquals(NaN, 0L);
    286         assertValueEquals(NaN, 0);
    287         assertValueEquals(NaN, (short)0);
    288 
    289         // Positive infinity, saturates upwards for integers
    290         assertValueEquals(POSITIVE_INFINITY, Float.POSITIVE_INFINITY);
    291         assertValueEquals(POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
    292         assertValueEquals(POSITIVE_INFINITY, Long.MAX_VALUE);
    293         assertValueEquals(POSITIVE_INFINITY, Integer.MAX_VALUE);
    294         assertValueEquals(POSITIVE_INFINITY, (short)-1);
    295 
    296         // Negative infinity, saturates downwards for integers
    297         assertValueEquals(NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY);
    298         assertValueEquals(NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY);
    299         assertValueEquals(NEGATIVE_INFINITY, Long.MIN_VALUE);
    300         assertValueEquals(NEGATIVE_INFINITY, Integer.MIN_VALUE);
    301         assertValueEquals(NEGATIVE_INFINITY, (short)0);
    302 
    303         // Normal finite values, round down for integers
    304         final Rational oneQuarter = new Rational(1, 4);
    305         assertValueEquals(oneQuarter, 1.0f / 4.0f);
    306         assertValueEquals(oneQuarter, 1.0 / 4.0);
    307         assertValueEquals(oneQuarter, 0L);
    308         assertValueEquals(oneQuarter, 0);
    309         assertValueEquals(oneQuarter, (short)0);
    310 
    311         final Rational nineFifths = new Rational(9, 5);
    312         assertValueEquals(nineFifths, 9.0f / 5.0f);
    313         assertValueEquals(nineFifths, 9.0 / 5.0);
    314         assertValueEquals(nineFifths, 1L);
    315         assertValueEquals(nineFifths, 1);
    316         assertValueEquals(nineFifths, (short)1);
    317 
    318         final Rational negativeHundred = new Rational(-1000, 10);
    319         assertValueEquals(negativeHundred, -100.f / 1.f);
    320         assertValueEquals(negativeHundred, -100.0 / 1.0);
    321         assertValueEquals(negativeHundred, -100L);
    322         assertValueEquals(negativeHundred, -100);
    323         assertValueEquals(negativeHundred, (short)-100);
    324 
    325         // Short truncates if the result is too large
    326         assertValueEquals(new Rational(Integer.MAX_VALUE, 1), (short)Integer.MAX_VALUE);
    327         assertValueEquals(new Rational(0x00FFFFFF, 1), (short)0x00FFFFFF);
    328         assertValueEquals(new Rational(0x00FF00FF, 1), (short)0x00FF00FF);
    329     }
    330 
    331     @SmallTest
    332     public void testSerialize() throws ClassNotFoundException, IOException {
    333         /*
    334          * Check correct [de]serialization
    335          */
    336         assertEqualsAfterSerializing(ZERO);
    337         assertEqualsAfterSerializing(NaN);
    338         assertEqualsAfterSerializing(NEGATIVE_INFINITY);
    339         assertEqualsAfterSerializing(POSITIVE_INFINITY);
    340         assertEqualsAfterSerializing(UNIT);
    341         assertEqualsAfterSerializing(new Rational(100, 200));
    342         assertEqualsAfterSerializing(new Rational(-100, 200));
    343         assertEqualsAfterSerializing(new Rational(5, 1));
    344         assertEqualsAfterSerializing(new Rational(Integer.MAX_VALUE, Integer.MIN_VALUE));
    345 
    346         /*
    347          * Check bad deserialization fails
    348          */
    349         try {
    350             Rational badZero = createIllegalRational(0, 100); // [0, 100] , should be [0, 1]
    351             Rational results = serializeRoundTrip(badZero);
    352             fail("Deserializing " + results + " should not have succeeded");
    353         } catch (InvalidObjectException e) {
    354             // OK
    355         }
    356 
    357         try {
    358             Rational badPosInfinity = createIllegalRational(100, 0); // [100, 0] , should be [1, 0]
    359             Rational results = serializeRoundTrip(badPosInfinity);
    360             fail("Deserializing " + results + " should not have succeeded");
    361         } catch (InvalidObjectException e) {
    362             // OK
    363         }
    364 
    365         try {
    366             Rational badNegInfinity =
    367                     createIllegalRational(-100, 0); // [-100, 0] , should be [-1, 0]
    368             Rational results = serializeRoundTrip(badNegInfinity);
    369             fail("Deserializing " + results + " should not have succeeded");
    370         } catch (InvalidObjectException e) {
    371             // OK
    372         }
    373 
    374         try {
    375             Rational badReduced = createIllegalRational(2, 4); // [2,4] , should be [1, 2]
    376             Rational results = serializeRoundTrip(badReduced);
    377             fail("Deserializing " + results + " should not have succeeded");
    378         } catch (InvalidObjectException e) {
    379             // OK
    380         }
    381 
    382         try {
    383             Rational badReducedNeg = createIllegalRational(-2, 4); // [-2, 4] should be [-1, 2]
    384             Rational results = serializeRoundTrip(badReducedNeg);
    385             fail("Deserializing " + results + " should not have succeeded");
    386         } catch (InvalidObjectException e) {
    387             // OK
    388         }
    389     }
    390 
    391     private static void assertValueEquals(Rational object, float expected) {
    392         assertEquals("Checking floatValue() for " + object + ";",
    393                 expected, object.floatValue());
    394     }
    395 
    396     private static void assertValueEquals(Rational object, double expected) {
    397         assertEquals("Checking doubleValue() for " + object + ";",
    398                 expected, object.doubleValue());
    399     }
    400 
    401     private static void assertValueEquals(Rational object, long expected) {
    402         assertEquals("Checking longValue() for " + object + ";",
    403                 expected, object.longValue());
    404     }
    405 
    406     private static void assertValueEquals(Rational object, int expected) {
    407         assertEquals("Checking intValue() for " + object + ";",
    408                 expected, object.intValue());
    409     }
    410 
    411     private static void assertValueEquals(Rational object, short expected) {
    412         assertEquals("Checking shortValue() for " + object + ";",
    413                 expected, object.shortValue());
    414     }
    415 
    416     private static void assertFinite(Rational object, boolean expected) {
    417         assertAction("finite", object, expected, object.isFinite());
    418     }
    419 
    420     private static void assertInfinite(Rational object, boolean expected) {
    421         assertAction("infinite", object, expected, object.isInfinite());
    422     }
    423 
    424     private static void assertNaN(Rational object, boolean expected) {
    425         assertAction("NaN", object, expected, object.isNaN());
    426     }
    427 
    428     private static void assertZero(Rational object, boolean expected) {
    429         assertAction("zero", object, expected, object.isZero());
    430     }
    431 
    432     private static <T> void assertAction(String action, T object, boolean expected,
    433             boolean actual) {
    434         String expectedMessage = expected ? action : ("not " + action);
    435         assertEquals("Expected " + object + " to be " + expectedMessage,
    436                 expected, actual);
    437     }
    438 
    439     private static <T extends Comparable<? super T>> void assertLessThan(T left, T right) {
    440         assertTrue("Expected (LR) left " + left + " to be less than right " + right,
    441                 left.compareTo(right) < 0);
    442         assertTrue("Expected (RL) left " + left + " to be less than right " + right,
    443                 right.compareTo(left) > 0);
    444     }
    445 
    446     private static <T extends Comparable<? super T>> void assertGreaterThan(T left, T right) {
    447         assertTrue("Expected (LR) left " + left + " to be greater than right " + right,
    448                 left.compareTo(right) > 0);
    449         assertTrue("Expected (RL) left " + left + " to be greater than right " + right,
    450                 right.compareTo(left) < 0);
    451     }
    452 
    453     private static <T extends Comparable<? super T>> void assertCompareEquals(T left, T right) {
    454         assertTrue("Expected (LR) left " + left + " to be compareEquals to right " + right,
    455                 left.compareTo(right) == 0);
    456         assertTrue("Expected (RL) left " + left + " to be compareEquals to right " + right,
    457                 right.compareTo(left) == 0);
    458     }
    459 
    460     private static <T extends Serializable> byte[] serialize(T obj) throws IOException {
    461         ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
    462         try (ObjectOutputStream objectStream = new ObjectOutputStream(byteStream)) {
    463             objectStream.writeObject(obj);
    464         }
    465         return byteStream.toByteArray();
    466     }
    467 
    468     private static <T extends Serializable> T deserialize(byte[] array, Class<T> klass)
    469             throws IOException, ClassNotFoundException {
    470         ByteArrayInputStream bais = new ByteArrayInputStream(array);
    471         ObjectInputStream ois = new ObjectInputStream(bais);
    472         Object obj = ois.readObject();
    473         return klass.cast(obj);
    474     }
    475 
    476     @SuppressWarnings("unchecked")
    477     private static <T extends Serializable> T serializeRoundTrip(T obj)
    478             throws IOException, ClassNotFoundException {
    479         Class<T> klass = (Class<T>) obj.getClass();
    480         byte[] arr = serialize(obj);
    481         T serialized = deserialize(arr, klass);
    482         return serialized;
    483     }
    484 
    485     private static <T extends Serializable> void assertEqualsAfterSerializing(T obj)
    486             throws ClassNotFoundException, IOException {
    487         T serialized = serializeRoundTrip(obj);
    488         assertEquals("Expected values to be equal after serialization round-trip", obj, serialized);
    489     }
    490 
    491     private static Rational createIllegalRational(int numerator, int denominator) {
    492         Rational r = new Rational(numerator, denominator);
    493         mutateField(r, "mNumerator", numerator);
    494         mutateField(r, "mDenominator", denominator);
    495         return r;
    496     }
    497 
    498     private static <T> void mutateField(T object, String name, int value) {
    499         try {
    500             Field f = object.getClass().getDeclaredField(name);
    501             f.setAccessible(true);
    502             f.set(object, value);
    503         } catch (NoSuchFieldException e) {
    504             throw new AssertionError(e);
    505         } catch (IllegalAccessException e) {
    506             throw new AssertionError(e);
    507         } catch (IllegalArgumentException e) {
    508             throw new AssertionError(e);
    509         }
    510     }
    511 }
    512