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 #include "fdevent/fdevent_test.h"
23 
TEST(ConnectionStateTest,to_string)24 TEST(ConnectionStateTest, to_string) {
25     ASSERT_EQ("offline", to_string(ConnectionState::kCsOffline));
26     ASSERT_EQ("bootloader", to_string(ConnectionState::kCsBootloader));
27     ASSERT_EQ("device", to_string(ConnectionState::kCsDevice));
28     ASSERT_EQ("host", to_string(ConnectionState::kCsHost));
29     ASSERT_EQ("recovery", to_string(ConnectionState::kCsRecovery));
30     ASSERT_EQ("rescue", to_string(ConnectionState::kCsRescue));
31     ASSERT_EQ("sideload", to_string(ConnectionState::kCsSideload));
32     ASSERT_EQ("unauthorized", to_string(ConnectionState::kCsUnauthorized));
33     ASSERT_EQ("authorizing", to_string(ConnectionState::kCsAuthorizing));
34     ASSERT_EQ("connecting", to_string(ConnectionState::kCsConnecting));
35 }
36 
37 struct TransportTest : public FdeventTest {};
38 
DisconnectFunc(void * arg,atransport *)39 static void DisconnectFunc(void* arg, atransport*) {
40     int* count = reinterpret_cast<int*>(arg);
41     ++*count;
42 }
43 
TEST_F(TransportTest,RunDisconnects)44 TEST_F(TransportTest, RunDisconnects) {
45     atransport t;
46     // RunDisconnects() can be called with an empty atransport.
47     t.RunDisconnects();
48 
49     int count = 0;
50     adisconnect disconnect;
51     disconnect.func = DisconnectFunc;
52     disconnect.opaque = &count;
53     t.AddDisconnect(&disconnect);
54     t.RunDisconnects();
55     ASSERT_EQ(1, count);
56 
57     // disconnect should have been removed automatically.
58     t.RunDisconnects();
59     ASSERT_EQ(1, count);
60 
61     count = 0;
62     t.AddDisconnect(&disconnect);
63     t.RemoveDisconnect(&disconnect);
64     t.RunDisconnects();
65     ASSERT_EQ(0, count);
66 }
67 
TEST_F(TransportTest,SetFeatures)68 TEST_F(TransportTest, SetFeatures) {
69     atransport t;
70     ASSERT_EQ(0U, t.features().size());
71 
72     t.SetFeatures(FeatureSetToString(FeatureSet{"foo"}));
73     ASSERT_EQ(1U, t.features().size());
74     ASSERT_TRUE(t.has_feature("foo"));
75 
76     t.SetFeatures(FeatureSetToString(FeatureSet{"foo", "bar"}));
77     ASSERT_EQ(2U, t.features().size());
78     ASSERT_TRUE(t.has_feature("foo"));
79     ASSERT_TRUE(t.has_feature("bar"));
80 
81     t.SetFeatures(FeatureSetToString(FeatureSet{"foo", "bar", "foo"}));
82     ASSERT_LE(2U, t.features().size());
83     ASSERT_TRUE(t.has_feature("foo"));
84     ASSERT_TRUE(t.has_feature("bar"));
85 
86     t.SetFeatures(FeatureSetToString(FeatureSet{"bar", "baz"}));
87     ASSERT_EQ(2U, t.features().size());
88     ASSERT_FALSE(t.has_feature("foo"));
89     ASSERT_TRUE(t.has_feature("bar"));
90     ASSERT_TRUE(t.has_feature("baz"));
91 
92     t.SetFeatures("");
93     ASSERT_EQ(0U, t.features().size());
94 }
95 
TEST_F(TransportTest,parse_banner_no_features)96 TEST_F(TransportTest, parse_banner_no_features) {
97     atransport t;
98 
99     parse_banner("host::", &t);
100 
101     ASSERT_EQ(0U, t.features().size());
102     ASSERT_EQ(kCsHost, t.GetConnectionState());
103 
104     ASSERT_EQ(std::string(), t.product);
105     ASSERT_EQ(std::string(), t.model);
106     ASSERT_EQ(std::string(), t.device);
107 }
108 
TEST_F(TransportTest,parse_banner_product_features)109 TEST_F(TransportTest, parse_banner_product_features) {
110     atransport t;
111 
112     const char banner[] =
113         "host::ro.product.name=foo;ro.product.model=bar;ro.product.device=baz;";
114     parse_banner(banner, &t);
115 
116     ASSERT_EQ(kCsHost, t.GetConnectionState());
117 
118     ASSERT_EQ(0U, t.features().size());
119 
120     ASSERT_EQ(std::string("foo"), t.product);
121     ASSERT_EQ(std::string("bar"), t.model);
122     ASSERT_EQ(std::string("baz"), t.device);
123 }
124 
TEST_F(TransportTest,parse_banner_features)125 TEST_F(TransportTest, parse_banner_features) {
126     atransport t;
127     const char banner[] =
128         "host::ro.product.name=foo;ro.product.model=bar;ro.product.device=baz;"
129         "features=woodly,doodly";
130     parse_banner(banner, &t);
131 
132     ASSERT_EQ(kCsHost, t.GetConnectionState());
133 
134     ASSERT_EQ(2U, t.features().size());
135     ASSERT_TRUE(t.has_feature("woodly"));
136     ASSERT_TRUE(t.has_feature("doodly"));
137 
138     ASSERT_EQ(std::string("foo"), t.product);
139     ASSERT_EQ(std::string("bar"), t.model);
140     ASSERT_EQ(std::string("baz"), t.device);
141 }
142 
143 #if ADB_HOST
TEST_F(TransportTest,test_matches_target)144 TEST_F(TransportTest, test_matches_target) {
145     std::string serial = "foo";
146     std::string devpath = "/path/to/bar";
147     std::string product = "test_product";
148     std::string model = "test_model";
149     std::string device = "test_device";
150 
151     atransport t;
152     t.serial = &serial[0];
153     t.devpath = &devpath[0];
154     t.product = &product[0];
155     t.model = &model[0];
156     t.device = &device[0];
157 
158     // These tests should not be affected by the transport type.
159     for (TransportType type : {kTransportAny, kTransportLocal}) {
160         t.type = type;
161 
162         EXPECT_TRUE(t.MatchesTarget(serial));
163         EXPECT_TRUE(t.MatchesTarget(devpath));
164         EXPECT_TRUE(t.MatchesTarget("product:" + product));
165         EXPECT_TRUE(t.MatchesTarget("model:" + model));
166         EXPECT_TRUE(t.MatchesTarget("device:" + device));
167 
168         // Product, model, and device don't match without the prefix.
169         EXPECT_FALSE(t.MatchesTarget(product));
170         EXPECT_FALSE(t.MatchesTarget(model));
171         EXPECT_FALSE(t.MatchesTarget(device));
172     }
173 }
174 
TEST_F(TransportTest,test_matches_target_local)175 TEST_F(TransportTest, test_matches_target_local) {
176     std::string serial = "100.100.100.100:5555";
177 
178     atransport t;
179     t.serial = &serial[0];
180 
181     // Network address matching should only be used for local transports.
182     for (TransportType type : {kTransportAny, kTransportLocal}) {
183         t.type = type;
184         bool should_match = (type == kTransportLocal);
185 
186         EXPECT_EQ(should_match, t.MatchesTarget("100.100.100.100"));
187         EXPECT_EQ(should_match, t.MatchesTarget("tcp:100.100.100.100"));
188         EXPECT_EQ(should_match, t.MatchesTarget("tcp:100.100.100.100:5555"));
189         EXPECT_EQ(should_match, t.MatchesTarget("udp:100.100.100.100"));
190         EXPECT_EQ(should_match, t.MatchesTarget("udp:100.100.100.100:5555"));
191 
192         // Wrong protocol, hostname, or port should never match.
193         EXPECT_FALSE(t.MatchesTarget("100.100.100"));
194         EXPECT_FALSE(t.MatchesTarget("100.100.100.100:"));
195         EXPECT_FALSE(t.MatchesTarget("100.100.100.100:-1"));
196         EXPECT_FALSE(t.MatchesTarget("100.100.100.100:5554"));
197         EXPECT_FALSE(t.MatchesTarget("abc:100.100.100.100"));
198     }
199 }
200 #endif
201