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    set_main_thread();
98    atransport t;
99
100    parse_banner("host::", &t);
101
102    ASSERT_EQ(0U, t.features().size());
103    ASSERT_EQ(kCsHost, t.GetConnectionState());
104
105    ASSERT_EQ(nullptr, t.product);
106    ASSERT_EQ(nullptr, t.model);
107    ASSERT_EQ(nullptr, t.device);
108}
109
110TEST(transport, parse_banner_product_features) {
111    atransport t;
112
113    const char banner[] =
114        "host::ro.product.name=foo;ro.product.model=bar;ro.product.device=baz;";
115    parse_banner(banner, &t);
116
117    ASSERT_EQ(kCsHost, t.GetConnectionState());
118
119    ASSERT_EQ(0U, t.features().size());
120
121    ASSERT_EQ(std::string("foo"), t.product);
122    ASSERT_EQ(std::string("bar"), t.model);
123    ASSERT_EQ(std::string("baz"), t.device);
124}
125
126TEST(transport, parse_banner_features) {
127    atransport t;
128
129    const char banner[] =
130        "host::ro.product.name=foo;ro.product.model=bar;ro.product.device=baz;"
131        "features=woodly,doodly";
132    parse_banner(banner, &t);
133
134    ASSERT_EQ(kCsHost, t.GetConnectionState());
135
136    ASSERT_EQ(2U, t.features().size());
137    ASSERT_TRUE(t.has_feature("woodly"));
138    ASSERT_TRUE(t.has_feature("doodly"));
139
140    ASSERT_EQ(std::string("foo"), t.product);
141    ASSERT_EQ(std::string("bar"), t.model);
142    ASSERT_EQ(std::string("baz"), t.device);
143}
144
145TEST(transport, test_matches_target) {
146    std::string serial = "foo";
147    std::string devpath = "/path/to/bar";
148    std::string product = "test_product";
149    std::string model = "test_model";
150    std::string device = "test_device";
151
152    atransport t;
153    t.serial = &serial[0];
154    t.devpath = &devpath[0];
155    t.product = &product[0];
156    t.model = &model[0];
157    t.device = &device[0];
158
159    // These tests should not be affected by the transport type.
160    for (TransportType type : {kTransportAny, kTransportLocal}) {
161        t.type = type;
162
163        EXPECT_TRUE(t.MatchesTarget(serial));
164        EXPECT_TRUE(t.MatchesTarget(devpath));
165        EXPECT_TRUE(t.MatchesTarget("product:" + product));
166        EXPECT_TRUE(t.MatchesTarget("model:" + model));
167        EXPECT_TRUE(t.MatchesTarget("device:" + device));
168
169        // Product, model, and device don't match without the prefix.
170        EXPECT_FALSE(t.MatchesTarget(product));
171        EXPECT_FALSE(t.MatchesTarget(model));
172        EXPECT_FALSE(t.MatchesTarget(device));
173    }
174}
175
176TEST(transport, test_matches_target_local) {
177    std::string serial = "100.100.100.100:5555";
178
179    atransport t;
180    t.serial = &serial[0];
181
182    // Network address matching should only be used for local transports.
183    for (TransportType type : {kTransportAny, kTransportLocal}) {
184        t.type = type;
185        bool should_match = (type == kTransportLocal);
186
187        EXPECT_EQ(should_match, t.MatchesTarget("100.100.100.100"));
188        EXPECT_EQ(should_match, t.MatchesTarget("tcp:100.100.100.100"));
189        EXPECT_EQ(should_match, t.MatchesTarget("tcp:100.100.100.100:5555"));
190        EXPECT_EQ(should_match, t.MatchesTarget("udp:100.100.100.100"));
191        EXPECT_EQ(should_match, t.MatchesTarget("udp:100.100.100.100:5555"));
192
193        // Wrong protocol, hostname, or port should never match.
194        EXPECT_FALSE(t.MatchesTarget("100.100.100"));
195        EXPECT_FALSE(t.MatchesTarget("100.100.100.100:"));
196        EXPECT_FALSE(t.MatchesTarget("100.100.100.100:-1"));
197        EXPECT_FALSE(t.MatchesTarget("100.100.100.100:5554"));
198        EXPECT_FALSE(t.MatchesTarget("abc:100.100.100.100"));
199    }
200}
201