|  | // Copyright 2014 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "components/cryptauth/wire_message.h" | 
|  |  | 
|  | #include <stdint.h> | 
|  |  | 
|  | #include "base/strings/string_util.h" | 
|  | #include "testing/gtest/include/gtest/gtest.h" | 
|  |  | 
|  | namespace cryptauth { | 
|  |  | 
|  | class CryptAuthWireMessageTest : public testing::Test { | 
|  | protected: | 
|  | CryptAuthWireMessageTest() {} | 
|  | ~CryptAuthWireMessageTest() override {} | 
|  |  | 
|  | private: | 
|  | DISALLOW_COPY_AND_ASSIGN(CryptAuthWireMessageTest); | 
|  | }; | 
|  |  | 
|  | TEST(CryptAuthWireMessageTest, Deserialize_EmptyMessage) { | 
|  | bool is_incomplete; | 
|  | std::unique_ptr<WireMessage> message = | 
|  | WireMessage::Deserialize(std::string(), &is_incomplete); | 
|  | EXPECT_TRUE(is_incomplete); | 
|  | EXPECT_FALSE(message); | 
|  | } | 
|  |  | 
|  | TEST(CryptAuthWireMessageTest, Deserialize_IncompleteHeader) { | 
|  | bool is_incomplete; | 
|  | std::unique_ptr<WireMessage> message = | 
|  | WireMessage::Deserialize("\3", &is_incomplete); | 
|  | EXPECT_TRUE(is_incomplete); | 
|  | EXPECT_FALSE(message); | 
|  | } | 
|  |  | 
|  | TEST(CryptAuthWireMessageTest, Deserialize_UnexpectedMessageFormatVersion) { | 
|  | bool is_incomplete; | 
|  | // Version 2 is below the minimum supported version. | 
|  | std::unique_ptr<WireMessage> message = | 
|  | WireMessage::Deserialize("\2\1\1", &is_incomplete); | 
|  | EXPECT_FALSE(is_incomplete); | 
|  | EXPECT_FALSE(message); | 
|  | } | 
|  |  | 
|  | TEST(CryptAuthWireMessageTest, Deserialize_BodyOfSizeZero) { | 
|  | bool is_incomplete; | 
|  | std::unique_ptr<WireMessage> message = | 
|  | WireMessage::Deserialize(std::string("\3\0\0", 3), &is_incomplete); | 
|  | EXPECT_FALSE(is_incomplete); | 
|  | EXPECT_FALSE(message); | 
|  | } | 
|  |  | 
|  | TEST(CryptAuthWireMessageTest, Deserialize_IncompleteBody) { | 
|  | bool is_incomplete; | 
|  | std::unique_ptr<WireMessage> message = | 
|  | WireMessage::Deserialize(std::string("\3\0\5", 3), &is_incomplete); | 
|  | EXPECT_TRUE(is_incomplete); | 
|  | EXPECT_FALSE(message); | 
|  | } | 
|  |  | 
|  | TEST(CryptAuthWireMessageTest, Deserialize_BodyLongerThanSpecifiedInHeader) { | 
|  | bool is_incomplete; | 
|  | std::unique_ptr<WireMessage> message = WireMessage::Deserialize( | 
|  | std::string("\3\0\5", 3) + "123456", &is_incomplete); | 
|  | EXPECT_FALSE(is_incomplete); | 
|  | EXPECT_FALSE(message); | 
|  | } | 
|  |  | 
|  | TEST(CryptAuthWireMessageTest, Deserialize_BodyIsNotValidJSON) { | 
|  | bool is_incomplete; | 
|  | std::unique_ptr<WireMessage> message = WireMessage::Deserialize( | 
|  | std::string("\3\0\5", 3) + "12345", &is_incomplete); | 
|  | EXPECT_FALSE(is_incomplete); | 
|  | EXPECT_FALSE(message); | 
|  | } | 
|  |  | 
|  | TEST(CryptAuthWireMessageTest, Deserialize_BodyIsNotADictionary) { | 
|  | bool is_incomplete; | 
|  | std::string header("\3\0\x15", 3); | 
|  | std::string bytes = | 
|  | header + "[{\"payload\": \"YQ==\"}]"; | 
|  | std::unique_ptr<WireMessage> message = | 
|  | WireMessage::Deserialize(bytes, &is_incomplete); | 
|  | EXPECT_FALSE(is_incomplete); | 
|  | EXPECT_FALSE(message); | 
|  | } | 
|  |  | 
|  | TEST(CryptAuthWireMessageTest, Deserialize_NonEncryptedMessage) { | 
|  | bool is_incomplete; | 
|  | std::string header("\3\0\x02", 3); | 
|  | std::string bytes = header + "{}"; | 
|  | std::unique_ptr<WireMessage> message = | 
|  | WireMessage::Deserialize(bytes, &is_incomplete); | 
|  | EXPECT_FALSE(is_incomplete); | 
|  | ASSERT_TRUE(message); | 
|  | EXPECT_EQ("{}", message->body()); | 
|  | } | 
|  |  | 
|  | TEST(CryptAuthWireMessageTest, Deserialize_BodyHasEmptyPayload) { | 
|  | bool is_incomplete; | 
|  | std::string header("\3\0\x29", 3); | 
|  | std::string bytes = header | 
|  | + "{\"payload\": \"\", \"feature\": \"testFeature\"}"; | 
|  | std::unique_ptr<WireMessage> message = | 
|  | WireMessage::Deserialize(bytes, &is_incomplete); | 
|  | EXPECT_FALSE(is_incomplete); | 
|  | EXPECT_FALSE(message); | 
|  | } | 
|  |  | 
|  | TEST(CryptAuthWireMessageTest, Deserialize_PayloadIsNotBase64Encoded) { | 
|  | bool is_incomplete; | 
|  | std::string header("\3\0\x30", 3); | 
|  | std::string bytes = | 
|  | header + "{\"payload\": \"garbage\", \"feature\": \"testFeature\"}"; | 
|  | std::unique_ptr<WireMessage> message = | 
|  | WireMessage::Deserialize(bytes, &is_incomplete); | 
|  | EXPECT_FALSE(is_incomplete); | 
|  | EXPECT_FALSE(message); | 
|  | } | 
|  |  | 
|  | TEST(CryptAuthWireMessageTest, Deserialize_ValidMessage) { | 
|  | bool is_incomplete; | 
|  | std::string header("\3\0\x2d", 3); | 
|  | std::string bytes = | 
|  | header + "{\"payload\": \"YQ==\", \"feature\": \"testFeature\"}"; | 
|  | std::unique_ptr<WireMessage> message = | 
|  | WireMessage::Deserialize(bytes, &is_incomplete); | 
|  | EXPECT_FALSE(is_incomplete); | 
|  | ASSERT_TRUE(message); | 
|  | EXPECT_EQ("a", message->payload()); | 
|  | EXPECT_EQ("testFeature", message->feature()); | 
|  | } | 
|  |  | 
|  | TEST(CryptAuthWireMessageTest, Deserialize_ValidMessageWithBase64UrlEncoding) { | 
|  | bool is_incomplete; | 
|  | std::string header("\3\0\x2d", 3); | 
|  | std::string bytes = | 
|  | header + "{\"payload\": \"_-Y=\", \"feature\": \"testFeature\"}"; | 
|  | std::unique_ptr<WireMessage> message = | 
|  | WireMessage::Deserialize(bytes, &is_incomplete); | 
|  | EXPECT_FALSE(is_incomplete); | 
|  | ASSERT_TRUE(message); | 
|  | EXPECT_EQ("\xFF\xE6", message->payload()); | 
|  | EXPECT_EQ("testFeature", message->feature()); | 
|  | } | 
|  |  | 
|  | TEST(CryptAuthWireMessageTest, Deserialize_ValidMessageWithExtraUnknownFields) { | 
|  | bool is_incomplete; | 
|  | std::string header("\3\0\x4c", 3); | 
|  | std::string bytes = header + | 
|  | "{" | 
|  | "  \"payload\": \"YQ==\"," | 
|  | "  \"feature\": \"testFeature\"," | 
|  | "  \"unexpected\": \"surprise!\"" | 
|  | "}"; | 
|  | std::unique_ptr<WireMessage> message = | 
|  | WireMessage::Deserialize(bytes, &is_incomplete); | 
|  | EXPECT_FALSE(is_incomplete); | 
|  | ASSERT_TRUE(message); | 
|  | EXPECT_EQ("a", message->payload()); | 
|  | EXPECT_EQ("testFeature", message->feature()); | 
|  | } | 
|  |  | 
|  | TEST(CryptAuthWireMessageTest, Deserialize_SizeEquals0x01FF) { | 
|  | // Create a message with a body of 0x01FF bytes to test the size contained in | 
|  | // the header is parsed correctly. | 
|  | std::string header("\3\x01\xff", 3); | 
|  | char json_template[] = "{" | 
|  | "  \"payload\":\"YQ==\"," | 
|  | "  \"feature\": \"testFeature\"," | 
|  | "  \"filler\":\"$1\"" | 
|  | "}"; | 
|  | // Add 3 to the size to take into account the "$1" and NUL terminator ("\0") | 
|  | // characters in |json_template|. | 
|  | uint16_t filler_size = 0x01ff - sizeof(json_template) + 3; | 
|  | std::string filler(filler_size, 'F'); | 
|  |  | 
|  | std::string body = base::ReplaceStringPlaceholders( | 
|  | json_template, std::vector<std::string>(1u, filler), nullptr); | 
|  | std::string serialized_message = header + body; | 
|  |  | 
|  | bool is_incomplete; | 
|  | std::unique_ptr<WireMessage> message = | 
|  | WireMessage::Deserialize(serialized_message, &is_incomplete); | 
|  | EXPECT_FALSE(is_incomplete); | 
|  | ASSERT_TRUE(message); | 
|  | EXPECT_EQ("a", message->payload()); | 
|  | EXPECT_EQ("testFeature", message->feature()); | 
|  | } | 
|  |  | 
|  | TEST(CryptAuthWireMessageTest, Serialize_WithoutFeature) { | 
|  | bool is_incomplete; | 
|  | std::string header("\3\0\x13", 3); | 
|  | std::string bytes = header + "{\"payload\": \"YQ==\"}"; | 
|  | std::unique_ptr<WireMessage> message = | 
|  | WireMessage::Deserialize(bytes, &is_incomplete); | 
|  | EXPECT_FALSE(is_incomplete); | 
|  | EXPECT_TRUE(message); | 
|  | EXPECT_EQ("a", message->payload()); | 
|  |  | 
|  | // If unspecified, the default feature is "easy_unlock" for backwards | 
|  | // compatibility. | 
|  | EXPECT_EQ("easy_unlock", message->feature()); | 
|  | } | 
|  |  | 
|  | TEST(CryptAuthWireMessageTest, Serialize_FailsWithoutPayload) { | 
|  | WireMessage message1(std::string(), "example id"); | 
|  | std::string bytes = message1.Serialize(); | 
|  | EXPECT_TRUE(bytes.empty()); | 
|  | } | 
|  |  | 
|  | }  // namespace cryptauth |