1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "gtest/gtest.h"
6 #include "osp/msgs/osp_messages.h"
7 
8 using openscreen::msgs::CborEncodeBuffer;
9 using openscreen::msgs::HttpHeader;
10 using openscreen::msgs::PresentationConnectionMessage;
11 using openscreen::msgs::PresentationStartRequest;
12 using openscreen::msgs::PresentationUrlAvailabilityRequest;
13 
14 namespace openscreen {
15 namespace osp {
16 
17 // TODO(btolsch): This is in the current (draft) spec, but should we actually
18 // allow this?
TEST(PresentationMessagesTest,EncodeRequestZeroUrls)19 TEST(PresentationMessagesTest, EncodeRequestZeroUrls) {
20   uint8_t buffer[256];
21   std::vector<std::string> urls;
22   ssize_t bytes_out = EncodePresentationUrlAvailabilityRequest(
23       PresentationUrlAvailabilityRequest{3, urls}, buffer, sizeof(buffer));
24   ASSERT_LE(bytes_out, static_cast<ssize_t>(sizeof(buffer)));
25   ASSERT_GT(bytes_out, 0);
26 
27   PresentationUrlAvailabilityRequest decoded_request;
28   ssize_t bytes_read = DecodePresentationUrlAvailabilityRequest(
29       buffer, bytes_out, &decoded_request);
30   ASSERT_EQ(bytes_read, bytes_out);
31   EXPECT_EQ(3u, decoded_request.request_id);
32   EXPECT_EQ(urls, decoded_request.urls);
33 }
34 
TEST(PresentationMessagesTest,EncodeRequestOneUrl)35 TEST(PresentationMessagesTest, EncodeRequestOneUrl) {
36   uint8_t buffer[256];
37   std::vector<std::string> urls{"https://example.com/receiver.html"};
38   ssize_t bytes_out = EncodePresentationUrlAvailabilityRequest(
39       PresentationUrlAvailabilityRequest{7, urls}, buffer, sizeof(buffer));
40   ASSERT_LE(bytes_out, static_cast<ssize_t>(sizeof(buffer)));
41   ASSERT_GT(bytes_out, 0);
42 
43   PresentationUrlAvailabilityRequest decoded_request;
44   ssize_t bytes_read = DecodePresentationUrlAvailabilityRequest(
45       buffer, bytes_out, &decoded_request);
46   ASSERT_EQ(bytes_read, bytes_out);
47   EXPECT_EQ(7u, decoded_request.request_id);
48   EXPECT_EQ(urls, decoded_request.urls);
49 }
50 
TEST(PresentationMessagesTest,EncodeRequestMultipleUrls)51 TEST(PresentationMessagesTest, EncodeRequestMultipleUrls) {
52   uint8_t buffer[256];
53   std::vector<std::string> urls{"https://example.com/receiver.html",
54                                 "https://openscreen.org/demo_receiver.html",
55                                 "https://turt.le/asdfXCV"};
56   ssize_t bytes_out = EncodePresentationUrlAvailabilityRequest(
57       PresentationUrlAvailabilityRequest{7, urls}, buffer, sizeof(buffer));
58   ASSERT_LE(bytes_out, static_cast<ssize_t>(sizeof(buffer)));
59   ASSERT_GT(bytes_out, 0);
60 
61   PresentationUrlAvailabilityRequest decoded_request;
62   ssize_t bytes_read = DecodePresentationUrlAvailabilityRequest(
63       buffer, bytes_out, &decoded_request);
64   ASSERT_EQ(bytes_read, bytes_out);
65   EXPECT_EQ(7u, decoded_request.request_id);
66   EXPECT_EQ(urls, decoded_request.urls);
67 }
68 
TEST(PresentationMessagesTest,EncodeWouldOverflow)69 TEST(PresentationMessagesTest, EncodeWouldOverflow) {
70   uint8_t buffer[40];
71   std::vector<std::string> urls{"https://example.com/receiver.html"};
72   ssize_t bytes_out = EncodePresentationUrlAvailabilityRequest(
73       PresentationUrlAvailabilityRequest{7, urls}, buffer, sizeof(buffer));
74   ASSERT_GT(bytes_out, static_cast<ssize_t>(sizeof(buffer)));
75 }
76 
77 // TODO(btolsch): Expand invalid utf8 testing to good/bad files and fuzzing.
TEST(PresentationMessagesTest,EncodeInvalidUtf8)78 TEST(PresentationMessagesTest, EncodeInvalidUtf8) {
79   uint8_t buffer[256];
80   std::vector<std::string> urls{"\xc0"};
81   ssize_t bytes_out = EncodePresentationUrlAvailabilityRequest(
82       PresentationUrlAvailabilityRequest{7, urls}, buffer, sizeof(buffer));
83   ASSERT_GT(0, bytes_out);
84 }
85 
TEST(PresentationMessagesTest,DecodeInvalidUtf8)86 TEST(PresentationMessagesTest, DecodeInvalidUtf8) {
87   uint8_t buffer[256];
88   std::vector<std::string> urls{"https://example.com/receiver.html"};
89   ssize_t bytes_out = EncodePresentationUrlAvailabilityRequest(
90       PresentationUrlAvailabilityRequest{7, urls}, buffer, sizeof(buffer));
91   ASSERT_LE(bytes_out, static_cast<ssize_t>(sizeof(buffer)));
92   ASSERT_GT(bytes_out, 0);
93   // Manually change a character in the url string to be non-utf8.
94   buffer[30] = 0xc0;
95 
96   PresentationUrlAvailabilityRequest decoded_request;
97   ssize_t bytes_read = DecodePresentationUrlAvailabilityRequest(
98       buffer, bytes_out, &decoded_request);
99   ASSERT_GT(0, bytes_read);
100 }
101 
TEST(PresentationMessagesTest,InitiationRequest)102 TEST(PresentationMessagesTest, InitiationRequest) {
103   uint8_t buffer[256];
104   const std::string kPresentationId = "lksdjfloiqwerlkjasdlfq";
105   const std::string kPresentationUrl = "https://example.com/receiver.html";
106   std::vector<HttpHeader> headers;
107   ssize_t bytes_out = EncodePresentationStartRequest(
108       PresentationStartRequest{13, kPresentationId, kPresentationUrl, headers},
109       buffer, sizeof(buffer));
110   ASSERT_LE(bytes_out, static_cast<ssize_t>(sizeof(buffer)));
111   ASSERT_GT(bytes_out, 0);
112 
113   PresentationStartRequest decoded_request;
114   ssize_t bytes_read =
115       DecodePresentationStartRequest(buffer, bytes_out, &decoded_request);
116   ASSERT_EQ(bytes_read, bytes_out);
117   EXPECT_EQ(13u, decoded_request.request_id);
118   EXPECT_EQ(kPresentationId, decoded_request.presentation_id);
119   EXPECT_EQ(kPresentationUrl, decoded_request.url);
120   EXPECT_EQ(0, (int)decoded_request.headers.size());
121 }
122 
TEST(PresentationMessagesTest,InitiationRequestWithoutOptional)123 TEST(PresentationMessagesTest, InitiationRequestWithoutOptional) {
124   uint8_t buffer[256];
125   const std::string kPresentationId = "lksdjfloiqwerlkjasdlfq";
126   const std::string kPresentationUrl = "https://example.com/receiver.html";
127   std::vector<HttpHeader> headers;
128   ssize_t bytes_out = EncodePresentationStartRequest(
129       PresentationStartRequest{13, kPresentationId, kPresentationUrl, headers},
130       buffer, sizeof(buffer));
131   ASSERT_LE(bytes_out, static_cast<ssize_t>(sizeof(buffer)));
132   ASSERT_GT(bytes_out, 0);
133 
134   PresentationStartRequest decoded_request;
135   ssize_t bytes_read =
136       DecodePresentationStartRequest(buffer, bytes_out, &decoded_request);
137   ASSERT_EQ(bytes_read, bytes_out);
138   EXPECT_EQ(13u, decoded_request.request_id);
139   EXPECT_EQ(kPresentationId, decoded_request.presentation_id);
140   EXPECT_EQ(kPresentationUrl, decoded_request.url);
141   EXPECT_EQ(0, (int)decoded_request.headers.size());
142 }
143 
TEST(PresentationMessagesTest,EncodeConnectionMessageString)144 TEST(PresentationMessagesTest, EncodeConnectionMessageString) {
145   uint8_t buffer[256];
146   PresentationConnectionMessage message;
147   message.connection_id = 1234;
148   message.message.which =
149       PresentationConnectionMessage::Message::Which::kString;
150   new (&message.message.str) std::string("test message as a string");
151   ssize_t bytes_out =
152       EncodePresentationConnectionMessage(message, buffer, sizeof(buffer));
153   ASSERT_LE(bytes_out, static_cast<ssize_t>(sizeof(buffer)));
154   ASSERT_GT(bytes_out, 0);
155 
156   PresentationConnectionMessage decoded_message;
157   ssize_t bytes_read =
158       DecodePresentationConnectionMessage(buffer, bytes_out, &decoded_message);
159   ASSERT_GT(bytes_read, 0);
160   EXPECT_EQ(bytes_read, bytes_out);
161   EXPECT_EQ(message.connection_id, decoded_message.connection_id);
162   ASSERT_EQ(message.message.which, decoded_message.message.which);
163   EXPECT_EQ(message.message.str, decoded_message.message.str);
164 }
165 
TEST(PresentationMessagesTest,EncodeConnectionMessageBytes)166 TEST(PresentationMessagesTest, EncodeConnectionMessageBytes) {
167   uint8_t buffer[256];
168   PresentationConnectionMessage message;
169   message.connection_id = 1234;
170   message.message.which = PresentationConnectionMessage::Message::Which::kBytes;
171   new (&message.message.bytes)
172       std::vector<uint8_t>{0, 1, 2, 3, 255, 254, 253, 86, 71, 0, 0, 1, 0, 2};
173   ssize_t bytes_out =
174       EncodePresentationConnectionMessage(message, buffer, sizeof(buffer));
175   ASSERT_LE(bytes_out, static_cast<ssize_t>(sizeof(buffer)));
176   ASSERT_GT(bytes_out, 0);
177 
178   PresentationConnectionMessage decoded_message;
179   ssize_t bytes_read =
180       DecodePresentationConnectionMessage(buffer, bytes_out, &decoded_message);
181   ASSERT_GT(bytes_read, 0);
182   EXPECT_EQ(bytes_read, bytes_out);
183   EXPECT_EQ(message.connection_id, decoded_message.connection_id);
184   ASSERT_EQ(message.message.which, decoded_message.message.which);
185   EXPECT_EQ(message.message.bytes, decoded_message.message.bytes);
186 }
187 
TEST(PresentationMessagesTest,CborEncodeBufferSmall)188 TEST(PresentationMessagesTest, CborEncodeBufferSmall) {
189   std::vector<std::string> urls{"https://example.com/receiver.html"};
190   PresentationUrlAvailabilityRequest request{7, urls};
191   CborEncodeBuffer buffer;
192   ASSERT_TRUE(EncodePresentationUrlAvailabilityRequest(request, &buffer));
193   EXPECT_LT(buffer.size(), CborEncodeBuffer::kDefaultInitialEncodeBufferSize);
194 
195   PresentationUrlAvailabilityRequest decoded_request;
196   size_t bytes_read = DecodePresentationUrlAvailabilityRequest(
197       buffer.data() + 1, buffer.size() - 1, &decoded_request);
198   EXPECT_EQ(bytes_read, buffer.size() - 1);
199   EXPECT_EQ(request.request_id, decoded_request.request_id);
200   EXPECT_EQ(request.urls, decoded_request.urls);
201 }
202 
TEST(PresentationMessagesTest,CborEncodeBufferMedium)203 TEST(PresentationMessagesTest, CborEncodeBufferMedium) {
204   std::string url = "https://example.com/receiver.html";
205   std::vector<std::string> urls{};
206   for (int i = 0; i < 100; ++i) {
207     urls.push_back(url);
208   }
209   PresentationUrlAvailabilityRequest request{7, urls};
210   CborEncodeBuffer buffer;
211   ASSERT_TRUE(EncodePresentationUrlAvailabilityRequest(request, &buffer));
212   EXPECT_GT(buffer.size(), CborEncodeBuffer::kDefaultInitialEncodeBufferSize);
213 
214   PresentationUrlAvailabilityRequest decoded_request;
215   ssize_t bytes_read = DecodePresentationUrlAvailabilityRequest(
216       buffer.data() + 1, buffer.size() - 1, &decoded_request);
217   ASSERT_GT(bytes_read, 0);
218   EXPECT_EQ(static_cast<size_t>(bytes_read), buffer.size() - 1);
219   EXPECT_EQ(request.request_id, decoded_request.request_id);
220   EXPECT_EQ(request.urls, decoded_request.urls);
221 }
222 
TEST(PresentationMessagesTest,CborEncodeBufferTooLarge)223 TEST(PresentationMessagesTest, CborEncodeBufferTooLarge) {
224   std::vector<std::string> urls{"https://example.com/receiver.html"};
225   PresentationUrlAvailabilityRequest request{7, urls};
226   CborEncodeBuffer buffer{10, 30};
227   ASSERT_FALSE(EncodePresentationUrlAvailabilityRequest(request, &buffer));
228 }
229 
230 }  // namespace osp
231 }  // namespace openscreen
232