1 /* 2 * Copyright (C) 2024 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.aconfig.storage.test; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertTrue; 21 22 import android.aconfig.DeviceProtos; 23 import android.aconfig.nano.Aconfig.parsed_flag; 24 import android.aconfig.storage.AconfigStorageReadAPI; 25 import android.aconfig.storage.FlagReadContext; 26 import android.aconfig.storage.FlagReadContext.StoredFlagType; 27 import android.aconfig.storage.PackageReadContext; 28 import android.aconfig.storage.SipHasher13; 29 import android.aconfig.storage.StorageInternalReader; 30 31 import org.junit.Test; 32 import org.junit.runner.RunWith; 33 import org.junit.runners.JUnit4; 34 35 import java.io.IOException; 36 import java.nio.MappedByteBuffer; 37 import java.util.ArrayList; 38 import java.util.List; 39 40 @RunWith(JUnit4.class) 41 public class AconfigStorageReadAPITest { 42 43 private String mStorageDir = "/data/local/tmp/aconfig_java_api_test"; 44 45 @Test testPackageContextQuery()46 public void testPackageContextQuery() { 47 MappedByteBuffer packageMap = null; 48 try { 49 packageMap = 50 AconfigStorageReadAPI.mapStorageFile(mStorageDir + "/maps/mockup.package.map"); 51 } catch (IOException ex) { 52 assertTrue(ex.toString(), false); 53 } 54 assertTrue(packageMap != null); 55 56 try { 57 PackageReadContext context = 58 AconfigStorageReadAPI.getPackageReadContext( 59 packageMap, "com.android.aconfig.storage.test_1"); 60 assertEquals(context.mPackageId, 0); 61 assertEquals(context.mBooleanStartIndex, 0); 62 63 context = 64 AconfigStorageReadAPI.getPackageReadContext( 65 packageMap, "com.android.aconfig.storage.test_2"); 66 assertEquals(context.mPackageId, 1); 67 assertEquals(context.mBooleanStartIndex, 3); 68 69 context = 70 AconfigStorageReadAPI.getPackageReadContext( 71 packageMap, "com.android.aconfig.storage.test_4"); 72 assertEquals(context.mPackageId, 2); 73 assertEquals(context.mBooleanStartIndex, 6); 74 } catch (IOException ex) { 75 assertTrue(ex.toString(), false); 76 } 77 } 78 79 @Test testNonExistPackageContextQuery()80 public void testNonExistPackageContextQuery() { 81 MappedByteBuffer packageMap = null; 82 try { 83 packageMap = 84 AconfigStorageReadAPI.mapStorageFile(mStorageDir + "/maps/mockup.package.map"); 85 } catch (IOException ex) { 86 assertTrue(ex.toString(), false); 87 } 88 assertTrue(packageMap != null); 89 90 try { 91 PackageReadContext context = 92 AconfigStorageReadAPI.getPackageReadContext(packageMap, "unknown"); 93 assertEquals(context.mPackageId, -1); 94 assertEquals(context.mBooleanStartIndex, -1); 95 } catch (IOException ex) { 96 assertTrue(ex.toString(), false); 97 } 98 } 99 100 @Test testFlagContextQuery()101 public void testFlagContextQuery() { 102 MappedByteBuffer flagMap = null; 103 try { 104 flagMap = AconfigStorageReadAPI.mapStorageFile(mStorageDir + "/maps/mockup.flag.map"); 105 } catch (IOException ex) { 106 assertTrue(ex.toString(), false); 107 } 108 assertTrue(flagMap != null); 109 110 class Baseline { 111 public int mPackageId; 112 public String mFlagName; 113 public StoredFlagType mFlagType; 114 public int mFlagIndex; 115 116 public Baseline( 117 int packageId, String flagName, StoredFlagType flagType, int flagIndex) { 118 mPackageId = packageId; 119 mFlagName = flagName; 120 mFlagType = flagType; 121 mFlagIndex = flagIndex; 122 } 123 } 124 125 List<Baseline> baselines = new ArrayList(); 126 baselines.add(new Baseline(0, "enabled_ro", StoredFlagType.ReadOnlyBoolean, 1)); 127 baselines.add(new Baseline(0, "enabled_rw", StoredFlagType.ReadWriteBoolean, 2)); 128 baselines.add(new Baseline(2, "enabled_rw", StoredFlagType.ReadWriteBoolean, 1)); 129 baselines.add(new Baseline(1, "disabled_rw", StoredFlagType.ReadWriteBoolean, 0)); 130 baselines.add(new Baseline(1, "enabled_fixed_ro", StoredFlagType.FixedReadOnlyBoolean, 1)); 131 baselines.add(new Baseline(1, "enabled_ro", StoredFlagType.ReadOnlyBoolean, 2)); 132 baselines.add(new Baseline(2, "enabled_fixed_ro", StoredFlagType.FixedReadOnlyBoolean, 0)); 133 baselines.add(new Baseline(0, "disabled_rw", StoredFlagType.ReadWriteBoolean, 0)); 134 135 try { 136 for (Baseline baseline : baselines) { 137 FlagReadContext context = 138 AconfigStorageReadAPI.getFlagReadContext( 139 flagMap, baseline.mPackageId, baseline.mFlagName); 140 assertEquals(context.mFlagType, baseline.mFlagType); 141 assertEquals(context.mFlagIndex, baseline.mFlagIndex); 142 } 143 } catch (IOException ex) { 144 assertTrue(ex.toString(), false); 145 } 146 } 147 148 @Test testNonExistFlagContextQuery()149 public void testNonExistFlagContextQuery() { 150 MappedByteBuffer flagMap = null; 151 try { 152 flagMap = AconfigStorageReadAPI.mapStorageFile(mStorageDir + "/maps/mockup.flag.map"); 153 } catch (IOException ex) { 154 assertTrue(ex.toString(), false); 155 } 156 assertTrue(flagMap != null); 157 158 try { 159 FlagReadContext context = 160 AconfigStorageReadAPI.getFlagReadContext(flagMap, 0, "unknown"); 161 assertEquals(context.mFlagType, null); 162 assertEquals(context.mFlagIndex, -1); 163 164 context = AconfigStorageReadAPI.getFlagReadContext(flagMap, 3, "enabled_ro"); 165 assertEquals(context.mFlagType, null); 166 assertEquals(context.mFlagIndex, -1); 167 } catch (IOException ex) { 168 assertTrue(ex.toString(), false); 169 } 170 } 171 172 @Test testBooleanFlagValueQuery()173 public void testBooleanFlagValueQuery() { 174 MappedByteBuffer flagVal = null; 175 try { 176 flagVal = AconfigStorageReadAPI.mapStorageFile(mStorageDir + "/boot/mockup.val"); 177 } catch (IOException ex) { 178 assertTrue(ex.toString(), false); 179 } 180 assertTrue(flagVal != null); 181 182 boolean[] baselines = {false, true, true, false, true, true, true, true}; 183 for (int i = 0; i < 8; ++i) { 184 try { 185 Boolean value = AconfigStorageReadAPI.getBooleanFlagValue(flagVal, i); 186 assertEquals(value, baselines[i]); 187 } catch (IOException ex) { 188 assertTrue(ex.toString(), false); 189 } 190 } 191 } 192 193 @Test testInvalidBooleanFlagValueQuery()194 public void testInvalidBooleanFlagValueQuery() { 195 MappedByteBuffer flagVal = null; 196 try { 197 flagVal = AconfigStorageReadAPI.mapStorageFile(mStorageDir + "/boot/mockup.val"); 198 } catch (IOException ex) { 199 assertTrue(ex.toString(), false); 200 } 201 assertTrue(flagVal != null); 202 203 try { 204 Boolean value = AconfigStorageReadAPI.getBooleanFlagValue(flagVal, 9); 205 assertTrue("should throw", false); 206 } catch (IOException ex) { 207 String expectedErrmsg = "invalid storage file byte offset"; 208 assertTrue(ex.toString(), ex.toString().contains(expectedErrmsg)); 209 } 210 } 211 212 @Test testRustJavaEqualHash()213 public void testRustJavaEqualHash() throws IOException { 214 List<parsed_flag> flags = DeviceProtos.loadAndParseFlagProtos(); 215 for (parsed_flag flag : flags) { 216 String packageName = flag.package_; 217 String flagName = flag.name; 218 long rHash = AconfigStorageReadAPI.hash(packageName); 219 long jHash = SipHasher13.hash(packageName.getBytes()); 220 assertEquals(rHash, jHash); 221 222 String fullFlagName = packageName + "/" + flagName; 223 rHash = AconfigStorageReadAPI.hash(fullFlagName); 224 jHash = SipHasher13.hash(fullFlagName.getBytes()); 225 assertEquals(rHash, jHash); 226 } 227 } 228 229 @Test testRustJavaEqualFlag()230 public void testRustJavaEqualFlag() throws IOException { 231 List<parsed_flag> flags = DeviceProtos.loadAndParseFlagProtos(); 232 233 String mapPath = "/metadata/aconfig/maps/"; 234 String flagsPath = "/metadata/aconfig/boot/"; 235 236 for (parsed_flag flag : flags) { 237 238 String container = flag.container; 239 String packageName = flag.package_; 240 String flagName = flag.name; 241 String fullFlagName = packageName + "/" + flagName; 242 243 MappedByteBuffer packageMap = 244 AconfigStorageReadAPI.mapStorageFile(mapPath + container + ".package.map"); 245 MappedByteBuffer flagMap = 246 AconfigStorageReadAPI.mapStorageFile(mapPath + container + ".flag.map"); 247 MappedByteBuffer flagValList = 248 AconfigStorageReadAPI.mapStorageFile(flagsPath + container + ".val"); 249 250 PackageReadContext packageContext = 251 AconfigStorageReadAPI.getPackageReadContext(packageMap, packageName); 252 253 FlagReadContext flagContext = 254 AconfigStorageReadAPI.getFlagReadContext( 255 flagMap, packageContext.mPackageId, flagName); 256 257 boolean rVal = 258 AconfigStorageReadAPI.getBooleanFlagValue( 259 flagValList, 260 packageContext.mBooleanStartIndex + flagContext.mFlagIndex); 261 262 StorageInternalReader reader = new StorageInternalReader(container, packageName); 263 boolean jVal = reader.getBooleanFlagValue(flagContext.mFlagIndex); 264 265 long rHash = AconfigStorageReadAPI.hash(packageName); 266 long jHash = SipHasher13.hash(packageName.getBytes()); 267 assertEquals(rVal, jVal); 268 } 269 } 270 }