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 com.android.timezone.location.storage.tzs2range;
18 
19 import static com.android.timezone.location.storage.s2.S2Support.cellId;
20 import static com.android.timezone.location.storage.testing.MoreAsserts.assertThrows;
21 
22 import static org.junit.Assert.assertEquals;
23 
24 import org.junit.Test;
25 
26 /** Tests for {@link TzS2RangeFileFormat}. */
27 public class TzS2RangeFileFormatTest {
28 
29     @Test
accessors()30     public void accessors() {
31         int s2Level = 12;
32         int prefixBitCount = 11;
33         int suffixBitCount = 16;
34         int suffixTableBlockIdOffset = 5;
35         int tableEntryBitCount = 24;
36         int entryRangeLengthBitCount = 5;
37         TzS2RangeFileFormat tzS2RangeFileFormat = new TzS2RangeFileFormat(s2Level, prefixBitCount,
38                 suffixBitCount, suffixTableBlockIdOffset, tableEntryBitCount,
39                 entryRangeLengthBitCount);
40 
41         assertEquals(s2Level, tzS2RangeFileFormat.getS2Level());
42         assertEquals(prefixBitCount, tzS2RangeFileFormat.getPrefixBitCount());
43         assertEquals(suffixBitCount, tzS2RangeFileFormat.getSuffixBitCount());
44         assertEquals(suffixTableBlockIdOffset, tzS2RangeFileFormat.getSuffixTableBlockIdOffset());
45         assertEquals(tableEntryBitCount, tzS2RangeFileFormat.getTableEntryBitCount());
46         assertEquals(entryRangeLengthBitCount,
47                 tzS2RangeFileFormat.getTableEntryRangeLengthBitCount());
48 
49         // Derived values
50         assertEquals((6 * intPow2(prefixBitCount - 3)) - 1,
51                 tzS2RangeFileFormat.getMaxPrefixValue());
52         assertEquals(maxValForBits(suffixBitCount), tzS2RangeFileFormat.getMaxSuffixValue());
53 
54         int expectedTzIdSetIdBitCount =
55                 tableEntryBitCount - suffixBitCount - entryRangeLengthBitCount;
56         assertEquals(maxValForBits(expectedTzIdSetIdBitCount),
57                 tzS2RangeFileFormat.getMaxTzIdSetIdValue());
58         assertEquals(tableEntryBitCount / 8, tzS2RangeFileFormat.getTableEntryByteCount());
59         assertEquals(maxValForBits(entryRangeLengthBitCount),
60                 tzS2RangeFileFormat.getTableEntryMaxRangeLengthValue());
61     }
62 
63     @Test
calculateRangeLength()64     public void calculateRangeLength() {
65         int s2Level = 12;
66         int prefixBitCount = 11;
67         int suffixBitCount = 16;
68         int suffixTableBlockIdOffset = 5;
69         int suffixTableEntryBitCount = 24;
70         int entryRangeLengthBitCount = 5;
71         TzS2RangeFileFormat tzS2RangeFileFormat = new TzS2RangeFileFormat(s2Level, prefixBitCount,
72                 suffixBitCount, suffixTableBlockIdOffset, suffixTableEntryBitCount,
73                 entryRangeLengthBitCount);
74 
75         assertEquals(2, tzS2RangeFileFormat.calculateRangeLength(
76                 cellId(s2Level, 0, 0), cellId(s2Level, 0, 2)));
77         assertEquals(2, tzS2RangeFileFormat.calculateRangeLength(
78                 cellId(s2Level, 0, 2), cellId(s2Level, 0, 4)));
79 
80         int cellsPerFace = intPow2(s2Level * 2);
81         assertEquals(cellsPerFace + 2,
82                 tzS2RangeFileFormat.calculateRangeLength(
83                         cellId(s2Level, 0, 2), cellId(s2Level, 1, 4)));
84     }
85 
86     @Test
createCellId()87     public void createCellId() {
88         int s2Level = 12;
89         int prefixBitCount = 11;
90         int suffixBitCount = 16;
91         int suffixTableBlockIdOffset = 5;
92         int suffixTableEntryBitCount = 24;
93         int entryRangeLengthBitCount = 5;
94         TzS2RangeFileFormat tzS2RangeFileFormat = new TzS2RangeFileFormat(s2Level, prefixBitCount,
95                 suffixBitCount, suffixTableBlockIdOffset, suffixTableEntryBitCount,
96                 entryRangeLengthBitCount);
97 
98         // Too many bits for prefixValue
99         assertThrows(IllegalArgumentException.class,
100                 () -> tzS2RangeFileFormat.createCellId(0b1000_00000000, 0b10000000_00000000));
101 
102         // Too many bits for suffixValue
103         assertThrows(IllegalArgumentException.class,
104                 () -> tzS2RangeFileFormat.createCellId(0b1000_00000000, 0b100000000_00000000));
105 
106         // Some valid cases.
107         assertEquals(cellId(s2Level, 4, 0),
108                 tzS2RangeFileFormat.createCellId(0b100_00000000, 0b00000000_00000000));
109         assertEquals(cellId(s2Level, 4, 1),
110                 tzS2RangeFileFormat.createCellId(0b100_00000000, 0b00000000_00000001));
111 
112         assertEquals(cellId(s2Level, 5, intPow2(0)),
113                 tzS2RangeFileFormat.createCellId(0b101_00000000, 0b00000000_00000001));
114         assertEquals(cellId(s2Level, 5, intPow2(8)),
115                 tzS2RangeFileFormat.createCellId(0b101_00000000, 0b00000001_00000000));
116         assertEquals(cellId(s2Level, 5, intPow2(16)),
117                 tzS2RangeFileFormat.createCellId(0b101_00000001, 0b00000000_00000000));
118     }
119 
120     @Test
extractFaceIdFromPrefix()121     public void extractFaceIdFromPrefix() {
122         int s2Level = 12;
123         int prefixBitCount = 11;
124         int suffixBitCount = 16;
125         int suffixTableBlockIdOffset = 5;
126         int suffixTableEntryBitCount = 24;
127         int entryRangeLengthBitCount = 5;
128         TzS2RangeFileFormat tzS2RangeFileFormat = new TzS2RangeFileFormat(s2Level, prefixBitCount,
129                 suffixBitCount, suffixTableBlockIdOffset, suffixTableEntryBitCount,
130                 entryRangeLengthBitCount);
131 
132         assertEquals(0, tzS2RangeFileFormat.extractFaceIdFromPrefix(0b00000000000));
133         assertEquals(5, tzS2RangeFileFormat.extractFaceIdFromPrefix(0b10100000000));
134         // We require this (invalid) face ID to work, since this method is used to detect face ID
135         // overflow.
136         assertEquals(6, tzS2RangeFileFormat.extractFaceIdFromPrefix(0b11000000000));
137     }
138 
139     @Test
createSuffixTableValue()140     public void createSuffixTableValue() {
141         int s2Level = 12;
142         int prefixBitCount = 11;
143         int suffixBitCount = 16;
144         int suffixTableBlockIdOffset = 5;
145         int suffixTableEntryBitCount = 24;
146         int entryRangeLengthBitCount = 5;
147         TzS2RangeFileFormat tzS2RangeFileFormat = new TzS2RangeFileFormat(s2Level, prefixBitCount,
148                 suffixBitCount, suffixTableBlockIdOffset, suffixTableEntryBitCount,
149                 entryRangeLengthBitCount);
150 
151         // The format above sets 5 bits for range length and implicitly sets 3 bits for TZ IDs set
152         // ID: suffixTableEntryBitCount(24) - suffixBitCount(16) - entryRangeLengthBitCount(5) = 3
153 
154         // Too many bits for rangeLength
155         assertThrows(IllegalArgumentException.class,
156                 () -> tzS2RangeFileFormat.createSuffixTableValue(0b100000, 0b101));
157 
158         // Too many bits for tzIdSetId
159         assertThrows(IllegalArgumentException.class,
160                 () -> tzS2RangeFileFormat.createSuffixTableValue(0b10101, 0b1101));
161 
162         // Some valid cases.
163         assertEquals(0b10101101, tzS2RangeFileFormat.createSuffixTableValue(0b10101, 0b101));
164         assertEquals(0b10101000, tzS2RangeFileFormat.createSuffixTableValue(0b10101, 0b000));
165         assertEquals(0b00000101, tzS2RangeFileFormat.createSuffixTableValue(0b00000, 0b101));
166     }
167 
maxValForBits(int bits)168     private static int maxValForBits(int bits) {
169         return intPow2(bits) - 1;
170     }
171 
intPow2(int value)172     private static int intPow2(int value) {
173         return (int) Math.pow(2, value);
174     }
175 }
176