1 /* 2 * Copyright (C) 2017 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 package com.android.tradefed.invoker; 17 18 import static org.junit.Assert.assertEquals; 19 import static org.junit.Assert.assertNotNull; 20 import static org.junit.Assert.assertNull; 21 import static org.junit.Assert.assertTrue; 22 import static org.junit.Assert.fail; 23 import static org.mockito.Mockito.mock; 24 25 import com.android.tradefed.build.BuildInfo; 26 import com.android.tradefed.build.IBuildInfo; 27 import com.android.tradefed.config.ConfigurationDescriptor; 28 import com.android.tradefed.device.ITestDevice; 29 import com.android.tradefed.invoker.proto.InvocationContext.Context; 30 import com.android.tradefed.testtype.suite.ModuleDefinition; 31 import com.android.tradefed.util.FileUtil; 32 import com.android.tradefed.util.MultiMap; 33 import com.android.tradefed.util.SerializationUtil; 34 import com.android.tradefed.util.UniqueMultiMap; 35 36 import org.junit.Before; 37 import org.junit.Test; 38 import org.junit.runner.RunWith; 39 import org.junit.runners.JUnit4; 40 41 import java.io.File; 42 import java.util.Arrays; 43 44 /** Unit tests for {@link InvocationContext} */ 45 @RunWith(JUnit4.class) 46 public class InvocationContextTest { 47 48 private InvocationContext mContext; 49 50 @Before setUp()51 public void setUp() { 52 mContext = new InvocationContext(); 53 } 54 55 /** Test setting and getting invocation ID. */ 56 @Test testGetInvocationID()57 public void testGetInvocationID() { 58 // initially null 59 assertNull(mContext.getInvocationId()); 60 61 // non-null after adding the ID as an attribute 62 mContext.addInvocationAttribute(IInvocationContext.INVOCATION_ID, "TEST_ID"); 63 assertEquals("TEST_ID", mContext.getInvocationId()); 64 } 65 66 /** Test the reverse look up of the device name in the configuration for an ITestDevice */ 67 @Test testGetDeviceName()68 public void testGetDeviceName() { 69 ITestDevice device1 = mock(ITestDevice.class); 70 ITestDevice device2 = mock(ITestDevice.class); 71 // assert that at init, map is empty. 72 assertNull(mContext.getDeviceName(device1)); 73 mContext.addAllocatedDevice("test1", device1); 74 assertEquals("test1", mContext.getDeviceName(device1)); 75 assertNull(mContext.getDeviceName(device2)); 76 } 77 78 /** Test the reverse look up of the device name in the configuration for an IBuildInfo */ 79 @Test testGetBuildInfoName()80 public void testGetBuildInfoName() { 81 IBuildInfo build1 = mock(IBuildInfo.class); 82 IBuildInfo build2 = mock(IBuildInfo.class); 83 // assert that at init, map is empty. 84 assertNull(mContext.getBuildInfoName(build1)); 85 mContext.addDeviceBuildInfo("test1", build1); 86 assertEquals("test1", mContext.getBuildInfoName(build1)); 87 assertNull(mContext.getBuildInfoName(build2)); 88 } 89 90 /** 91 * Test adding attributes and querying them. The map returned is always a copy and does not 92 * affect the actual invocation attributes. 93 */ 94 @Test testGetAttributes()95 public void testGetAttributes() { 96 mContext.addInvocationAttribute("TEST_KEY", "TEST_VALUE"); 97 assertEquals(Arrays.asList("TEST_VALUE"), mContext.getAttributes().get("TEST_KEY")); 98 MultiMap<String, String> map = mContext.getAttributes(); 99 map.remove("TEST_KEY"); 100 // assert that the key is still there in the map from the context 101 assertEquals(Arrays.asList("TEST_VALUE"), mContext.getAttributes().get("TEST_KEY")); 102 } 103 104 /** Test that once locked the invocation context does not accept more invocation attributes. */ 105 @Test testLockedContext()106 public void testLockedContext() { 107 mContext.lockAttributes(); 108 try { 109 mContext.addInvocationAttribute("test", "Test"); 110 fail("Should have thrown an exception."); 111 } catch (IllegalStateException expected) { 112 // expected 113 } 114 try { 115 mContext.addInvocationAttributes(new UniqueMultiMap<>()); 116 fail("Should have thrown an exception."); 117 } catch (IllegalStateException expected) { 118 // expected 119 } 120 } 121 122 /** Test that serializing and deserializing an {@link InvocationContext}. */ 123 @Test testSerialize()124 public void testSerialize() throws Exception { 125 assertNotNull(mContext.getDeviceBuildMap()); 126 ITestDevice device = mock(ITestDevice.class); 127 IBuildInfo info = new BuildInfo("1234", "test-target"); 128 mContext.addAllocatedDevice("test-device", device); 129 mContext.addDeviceBuildInfo("test-device", info); 130 mContext.setConfigurationDescriptor(new ConfigurationDescriptor()); 131 assertEquals(info, mContext.getBuildInfo(device)); 132 File ser = SerializationUtil.serialize(mContext); 133 try { 134 InvocationContext deserialized = 135 (InvocationContext) SerializationUtil.deserialize(ser, true); 136 // One consequence is that transient attribute will become null but our custom 137 // deserialization should fix that. 138 assertNotNull(deserialized.getDeviceBuildMap()); 139 assertNotNull(deserialized.getConfigurationDescriptor()); 140 assertEquals(info, deserialized.getBuildInfo("test-device")); 141 142 // The device are not carried 143 assertTrue(deserialized.getDevices().isEmpty()); 144 // Re-assigning a device, recreate the previous relationships 145 deserialized.addAllocatedDevice("test-device", device); 146 assertEquals(info, mContext.getBuildInfo(device)); 147 } finally { 148 FileUtil.deleteFile(ser); 149 } 150 } 151 152 @Test testProtoSerialize()153 public void testProtoSerialize() { 154 InvocationContext context = new InvocationContext(); 155 ConfigurationDescriptor descriptor = new ConfigurationDescriptor(); 156 descriptor.setModuleName("module"); 157 context.setConfigurationDescriptor(descriptor); 158 context.setTestTag("tag"); 159 context.addInvocationAttribute("test_key", "test_value"); 160 Context protoContext = context.toProto(); 161 // Check the proto 162 assertEquals("tag", protoContext.getTestTag()); 163 assertEquals(1, protoContext.getMetadataList().size()); 164 assertEquals("test_key", protoContext.getMetadataList().get(0).getKey()); 165 166 // Check the deserialize 167 InvocationContext deserialized = InvocationContext.fromProto(protoContext); 168 assertNull(deserialized.getModuleInvocationContext()); 169 assertNotNull(deserialized.getConfigurationDescriptor()); 170 assertEquals("tag", deserialized.getTestTag()); 171 } 172 173 @Test testProtoSerialize_moduleContext()174 public void testProtoSerialize_moduleContext() { 175 InvocationContext context = new InvocationContext(); 176 ConfigurationDescriptor descriptor = new ConfigurationDescriptor(); 177 descriptor.setModuleName("module"); 178 context.setConfigurationDescriptor(descriptor); 179 180 InvocationContext moduleContext = new InvocationContext(); 181 moduleContext.addInvocationAttribute(ModuleDefinition.MODULE_ID, "module-id"); 182 moduleContext.setConfigurationDescriptor(new ConfigurationDescriptor()); 183 context.setModuleInvocationContext(moduleContext); 184 185 Context protoContext = context.toProto(); 186 assertNotNull(protoContext.getModuleContext()); 187 188 // Check the deserialize 189 InvocationContext deserialized = InvocationContext.fromProto(protoContext); 190 assertNotNull(deserialized.getModuleInvocationContext()); 191 assertEquals( 192 "module-id", 193 deserialized 194 .getModuleInvocationContext() 195 .getAttributes() 196 .get(ModuleDefinition.MODULE_ID) 197 .get(0)); 198 } 199 } 200