• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 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 "cast/protocol/castv2/validation.h"
6 
7 #include <numeric>
8 #include <string>
9 
10 #include "absl/strings/string_view.h"
11 #include "cast/protocol/castv2/receiver_examples/get_app_availability_data.h"
12 #include "cast/protocol/castv2/receiver_examples/get_app_availability_response_data.h"
13 #include "cast/protocol/castv2/receiver_examples/launch_data.h"
14 #include "cast/protocol/castv2/receiver_examples/stop_data.h"
15 #include "cast/protocol/castv2/receiver_schema_data.h"
16 #include "cast/protocol/castv2/streaming_examples/answer_data.h"
17 #include "cast/protocol/castv2/streaming_examples/capabilities_response_data.h"
18 #include "cast/protocol/castv2/streaming_examples/get_capabilities_data.h"
19 #include "cast/protocol/castv2/streaming_examples/get_status_data.h"
20 #include "cast/protocol/castv2/streaming_examples/offer_data.h"
21 #include "cast/protocol/castv2/streaming_examples/rpc_data.h"
22 #include "cast/protocol/castv2/streaming_examples/status_response_data.h"
23 #include "gmock/gmock.h"
24 #include "gtest/gtest.h"
25 #include "json/value.h"
26 #include "platform/base/error.h"
27 #include "util/json/json_serialization.h"
28 #include "util/osp_logging.h"
29 #include "util/std_util.h"
30 #include "util/stringprintf.h"
31 
32 namespace openscreen {
33 namespace cast {
34 
35 namespace {
36 
37 constexpr char kEmptyJson[] = "{}";
38 
39 // Schema format string, that allows for specifying definitions,
40 // properties, and required fields.
41 constexpr char kSchemaFormat[] = R"({
42   "$schema": "http://json-schema.org/draft-07/schema#",
43   "$id": "https://something/app_schema_data.h",
44   "definitions": {
45     %s
46   },
47   "type": "object",
48   "properties": {
49     %s
50   },
51   "required": [%s]
52 })";
53 
54 // Fields used for an appId containing schema
55 constexpr char kAppIdDefinition[] = R"("app_id": {
56     "type": "string",
57     "enum": ["0F5096E8", "85CDB22F"]
58   })";
59 constexpr char kAppIdName[] = "\"appId\"";
60 constexpr char kAppIdProperty[] =
61     R"(  "appId": {"$ref": "#/definitions/app_id"})";
62 
63 // Teest documents containing an appId.
64 constexpr char kValidAppIdDocument[] = R"({ "appId": "0F5096E8" })";
65 constexpr char kInvalidAppIdDocument[] = R"({ "appId": "FooBar" })";
66 
BuildSchema(const char * definitions,const char * properties,const char * required)67 std::string BuildSchema(const char* definitions,
68                         const char* properties,
69                         const char* required) {
70   return StringPrintf(kSchemaFormat, definitions, properties, required);
71 }
72 
TestValidate(absl::string_view document,absl::string_view schema)73 bool TestValidate(absl::string_view document, absl::string_view schema) {
74   OSP_DVLOG << "Validating document: \"" << document << "\" against schema: \""
75             << schema << "\"";
76   ErrorOr<Json::Value> document_root = json::Parse(document);
77   EXPECT_TRUE(document_root.is_value());
78   ErrorOr<Json::Value> schema_root = json::Parse(schema);
79   EXPECT_TRUE(schema_root.is_value());
80 
81   std::vector<Error> errors =
82       Validate(document_root.value(), schema_root.value());
83   return errors.empty();
84 }
85 
GetEmptySchema()86 const std::string& GetEmptySchema() {
87   static const std::string kEmptySchema = BuildSchema("", "", "");
88   return kEmptySchema;
89 }
90 
GetAppSchema()91 const std::string& GetAppSchema() {
92   static const std::string kAppIdSchema =
93       BuildSchema(kAppIdDefinition, kAppIdProperty, kAppIdName);
94   return kAppIdSchema;
95 }
96 
97 class StreamingValidationTest : public testing::TestWithParam<const char*> {};
98 class ReceiverValidationTest : public testing::TestWithParam<const char*> {};
99 
100 }  // namespace
101 
TEST(ValidationTest,EmptyPassesEmpty)102 TEST(ValidationTest, EmptyPassesEmpty) {
103   EXPECT_TRUE(TestValidate(kEmptyJson, kEmptyJson));
104 }
105 
TEST(ValidationTest,EmptyPassesBasicSchema)106 TEST(ValidationTest, EmptyPassesBasicSchema) {
107   EXPECT_TRUE(TestValidate(kEmptyJson, GetEmptySchema()));
108 }
109 
TEST(ValidationTest,EmptyFailsAppIdSchema)110 TEST(ValidationTest, EmptyFailsAppIdSchema) {
111   EXPECT_FALSE(TestValidate(kEmptyJson, GetAppSchema()));
112 }
113 
TEST(ValidationTest,InvalidAppIdFailsAppIdSchema)114 TEST(ValidationTest, InvalidAppIdFailsAppIdSchema) {
115   EXPECT_FALSE(TestValidate(kInvalidAppIdDocument, GetAppSchema()));
116 }
117 
TEST(ValidationTest,ValidAppIdPassesAppIdSchema)118 TEST(ValidationTest, ValidAppIdPassesAppIdSchema) {
119   EXPECT_TRUE(TestValidate(kValidAppIdDocument, GetAppSchema()));
120 }
121 
TEST(ValidationTest,InvalidAppIdPassesEmptySchema)122 TEST(ValidationTest, InvalidAppIdPassesEmptySchema) {
123   EXPECT_TRUE(TestValidate(kInvalidAppIdDocument, GetEmptySchema()));
124 }
125 
TEST(ValidationTest,ValidAppIdPassesEmptySchema)126 TEST(ValidationTest, ValidAppIdPassesEmptySchema) {
127   EXPECT_TRUE(TestValidate(kValidAppIdDocument, GetEmptySchema()));
128 }
129 
130 INSTANTIATE_TEST_SUITE_P(StreamingValidations,
131                          StreamingValidationTest,
132                          testing::Values(kAnswer,
133                                          kCapabilitiesResponse,
134                                          kGetCapabilities,
135                                          kGetStatus,
136                                          kOffer,
137                                          kRpc,
138                                          kStatusResponse));
139 
TEST_P(StreamingValidationTest,ExampleStreamingMessages)140 TEST_P(StreamingValidationTest, ExampleStreamingMessages) {
141   ErrorOr<Json::Value> message_root = json::Parse(GetParam());
142   EXPECT_TRUE(message_root.is_value());
143   EXPECT_TRUE(ValidateStreamingMessage(message_root.value()).empty());
144 }
145 
ExpectReceiverMessageValid(const char * message)146 void ExpectReceiverMessageValid(const char* message) {}
147 
148 INSTANTIATE_TEST_SUITE_P(ReceiverValidations,
149                          ReceiverValidationTest,
150                          testing::Values(kGetAppAvailability,
151                                          kGetAppAvailabilityResponse,
152                                          kLaunch,
153                                          kStop));
154 
TEST_P(ReceiverValidationTest,ExampleReceiverMessages)155 TEST_P(ReceiverValidationTest, ExampleReceiverMessages) {
156   ErrorOr<Json::Value> message_root = json::Parse(GetParam());
157   EXPECT_TRUE(message_root.is_value());
158   EXPECT_TRUE(ValidateReceiverMessage(message_root.value()).empty());
159 }
160 }  // namespace cast
161 }  // namespace openscreen
162