1 /* 2 * Copyright (C) 2015 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 #include "transport.h" 18 19 #include <gtest/gtest.h> 20 21 #include "adb.h" 22 23 class TransportSetup { 24 public: 25 TransportSetup() { 26 #ifdef _WIN32 27 // Use extern instead of including sysdeps.h which brings in various macros 28 // that conflict with APIs used in this file. 29 extern void adb_sysdeps_init(void); 30 adb_sysdeps_init(); 31 #else 32 // adb_sysdeps_init() is an inline function that we cannot link against. 33 #endif 34 } 35 }; 36 37 // Static initializer will call adb_sysdeps_init() before main() to initialize 38 // the transport mutex before it is used in the tests. Alternatives would be to 39 // use __attribute__((constructor)) here or to use that or a static initializer 40 // for adb_sysdeps_init() itself in sysdeps_win32.cpp (caveats of unclear 41 // init order), or to use a test fixture whose SetUp() could do the init once. 42 static TransportSetup g_TransportSetup; 43 44 TEST(transport, kick_transport) { 45 atransport t; 46 static size_t kick_count; 47 kick_count = 0; 48 // Mutate some member so we can test that the function is run. 49 t.SetKickFunction([](atransport* trans) { kick_count++; }); 50 ASSERT_FALSE(t.IsKicked()); 51 t.Kick(); 52 ASSERT_TRUE(t.IsKicked()); 53 ASSERT_EQ(1u, kick_count); 54 // A transport can only be kicked once. 55 t.Kick(); 56 ASSERT_TRUE(t.IsKicked()); 57 ASSERT_EQ(1u, kick_count); 58 } 59 60 static void DisconnectFunc(void* arg, atransport*) { 61 int* count = reinterpret_cast<int*>(arg); 62 ++*count; 63 } 64 65 TEST(transport, RunDisconnects) { 66 atransport t; 67 // RunDisconnects() can be called with an empty atransport. 68 t.RunDisconnects(); 69 70 int count = 0; 71 adisconnect disconnect; 72 disconnect.func = DisconnectFunc; 73 disconnect.opaque = &count; 74 t.AddDisconnect(&disconnect); 75 t.RunDisconnects(); 76 ASSERT_EQ(1, count); 77 78 // disconnect should have been removed automatically. 79 t.RunDisconnects(); 80 ASSERT_EQ(1, count); 81 82 count = 0; 83 t.AddDisconnect(&disconnect); 84 t.RemoveDisconnect(&disconnect); 85 t.RunDisconnects(); 86 ASSERT_EQ(0, count); 87 } 88 89 TEST(transport, SetFeatures) { 90 atransport t; 91 ASSERT_EQ(0U, t.features().size()); 92 93 t.SetFeatures(FeatureSetToString(FeatureSet{"foo"})); 94 ASSERT_EQ(1U, t.features().size()); 95 ASSERT_TRUE(t.has_feature("foo")); 96 97 t.SetFeatures(FeatureSetToString(FeatureSet{"foo", "bar"})); 98 ASSERT_EQ(2U, t.features().size()); 99 ASSERT_TRUE(t.has_feature("foo")); 100 ASSERT_TRUE(t.has_feature("bar")); 101 102 t.SetFeatures(FeatureSetToString(FeatureSet{"foo", "bar", "foo"})); 103 ASSERT_EQ(2U, t.features().size()); 104 ASSERT_TRUE(t.has_feature("foo")); 105 ASSERT_TRUE(t.has_feature("bar")); 106 107 t.SetFeatures(FeatureSetToString(FeatureSet{"bar", "baz"})); 108 ASSERT_EQ(2U, t.features().size()); 109 ASSERT_FALSE(t.has_feature("foo")); 110 ASSERT_TRUE(t.has_feature("bar")); 111 ASSERT_TRUE(t.has_feature("baz")); 112 113 t.SetFeatures(""); 114 ASSERT_EQ(0U, t.features().size()); 115 } 116 117 TEST(transport, parse_banner_no_features) { 118 atransport t; 119 120 parse_banner("host::", &t); 121 122 ASSERT_EQ(0U, t.features().size()); 123 ASSERT_EQ(kCsHost, t.connection_state); 124 125 ASSERT_EQ(nullptr, t.product); 126 ASSERT_EQ(nullptr, t.model); 127 ASSERT_EQ(nullptr, t.device); 128 } 129 130 TEST(transport, parse_banner_product_features) { 131 atransport t; 132 133 const char banner[] = 134 "host::ro.product.name=foo;ro.product.model=bar;ro.product.device=baz;"; 135 parse_banner(banner, &t); 136 137 ASSERT_EQ(kCsHost, t.connection_state); 138 139 ASSERT_EQ(0U, t.features().size()); 140 141 ASSERT_EQ(std::string("foo"), t.product); 142 ASSERT_EQ(std::string("bar"), t.model); 143 ASSERT_EQ(std::string("baz"), t.device); 144 } 145 146 TEST(transport, parse_banner_features) { 147 atransport t; 148 149 const char banner[] = 150 "host::ro.product.name=foo;ro.product.model=bar;ro.product.device=baz;" 151 "features=woodly,doodly"; 152 parse_banner(banner, &t); 153 154 ASSERT_EQ(kCsHost, t.connection_state); 155 156 ASSERT_EQ(2U, t.features().size()); 157 ASSERT_TRUE(t.has_feature("woodly")); 158 ASSERT_TRUE(t.has_feature("doodly")); 159 160 ASSERT_EQ(std::string("foo"), t.product); 161 ASSERT_EQ(std::string("bar"), t.model); 162 ASSERT_EQ(std::string("baz"), t.device); 163 } 164 165 TEST(transport, test_matches_target) { 166 std::string serial = "foo"; 167 std::string devpath = "/path/to/bar"; 168 std::string product = "test_product"; 169 std::string model = "test_model"; 170 std::string device = "test_device"; 171 172 atransport t; 173 t.serial = &serial[0]; 174 t.devpath = &devpath[0]; 175 t.product = &product[0]; 176 t.model = &model[0]; 177 t.device = &device[0]; 178 179 // These tests should not be affected by the transport type. 180 for (TransportType type : {kTransportAny, kTransportLocal}) { 181 t.type = type; 182 183 EXPECT_TRUE(t.MatchesTarget(serial)); 184 EXPECT_TRUE(t.MatchesTarget(devpath)); 185 EXPECT_TRUE(t.MatchesTarget("product:" + product)); 186 EXPECT_TRUE(t.MatchesTarget("model:" + model)); 187 EXPECT_TRUE(t.MatchesTarget("device:" + device)); 188 189 // Product, model, and device don't match without the prefix. 190 EXPECT_FALSE(t.MatchesTarget(product)); 191 EXPECT_FALSE(t.MatchesTarget(model)); 192 EXPECT_FALSE(t.MatchesTarget(device)); 193 } 194 } 195 196 TEST(transport, test_matches_target_local) { 197 std::string serial = "100.100.100.100:5555"; 198 199 atransport t; 200 t.serial = &serial[0]; 201 202 // Network address matching should only be used for local transports. 203 for (TransportType type : {kTransportAny, kTransportLocal}) { 204 t.type = type; 205 bool should_match = (type == kTransportLocal); 206 207 EXPECT_EQ(should_match, t.MatchesTarget("100.100.100.100")); 208 EXPECT_EQ(should_match, t.MatchesTarget("tcp:100.100.100.100")); 209 EXPECT_EQ(should_match, t.MatchesTarget("tcp:100.100.100.100:5555")); 210 EXPECT_EQ(should_match, t.MatchesTarget("udp:100.100.100.100")); 211 EXPECT_EQ(should_match, t.MatchesTarget("udp:100.100.100.100:5555")); 212 213 // Wrong protocol, hostname, or port should never match. 214 EXPECT_FALSE(t.MatchesTarget("100.100.100")); 215 EXPECT_FALSE(t.MatchesTarget("100.100.100.100:")); 216 EXPECT_FALSE(t.MatchesTarget("100.100.100.100:-1")); 217 EXPECT_FALSE(t.MatchesTarget("100.100.100.100:5554")); 218 EXPECT_FALSE(t.MatchesTarget("abc:100.100.100.100")); 219 } 220 } 221