1 /* 2 * Copyright (C) 2020 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 android.util 18 19 import androidx.test.filters.LargeTest 20 import androidx.test.filters.SmallTest 21 import androidx.test.runner.AndroidJUnit4 22 import org.junit.Assert.assertEquals 23 import org.junit.Test 24 import org.junit.runner.RunWith 25 import org.mockito.Mockito.mock 26 import kotlin.math.abs 27 import kotlin.math.min 28 import kotlin.math.roundToInt 29 30 @RunWith(AndroidJUnit4::class) 31 class TypedValueTest { 32 @LargeTest 33 @Test testFloatToComplexnull34 fun testFloatToComplex() { 35 fun assertRoundTripEquals(value: Float, expectedRadix: Int? = null) { 36 val complex = TypedValue.floatToComplex(value) 37 // Ensure values are accurate within .5% of the original value and within .5 38 val delta = min(abs(value) / 512f, .5f) 39 assertEquals(value, TypedValue.complexToFloat(complex), delta) 40 // If expectedRadix is provided, validate it 41 if (expectedRadix != null) { 42 val actualRadix = ((complex shr TypedValue.COMPLEX_RADIX_SHIFT) 43 and TypedValue.COMPLEX_RADIX_MASK) 44 assertEquals("Incorrect radix for $value:", expectedRadix, actualRadix) 45 } 46 } 47 48 assertRoundTripEquals(0f, TypedValue.COMPLEX_RADIX_23p0) 49 50 assertRoundTripEquals(0.5f, TypedValue.COMPLEX_RADIX_0p23) 51 assertRoundTripEquals(0.05f, TypedValue.COMPLEX_RADIX_0p23) 52 assertRoundTripEquals(0.005f, TypedValue.COMPLEX_RADIX_0p23) 53 assertRoundTripEquals(0.0005f, TypedValue.COMPLEX_RADIX_0p23) 54 assertRoundTripEquals(0.00005f, TypedValue.COMPLEX_RADIX_0p23) 55 56 assertRoundTripEquals(1.5f, TypedValue.COMPLEX_RADIX_8p15) 57 assertRoundTripEquals(10.5f, TypedValue.COMPLEX_RADIX_8p15) 58 assertRoundTripEquals(100.5f, TypedValue.COMPLEX_RADIX_8p15) 59 assertRoundTripEquals(255.5f, TypedValue.COMPLEX_RADIX_8p15) // 2^8 - .5 60 61 assertRoundTripEquals(256.5f, TypedValue.COMPLEX_RADIX_16p7) // 2^8 + .5 62 assertRoundTripEquals(1000.5f, TypedValue.COMPLEX_RADIX_16p7) 63 assertRoundTripEquals(10000.5f, TypedValue.COMPLEX_RADIX_16p7) 64 assertRoundTripEquals(65535.5f, TypedValue.COMPLEX_RADIX_16p7) // 2^16 - .5 65 66 assertRoundTripEquals(65536.5f, TypedValue.COMPLEX_RADIX_23p0) // 2^16 + .5 67 assertRoundTripEquals(100000.5f, TypedValue.COMPLEX_RADIX_23p0) 68 assertRoundTripEquals(1000000.5f, TypedValue.COMPLEX_RADIX_23p0) 69 assertRoundTripEquals(8388607.2f, TypedValue.COMPLEX_RADIX_23p0) // 2^23 -.8 70 71 assertRoundTripEquals(-0.5f, TypedValue.COMPLEX_RADIX_0p23) 72 assertRoundTripEquals(-0.05f, TypedValue.COMPLEX_RADIX_0p23) 73 assertRoundTripEquals(-0.005f, TypedValue.COMPLEX_RADIX_0p23) 74 assertRoundTripEquals(-0.0005f, TypedValue.COMPLEX_RADIX_0p23) 75 assertRoundTripEquals(-0.00005f, TypedValue.COMPLEX_RADIX_0p23) 76 77 assertRoundTripEquals(-1.5f, TypedValue.COMPLEX_RADIX_8p15) 78 assertRoundTripEquals(-10.5f, TypedValue.COMPLEX_RADIX_8p15) 79 assertRoundTripEquals(-100.5f, TypedValue.COMPLEX_RADIX_8p15) 80 assertRoundTripEquals(-255.5f, TypedValue.COMPLEX_RADIX_8p15) // -2^8 + .5 81 82 // NOTE: -256.5f fits in COMPLEX_RADIX_8p15 but is stored with COMPLEX_RADIX_16p7 for 83 // simplicity of the algorithm. However, it's better not to enforce that with a test. 84 assertRoundTripEquals(-257.5f, TypedValue.COMPLEX_RADIX_16p7) // -2^8 - 1.5 85 assertRoundTripEquals(-1000.5f, TypedValue.COMPLEX_RADIX_16p7) 86 assertRoundTripEquals(-10000.5f, TypedValue.COMPLEX_RADIX_16p7) 87 assertRoundTripEquals(-65535.5f, TypedValue.COMPLEX_RADIX_16p7) // -2^16 + .5 88 89 // NOTE: -65536.5f fits in COMPLEX_RADIX_16p7 but is stored with COMPLEX_RADIX_23p0 for 90 // simplicity of the algorithm. However, it's better not to enforce that with a test. 91 assertRoundTripEquals(-65537.5f, TypedValue.COMPLEX_RADIX_23p0) // -2^16 - 1.5 92 assertRoundTripEquals(-100000.5f, TypedValue.COMPLEX_RADIX_23p0) 93 assertRoundTripEquals(-1000000.5f, TypedValue.COMPLEX_RADIX_23p0) 94 assertRoundTripEquals(-8388607.5f, TypedValue.COMPLEX_RADIX_23p0) // 2^23 -.5 95 96 // Test for every integer value in the range... 97 for (i: Int in -(1 shl 23) until (1 shl 23)) { 98 // ... that true integers are stored as the precise integer 99 assertRoundTripEquals(i.toFloat(), TypedValue.COMPLEX_RADIX_23p0) 100 // ... that values round up when just below an integer 101 assertRoundTripEquals(i - .1f) 102 // ... that values round down when just above an integer 103 assertRoundTripEquals(i + .1f) 104 } 105 } 106 107 @SmallTest 108 @Test(expected = IllegalArgumentException::class) testFloatToComplex_failsIfValueTooLargenull109 fun testFloatToComplex_failsIfValueTooLarge() { 110 TypedValue.floatToComplex(8388607.5f) // 2^23 - .5 111 } 112 113 @SmallTest 114 @Test(expected = IllegalArgumentException::class) testFloatToComplex_failsIfValueTooSmallnull115 fun testFloatToComplex_failsIfValueTooSmall() { 116 TypedValue.floatToComplex(8388608.5f) // -2^23 - .5 117 } 118 119 @LargeTest 120 @Test testIntToComplexnull121 fun testIntToComplex() { 122 // Validates every single valid value 123 for (value: Int in -(1 shl 23) until (1 shl 23)) { 124 assertEquals(value.toFloat(), TypedValue.complexToFloat(TypedValue.intToComplex(value))) 125 } 126 } 127 128 @SmallTest 129 @Test(expected = IllegalArgumentException::class) testIntToComplex_failsIfValueTooLargenull130 fun testIntToComplex_failsIfValueTooLarge() { 131 TypedValue.intToComplex(0x800000) 132 } 133 134 @SmallTest 135 @Test(expected = IllegalArgumentException::class) testIntToComplex_failsIfValueTooSmallnull136 fun testIntToComplex_failsIfValueTooSmall() { 137 TypedValue.intToComplex(-0x800001) 138 } 139 140 @SmallTest 141 @Test testCreateComplexDimension_appliesUnitsnull142 fun testCreateComplexDimension_appliesUnits() { 143 val metrics: DisplayMetrics = mock(DisplayMetrics::class.java) 144 metrics.density = 3.25f 145 146 val height = 52 * metrics.density 147 val widthFloat = height * 16 / 9 148 val widthDimen = TypedValue.createComplexDimension( 149 widthFloat / metrics.density, 150 TypedValue.COMPLEX_UNIT_DIP 151 ) 152 val widthPx = TypedValue.complexToDimensionPixelSize(widthDimen, metrics) 153 assertEquals(widthFloat.roundToInt(), widthPx) 154 } 155 }