aboutsummaryrefslogtreecommitdiff
path: root/src/headerparser_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/headerparser_test.cc')
-rw-r--r--src/headerparser_test.cc210
1 files changed, 210 insertions, 0 deletions
diff --git a/src/headerparser_test.cc b/src/headerparser_test.cc
new file mode 100644
index 0000000..66ed824
--- /dev/null
+++ b/src/headerparser_test.cc
@@ -0,0 +1,210 @@
+// Copyright 2008 Google Inc.
+// Author: Lincoln Smith
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <config.h>
+#include "headerparser.h"
+#include <stdlib.h> // rand, srand
+#include <string>
+#include <vector>
+#include "testing.h"
+#include "varint_bigendian.h"
+
+namespace open_vcdiff {
+namespace { // anonymous
+
+using std::vector;
+
+class VCDiffHeaderParserTest : public testing::Test {
+ protected:
+ typedef std::string string;
+
+ static const int kTestSize = 1024;
+
+ VCDiffHeaderParserTest() : parser(NULL) { }
+
+ virtual ~VCDiffHeaderParserTest() {
+ delete parser;
+ }
+
+ virtual void SetUp() {
+ srand(1); // make sure each test uses the same data set
+ }
+
+ void StartParsing() {
+ parser = new VCDiffHeaderParser(
+ encoded_buffer_.data(),
+ encoded_buffer_.data() + encoded_buffer_.size());
+ EXPECT_EQ(encoded_buffer_.data(), parser->UnparsedData());
+ }
+
+ void VerifyByte(unsigned char expected_value) {
+ unsigned char decoded_byte = 0;
+ const char* prior_position = parser->UnparsedData();
+ EXPECT_TRUE(parser->ParseByte(&decoded_byte));
+ EXPECT_EQ(expected_value, decoded_byte);
+ EXPECT_EQ(RESULT_SUCCESS, parser->GetResult());
+ EXPECT_EQ(prior_position + sizeof(unsigned char),
+ parser->UnparsedData());
+ }
+
+ void VerifyInt32(int32_t expected_value) {
+ int32_t decoded_integer = 0;
+ const char* prior_position = parser->UnparsedData();
+ EXPECT_TRUE(parser->ParseInt32("decoded int32", &decoded_integer));
+ EXPECT_EQ(expected_value, decoded_integer);
+ EXPECT_EQ(RESULT_SUCCESS, parser->GetResult());
+ EXPECT_EQ(prior_position + VarintBE<int32_t>::Length(decoded_integer),
+ parser->UnparsedData());
+ }
+
+ void VerifyUInt32(uint32_t expected_value) {
+ uint32_t decoded_integer = 0;
+ const char* prior_position = parser->UnparsedData();
+ EXPECT_TRUE(parser->ParseUInt32("decoded uint32", &decoded_integer));
+ EXPECT_EQ(expected_value, decoded_integer);
+ EXPECT_EQ(RESULT_SUCCESS, parser->GetResult());
+ EXPECT_EQ(prior_position + VarintBE<int64_t>::Length(decoded_integer),
+ parser->UnparsedData());
+ }
+
+ void VerifyChecksum(VCDChecksum expected_value) {
+ VCDChecksum decoded_checksum = 0;
+ const char* prior_position = parser->UnparsedData();
+ EXPECT_TRUE(parser->ParseChecksum("decoded checksum", &decoded_checksum));
+ EXPECT_EQ(expected_value, decoded_checksum);
+ EXPECT_EQ(RESULT_SUCCESS, parser->GetResult());
+ EXPECT_EQ(prior_position + VarintBE<int64_t>::Length(decoded_checksum),
+ parser->UnparsedData());
+ }
+
+ string encoded_buffer_;
+ VCDiffHeaderParser* parser;
+};
+
+TEST_F(VCDiffHeaderParserTest, ParseRandomBytes) {
+ vector<unsigned char> byte_values;
+ for (int i = 0; i < kTestSize; ++i) {
+ unsigned char random_byte = PortableRandomInRange<unsigned char>(0xFF);
+ encoded_buffer_.push_back(random_byte);
+ byte_values.push_back(random_byte);
+ }
+ StartParsing();
+ for (int position = 0; position < kTestSize; ++position) {
+ VerifyByte(byte_values[position]);
+ }
+ unsigned char decoded_byte = 0;
+ EXPECT_FALSE(parser->ParseByte(&decoded_byte));
+ EXPECT_EQ(RESULT_END_OF_DATA, parser->GetResult());
+ EXPECT_EQ(encoded_buffer_.data() + encoded_buffer_.size(),
+ parser->UnparsedData());
+}
+
+TEST_F(VCDiffHeaderParserTest, ParseRandomInt32) {
+ vector<int32_t> integer_values;
+ for (int i = 0; i < kTestSize; ++i) {
+ int32_t random_integer = PortableRandomInRange<int32_t>(0x7FFFFFFF);
+ VarintBE<int32_t>::AppendToString(random_integer, &encoded_buffer_);
+ integer_values.push_back(random_integer);
+ }
+ StartParsing();
+ for (int i = 0; i < kTestSize; ++i) {
+ VerifyInt32(integer_values[i]);
+ }
+ int32_t decoded_integer = 0;
+ EXPECT_FALSE(parser->ParseInt32("decoded integer", &decoded_integer));
+ EXPECT_EQ(RESULT_END_OF_DATA, parser->GetResult());
+ EXPECT_EQ(encoded_buffer_.data() + encoded_buffer_.size(),
+ parser->UnparsedData());
+}
+
+TEST_F(VCDiffHeaderParserTest, ParseRandomUInt32) {
+ vector<uint32_t> integer_values;
+ for (int i = 0; i < kTestSize; ++i) {
+ uint32_t random_integer = PortableRandomInRange<uint32_t>(0xFFFFFFFF);
+ VarintBE<int64_t>::AppendToString(random_integer, &encoded_buffer_);
+ integer_values.push_back(random_integer);
+ }
+ StartParsing();
+ uint32_t decoded_integer = 0;
+ for (int i = 0; i < kTestSize; ++i) {
+ VerifyUInt32(integer_values[i]);
+ }
+ EXPECT_FALSE(parser->ParseUInt32("decoded integer", &decoded_integer));
+ EXPECT_EQ(RESULT_END_OF_DATA, parser->GetResult());
+ EXPECT_EQ(encoded_buffer_.data() + encoded_buffer_.size(),
+ parser->UnparsedData());
+}
+
+TEST_F(VCDiffHeaderParserTest, ParseRandomChecksum) {
+ vector<VCDChecksum> checksum_values;
+ for (int i = 0; i < kTestSize; ++i) {
+ VCDChecksum random_checksum =
+ PortableRandomInRange<VCDChecksum>(0xFFFFFFFF);
+ VarintBE<int64_t>::AppendToString(random_checksum, &encoded_buffer_);
+ checksum_values.push_back(random_checksum);
+ }
+ StartParsing();
+ for (int i = 0; i < kTestSize; ++i) {
+ VerifyChecksum(checksum_values[i]);
+ }
+ VCDChecksum decoded_checksum = 0;
+ EXPECT_FALSE(parser->ParseChecksum("decoded checksum", &decoded_checksum));
+ EXPECT_EQ(RESULT_END_OF_DATA, parser->GetResult());
+ EXPECT_EQ(encoded_buffer_.data() + encoded_buffer_.size(),
+ parser->UnparsedData());
+}
+
+TEST_F(VCDiffHeaderParserTest, ParseMixed) {
+ VarintBE<int64_t>::AppendToString(0xCAFECAFE, &encoded_buffer_);
+ encoded_buffer_.push_back(0xFF);
+ VarintBE<int32_t>::AppendToString(0x02020202, &encoded_buffer_);
+ VarintBE<int64_t>::AppendToString(0xCAFECAFE, &encoded_buffer_);
+ encoded_buffer_.push_back(0xFF);
+ encoded_buffer_.push_back(0xFF);
+ StartParsing();
+ VerifyUInt32(0xCAFECAFE);
+ VerifyByte(0xFF);
+ VerifyInt32(0x02020202);
+ VerifyChecksum(0xCAFECAFE);
+ int32_t incomplete_int32 = 0;
+ EXPECT_FALSE(parser->ParseInt32("incomplete Varint", &incomplete_int32));
+ EXPECT_EQ(0, incomplete_int32);
+ EXPECT_EQ(RESULT_END_OF_DATA, parser->GetResult());
+ EXPECT_EQ(encoded_buffer_.data() + encoded_buffer_.size() - 2,
+ parser->UnparsedData());
+}
+
+TEST_F(VCDiffHeaderParserTest, ParseInvalidVarint) {
+ // Start with a byte that has the continuation bit plus a high-order bit set
+ encoded_buffer_.append(1, static_cast<char>(0xC0));
+ // Add too many bytes with continuation bits
+ encoded_buffer_.append(6, static_cast<char>(0x80));
+ StartParsing();
+ int32_t invalid_int32 = 0;
+ EXPECT_FALSE(parser->ParseInt32("invalid Varint", &invalid_int32));
+ EXPECT_EQ(0, invalid_int32);
+ EXPECT_EQ(RESULT_ERROR, parser->GetResult());
+ EXPECT_EQ(encoded_buffer_.data(), parser->UnparsedData());
+ // After the parse failure, any other call to Parse... should return an error,
+ // even though there is still a byte that could be read as valid.
+ unsigned char decoded_byte = 0;
+ EXPECT_FALSE(parser->ParseByte(&decoded_byte));
+ EXPECT_EQ(0, decoded_byte);
+ EXPECT_EQ(RESULT_ERROR, parser->GetResult());
+ EXPECT_EQ(encoded_buffer_.data(), parser->UnparsedData());
+}
+
+} // namespace open_vcdiff
+} // anonymous namespace