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.aconfigd.test; 18 19 import static org.junit.Assert.assertArrayEquals; 20 import static org.junit.Assert.assertEquals; 21 import static org.junit.Assert.assertTrue; 22 23 import android.aconfigd.Aconfigd.StorageRequestMessage; 24 import android.aconfigd.Aconfigd.StorageRequestMessages; 25 import android.aconfigd.Aconfigd.StorageReturnMessage; 26 import android.aconfigd.Aconfigd.StorageReturnMessages; 27 import android.aconfigd.AconfigdClientSocket; 28 import android.aconfigd.AconfigdFlagInfo; 29 import android.aconfigd.AconfigdJavaUtils; 30 import android.util.proto.ProtoOutputStream; 31 32 import org.junit.Test; 33 import org.junit.runner.RunWith; 34 import org.junit.runners.JUnit4; 35 36 import java.io.ByteArrayInputStream; 37 import java.io.ByteArrayOutputStream; 38 import java.io.InputStream; 39 import java.util.Arrays; 40 import java.util.List; 41 import java.util.Map; 42 import java.util.function.Function; 43 44 @RunWith(JUnit4.class) 45 public class AconfigdJavaUtilsTest { 46 47 @Test testListFlagsValueInNewStorage_singleFlag()48 public void testListFlagsValueInNewStorage_singleFlag() throws Exception { 49 String packageName = "android.acondigd.test"; 50 String flagName = "test_flag"; 51 String serverValue = ""; 52 String localValue = ""; 53 String bootValue = "true"; 54 String defaultValue = "true"; 55 boolean hasServerOverride = false; 56 boolean isReadWrite = false; 57 boolean hasLocalOverride = false; 58 59 AconfigdFlagInfo expectedRev = 60 AconfigdFlagInfo.newBuilder() 61 .setBootFlagValue(bootValue) 62 .setDefaultFlagValue(defaultValue) 63 .setFlagName(flagName) 64 .setHasLocalOverride(hasLocalOverride) 65 .setHasServerOverride(hasServerOverride) 66 .setIsReadWrite(isReadWrite) 67 .setLocalFlagValue(localValue) 68 .setPackageName(packageName) 69 .setServerFlagValue(serverValue) 70 .build(); 71 72 ProtoOutputStream serverReturn = writeListFlagsRequest(Arrays.asList(expectedRev)); 73 74 ByteArrayOutputStream buffer = new ByteArrayOutputStream(serverReturn.getRawSize()); 75 buffer.write(serverReturn.getBytes(), 0, serverReturn.getRawSize()); 76 77 AconfigdClientSocket localSocket = 78 new FakeAconfigdClientSocketImpl( 79 input -> new ByteArrayInputStream(buffer.toByteArray())); 80 81 Map<String, AconfigdFlagInfo> flagMap = 82 AconfigdJavaUtils.listFlagsValueInNewStorage(localSocket); 83 assertTrue(flagMap.containsKey(expectedRev.getFullFlagName())); 84 assertEquals(expectedRev, flagMap.get(expectedRev.getFullFlagName())); 85 } 86 87 @Test testListFlagsValueInNewStorage_multiFlags()88 public void testListFlagsValueInNewStorage_multiFlags() throws Exception { 89 String packageName = "android.acondigd.test"; 90 String flagName1 = "test_flag1"; 91 String flagName2 = "test_flag2"; 92 String serverValue = ""; 93 String localValue = ""; 94 String bootValue = "true"; 95 String defaultValue = "true"; 96 boolean hasServerOverride = false; 97 boolean isReadWrite = false; 98 boolean hasLocalOverride = false; 99 100 AconfigdFlagInfo expectedRev1 = 101 AconfigdFlagInfo.newBuilder() 102 .setBootFlagValue(bootValue) 103 .setDefaultFlagValue(defaultValue) 104 .setFlagName(flagName1) 105 .setHasLocalOverride(hasLocalOverride) 106 .setHasServerOverride(hasServerOverride) 107 .setIsReadWrite(isReadWrite) 108 .setLocalFlagValue(localValue) 109 .setPackageName(packageName) 110 .setServerFlagValue(serverValue) 111 .build(); 112 113 AconfigdFlagInfo expectedRev2 = 114 AconfigdFlagInfo.newBuilder() 115 .setBootFlagValue(bootValue) 116 .setDefaultFlagValue(defaultValue) 117 .setFlagName(flagName2) 118 .setHasLocalOverride(hasLocalOverride) 119 .setHasServerOverride(hasServerOverride) 120 .setIsReadWrite(isReadWrite) 121 .setLocalFlagValue(localValue) 122 .setPackageName(packageName) 123 .setServerFlagValue(serverValue) 124 .build(); 125 126 ProtoOutputStream serverReturn = 127 writeListFlagsRequest(Arrays.asList(expectedRev1, expectedRev2)); 128 129 ByteArrayOutputStream buffer = new ByteArrayOutputStream(serverReturn.getRawSize()); 130 buffer.write(serverReturn.getBytes(), 0, serverReturn.getRawSize()); 131 132 AconfigdClientSocket localSocket = 133 new FakeAconfigdClientSocketImpl( 134 input -> new ByteArrayInputStream(buffer.toByteArray())); 135 136 Map<String, AconfigdFlagInfo> flagMap = 137 AconfigdJavaUtils.listFlagsValueInNewStorage(localSocket); 138 assertTrue(flagMap.containsKey(expectedRev1.getFullFlagName())); 139 assertTrue(flagMap.containsKey(expectedRev2.getFullFlagName())); 140 assertEquals(expectedRev1, flagMap.get(expectedRev1.getFullFlagName())); 141 assertEquals(expectedRev2, flagMap.get(expectedRev2.getFullFlagName())); 142 } 143 144 @Test testListFlagsValueInNewStorage_errorMessage()145 public void testListFlagsValueInNewStorage_errorMessage() throws Exception { 146 ProtoOutputStream serverReturn = new ProtoOutputStream(); 147 String expectErrorMessage = "invalid"; 148 long msgsToken = serverReturn.start(StorageReturnMessages.MSGS); 149 serverReturn.write(StorageReturnMessage.ERROR_MESSAGE, expectErrorMessage); 150 serverReturn.end(msgsToken); 151 152 ByteArrayOutputStream buffer = new ByteArrayOutputStream(serverReturn.getRawSize()); 153 buffer.write(serverReturn.getBytes(), 0, serverReturn.getRawSize()); 154 155 AconfigdClientSocket localSocket = 156 new FakeAconfigdClientSocketImpl( 157 input -> new ByteArrayInputStream(buffer.toByteArray())); 158 159 Map<String, AconfigdFlagInfo> flagMap = 160 AconfigdJavaUtils.listFlagsValueInNewStorage(localSocket); 161 assertTrue(flagMap.isEmpty()); 162 } 163 164 @Test testListFlagsValueInNewStorage_checkRequest()165 public void testListFlagsValueInNewStorage_checkRequest() throws Exception { 166 167 ProtoOutputStream expectRequests = new ProtoOutputStream(); 168 long msgsToken = expectRequests.start(StorageRequestMessages.MSGS); 169 long msgToken = expectRequests.start(StorageRequestMessage.LIST_STORAGE_MESSAGE); 170 expectRequests.write(StorageRequestMessage.ListStorageMessage.ALL, 1); 171 expectRequests.end(msgToken); 172 expectRequests.end(msgsToken); 173 174 ProtoOutputStream serverReturn = new ProtoOutputStream(); 175 String expectErrorMessage = "invalid"; 176 msgsToken = serverReturn.start(StorageReturnMessages.MSGS); 177 serverReturn.write(StorageReturnMessage.ERROR_MESSAGE, expectErrorMessage); 178 serverReturn.end(msgsToken); 179 180 ByteArrayOutputStream buffer = new ByteArrayOutputStream(serverReturn.getRawSize()); 181 buffer.write(serverReturn.getBytes(), 0, serverReturn.getRawSize()); 182 183 AconfigdClientSocket localSocket = 184 new FakeAconfigdClientSocketImpl( 185 input -> { 186 assertArrayEquals(expectRequests.getBytes(), input); 187 return new ByteArrayInputStream(buffer.toByteArray()); 188 }); 189 190 Map<String, AconfigdFlagInfo> flagMap = 191 AconfigdJavaUtils.listFlagsValueInNewStorage(localSocket); 192 assertTrue(flagMap.isEmpty()); 193 } 194 writeListFlagsRequest(List<AconfigdFlagInfo> flags)195 private ProtoOutputStream writeListFlagsRequest(List<AconfigdFlagInfo> flags) { 196 ProtoOutputStream serverReturn = new ProtoOutputStream(); 197 long msgsToken = serverReturn.start(StorageReturnMessages.MSGS); 198 long listToken = serverReturn.start(StorageReturnMessage.LIST_STORAGE_MESSAGE); 199 200 for (AconfigdFlagInfo flag : flags) { 201 long flagToken = 202 serverReturn.start(StorageReturnMessage.ListStorageReturnMessage.FLAGS); 203 serverReturn.write( 204 StorageReturnMessage.FlagQueryReturnMessage.PACKAGE_NAME, 205 flag.getPackageName()); 206 serverReturn.write( 207 StorageReturnMessage.FlagQueryReturnMessage.FLAG_NAME, flag.getFlagName()); 208 serverReturn.write( 209 StorageReturnMessage.FlagQueryReturnMessage.SERVER_FLAG_VALUE, 210 flag.getServerFlagValue()); 211 serverReturn.write( 212 StorageReturnMessage.FlagQueryReturnMessage.LOCAL_FLAG_VALUE, 213 flag.getLocalFlagValue()); 214 serverReturn.write( 215 StorageReturnMessage.FlagQueryReturnMessage.BOOT_FLAG_VALUE, 216 flag.getBootFlagValue()); 217 serverReturn.write( 218 StorageReturnMessage.FlagQueryReturnMessage.DEFAULT_FLAG_VALUE, 219 flag.getDefaultFlagValue()); 220 serverReturn.write( 221 StorageReturnMessage.FlagQueryReturnMessage.HAS_SERVER_OVERRIDE, 222 flag.getHasServerOverride()); 223 serverReturn.write( 224 StorageReturnMessage.FlagQueryReturnMessage.IS_READWRITE, 225 flag.getIsReadWrite()); 226 serverReturn.write( 227 StorageReturnMessage.FlagQueryReturnMessage.HAS_LOCAL_OVERRIDE, 228 flag.getHasLocalOverride()); 229 serverReturn.end(flagToken); 230 } 231 232 serverReturn.end(listToken); 233 serverReturn.end(msgsToken); 234 return serverReturn; 235 } 236 237 private class FakeAconfigdClientSocketImpl implements AconfigdClientSocket { 238 private Function<byte[], InputStream> mSendFunc; 239 FakeAconfigdClientSocketImpl(Function<byte[], InputStream> sendFunc)240 FakeAconfigdClientSocketImpl(Function<byte[], InputStream> sendFunc) { 241 mSendFunc = sendFunc; 242 } 243 244 @Override send(byte[] requests)245 public InputStream send(byte[] requests) { 246 return mSendFunc.apply(requests); 247 } 248 249 @Override close()250 public void close() { 251 return; 252 } 253 } 254 } 255