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
23TEST(transport, kick_transport) {
24  atransport t;
25  static size_t kick_count;
26  kick_count = 0;
27  // Mutate some member so we can test that the function is run.
28  t.SetKickFunction([](atransport* trans) { kick_count++; });
29  ASSERT_FALSE(t.IsKicked());
30  t.Kick();
31  ASSERT_TRUE(t.IsKicked());
32  ASSERT_EQ(1u, kick_count);
33  // A transport can only be kicked once.
34  t.Kick();
35  ASSERT_TRUE(t.IsKicked());
36  ASSERT_EQ(1u, kick_count);
37}
38
39static void DisconnectFunc(void* arg, atransport*) {
40    int* count = reinterpret_cast<int*>(arg);
41    ++*count;
42}
43
44TEST(transport, 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
68TEST(transport, 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_EQ(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
96TEST(transport, 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.connection_state);
103
104    ASSERT_EQ(nullptr, t.product);
105    ASSERT_EQ(nullptr, t.model);
106    ASSERT_EQ(nullptr, t.device);
107}
108
109TEST(transport, 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.connection_state);
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
125TEST(transport, parse_banner_features) {
126    atransport t;
127
128    const char banner[] =
129        "host::ro.product.name=foo;ro.product.model=bar;ro.product.device=baz;"
130        "features=woodly,doodly";
131    parse_banner(banner, &t);
132
133    ASSERT_EQ(kCsHost, t.connection_state);
134
135    ASSERT_EQ(2U, t.features().size());
136    ASSERT_TRUE(t.has_feature("woodly"));
137    ASSERT_TRUE(t.has_feature("doodly"));
138
139    ASSERT_EQ(std::string("foo"), t.product);
140    ASSERT_EQ(std::string("bar"), t.model);
141    ASSERT_EQ(std::string("baz"), t.device);
142}
143
144TEST(transport, 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
175TEST(transport, 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