1 #include "lldb/Utility/UriParser.h"
2 #include "gtest/gtest.h"
3 
4 using namespace lldb_private;
5 
6 // result strings (scheme/hostname/port/path) passed into UriParser::Parse
7 // are initialized to kAsdf so we can verify that they are unmodified if the
8 // URI is invalid
9 static const char *kAsdf = "asdf";
10 
11 class UriTestCase {
12 public:
13   UriTestCase(const char *uri, const char *scheme, const char *hostname,
14               llvm::Optional<uint16_t> port, const char *path)
15       : m_uri(uri), m_result(true), m_scheme(scheme), m_hostname(hostname),
16         m_port(port), m_path(path) {}
17 
18   UriTestCase(const char *uri)
19       : m_uri(uri), m_result(false), m_scheme(kAsdf), m_hostname(kAsdf),
20         m_port(1138), m_path(kAsdf) {}
21 
22   const char *m_uri;
23   bool m_result;
24   const char *m_scheme;
25   const char *m_hostname;
26   llvm::Optional<uint16_t> m_port;
27   const char *m_path;
28 };
29 
30 #define VALIDATE                                                               \
31   llvm::StringRef scheme(kAsdf);                                               \
32   llvm::StringRef hostname(kAsdf);                                             \
33   llvm::Optional<uint16_t> port(1138);                                         \
34   llvm::StringRef path(kAsdf);                                                 \
35   EXPECT_EQ(testCase.m_result,                                                 \
36             UriParser::Parse(testCase.m_uri, scheme, hostname, port, path));   \
37   EXPECT_STREQ(testCase.m_scheme, scheme.str().c_str());                       \
38   EXPECT_STREQ(testCase.m_hostname, hostname.str().c_str());                   \
39   EXPECT_EQ(testCase.m_port, port);                                            \
40   EXPECT_STREQ(testCase.m_path, path.str().c_str());
41 
42 TEST(UriParserTest, Minimal) {
43   const UriTestCase testCase("x://y", "x", "y", llvm::None, "/");
44   VALIDATE
45 }
46 
47 TEST(UriParserTest, MinimalPort) {
48   const UriTestCase testCase("x://y:1", "x", "y", 1, "/");
49   llvm::StringRef scheme(kAsdf);
50   llvm::StringRef hostname(kAsdf);
51   llvm::Optional<uint16_t> port(1138);
52   llvm::StringRef path(kAsdf);
53   bool result = UriParser::Parse(testCase.m_uri, scheme, hostname, port, path);
54   EXPECT_EQ(testCase.m_result, result);
55 
56   EXPECT_STREQ(testCase.m_scheme, scheme.str().c_str());
57   EXPECT_STREQ(testCase.m_hostname, hostname.str().c_str());
58   EXPECT_EQ(testCase.m_port, port);
59   EXPECT_STREQ(testCase.m_path, path.str().c_str());
60 }
61 
62 TEST(UriParserTest, MinimalPath) {
63   const UriTestCase testCase("x://y/", "x", "y", llvm::None, "/");
64   VALIDATE
65 }
66 
67 TEST(UriParserTest, MinimalPortPath) {
68   const UriTestCase testCase("x://y:1/", "x", "y", 1, "/");
69   VALIDATE
70 }
71 
72 TEST(UriParserTest, LongPath) {
73   const UriTestCase testCase("x://y/abc/def/xyz", "x", "y", llvm::None,
74                              "/abc/def/xyz");
75   VALIDATE
76 }
77 
78 TEST(UriParserTest, TypicalPortPathIPv4) {
79   const UriTestCase testCase("connect://192.168.100.132:5432/", "connect",
80                              "192.168.100.132", 5432, "/");
81   VALIDATE;
82 }
83 
84 TEST(UriParserTest, TypicalPortPathIPv6) {
85   const UriTestCase testCase(
86       "connect://[2601:600:107f:db64:a42b:4faa:284:3082]:5432/", "connect",
87       "2601:600:107f:db64:a42b:4faa:284:3082", 5432, "/");
88   VALIDATE;
89 }
90 
91 TEST(UriParserTest, BracketedHostnamePort) {
92   const UriTestCase testCase("connect://[192.168.100.132]:5432/", "connect",
93                              "192.168.100.132", 5432, "/");
94   llvm::StringRef scheme(kAsdf);
95   llvm::StringRef hostname(kAsdf);
96   llvm::Optional<uint16_t> port(1138);
97   llvm::StringRef path(kAsdf);
98   bool result = UriParser::Parse(testCase.m_uri, scheme, hostname, port, path);
99   EXPECT_EQ(testCase.m_result, result);
100 
101   EXPECT_STREQ(testCase.m_scheme, scheme.str().c_str());
102   EXPECT_STREQ(testCase.m_hostname, hostname.str().c_str());
103   EXPECT_EQ(testCase.m_port, port);
104   EXPECT_STREQ(testCase.m_path, path.str().c_str());
105 }
106 
107 TEST(UriParserTest, BracketedHostname) {
108   const UriTestCase testCase("connect://[192.168.100.132]", "connect",
109                              "192.168.100.132", llvm::None, "/");
110   VALIDATE
111 }
112 
113 TEST(UriParserTest, BracketedHostnameWithPortIPv4) {
114   // Android device over IPv4: port is a part of the hostname.
115   const UriTestCase testCase("connect://[192.168.100.132:1234]", "connect",
116                              "192.168.100.132:1234", llvm::None, "/");
117   VALIDATE
118 }
119 
120 TEST(UriParserTest, BracketedHostnameWithPortIPv6) {
121   // Android device over IPv6: port is a part of the hostname.
122   const UriTestCase testCase(
123       "connect://[[2601:600:107f:db64:a42b:4faa:284]:1234]", "connect",
124       "[2601:600:107f:db64:a42b:4faa:284]:1234", llvm::None, "/");
125   VALIDATE
126 }
127 
128 TEST(UriParserTest, BracketedHostnameWithColon) {
129   const UriTestCase testCase("connect://[192.168.100.132:5555]:1234", "connect",
130                              "192.168.100.132:5555", 1234, "/");
131   VALIDATE
132 }
133 
134 TEST(UriParserTest, SchemeHostSeparator) {
135   const UriTestCase testCase("x:/y");
136   VALIDATE
137 }
138 
139 TEST(UriParserTest, SchemeHostSeparator2) {
140   const UriTestCase testCase("x:y");
141   VALIDATE
142 }
143 
144 TEST(UriParserTest, SchemeHostSeparator3) {
145   const UriTestCase testCase("x//y");
146   VALIDATE
147 }
148 
149 TEST(UriParserTest, SchemeHostSeparator4) {
150   const UriTestCase testCase("x/y");
151   VALIDATE
152 }
153 
154 TEST(UriParserTest, BadPort) {
155   const UriTestCase testCase("x://y:a/");
156   VALIDATE
157 }
158 
159 TEST(UriParserTest, BadPort2) {
160   const UriTestCase testCase("x://y:5432a/");
161   VALIDATE
162 }
163 
164 TEST(UriParserTest, Empty) {
165   const UriTestCase testCase("");
166   VALIDATE
167 }
168 
169 TEST(UriParserTest, PortOverflow) {
170   const UriTestCase testCase("x://"
171                              "y:"
172                              "0123456789012345678901234567890123456789012345678"
173                              "9012345678901234567890123456789012345678901234567"
174                              "89/");
175   VALIDATE
176 }
177