aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/tools/singlejar/combiners_test.cc
diff options
context:
space:
mode:
authorGravatar Sasha Smundak <asmundak@google.com>2016-07-27 17:05:11 +0000
committerGravatar Adam Michael <ajmichael@google.com>2016-07-28 18:36:29 -0400
commitde63c6f89798b3ce2db02b81bd8c139341ad0868 (patch)
treecb241c75723b09205bf3778fbea79567d643cde2 /src/tools/singlejar/combiners_test.cc
parenta1a31ff6d16811dc72df32861bd1c1a98e104f02 (diff)
Initial checkin of the combiner classes.
-- MOS_MIGRATED_REVID=128597707
Diffstat (limited to 'src/tools/singlejar/combiners_test.cc')
-rw-r--r--src/tools/singlejar/combiners_test.cc193
1 files changed, 193 insertions, 0 deletions
diff --git a/src/tools/singlejar/combiners_test.cc b/src/tools/singlejar/combiners_test.cc
new file mode 100644
index 0000000000..9b6701c9ea
--- /dev/null
+++ b/src/tools/singlejar/combiners_test.cc
@@ -0,0 +1,193 @@
+// Copyright 2016 The Bazel Authors. All rights reserved.
+//
+// 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 "src/tools/singlejar/combiners.h"
+
+#include "src/tools/singlejar/input_jar.h"
+#include "src/tools/singlejar/zip_headers.h"
+#include "src/tools/singlejar/zlib_interface.h"
+#include "gtest/gtest.h"
+
+namespace {
+
+static const char kTag1Contents[] = "<tag1>Contents1</tag1>";
+static const char kTag2Contents[] = "<tag2>Contents2</tag2>";
+static const char kCombinedXmlContents[] =
+ "<toplevel>\n<tag1>Contents1</tag1><tag2>Contents2</tag2></toplevel>\n";
+static const char kConcatenatedContents[] =
+ "<tag1>Contents1</tag1><tag2>Contents2</tag2>";
+const uint8_t kPoison = 0xFA;
+
+// A test fixture is used because test case setup is needed.
+class CombinersTest : public ::testing::Test {
+ protected:
+ static void SetUpTestCase() {
+ ASSERT_EQ(0, chdir(getenv("TEST_TMPDIR")));
+ ASSERT_TRUE(CreateFile("tag1.xml", kTag1Contents));
+ ASSERT_TRUE(CreateFile("tag2.xml", kTag2Contents));
+ ASSERT_EQ(0, system("zip -qm combiners.zip tag1.xml tag2.xml"));
+ }
+
+ static void TearDownTestCase() { system("rm -f xmls.zip"); }
+
+ static bool CreateFile(const char *filename, const char *contents) {
+ FILE *fp = fopen(filename, "wb");
+ size_t contents_size = strlen(contents);
+ if (fp == nullptr || fwrite(contents, contents_size, 1, fp) != 1 ||
+ fclose(fp)) {
+ perror(filename);
+ return false;
+ }
+ return true;
+ }
+};
+
+// Test Concatenator.
+TEST_F(CombinersTest, ConcatenatorSmall) {
+ InputJar input_jar;
+ Concatenator concatenator("concat");
+ ASSERT_TRUE(input_jar.Open("combiners.zip"));
+ const LH *lh;
+ const CDH *cdh;
+ while ((cdh = input_jar.NextEntry(&lh))) {
+ if (cdh->file_name_is("tag1.xml") || cdh->file_name_is("tag2.xml")) {
+ ASSERT_TRUE(concatenator.Merge(cdh, lh));
+ }
+ }
+
+ // Create output, verify Local Header contents.
+ LH *entry = reinterpret_cast<LH *>(concatenator.OutputEntry());
+ EXPECT_TRUE(entry->is());
+ EXPECT_EQ(20, entry->version());
+ EXPECT_EQ(Z_DEFLATED, entry->compression_method());
+ uint64_t original_size = entry->uncompressed_file_size();
+ uint64_t compressed_size = entry->compressed_file_size();
+ EXPECT_EQ(strlen(kConcatenatedContents), original_size);
+ EXPECT_LE(compressed_size, original_size);
+ EXPECT_TRUE(entry->file_name_is("concat"));
+ EXPECT_EQ(0, entry->extra_fields_length());
+
+ // Decompress and check contents.
+ Inflater inflater;
+ inflater.DataToInflate(entry->data(), compressed_size);
+ uint8_t buffer[256];
+ memset(buffer, kPoison, sizeof(buffer));
+ ASSERT_EQ(Z_STREAM_END, inflater.Inflate((buffer), sizeof(buffer)));
+ EXPECT_EQ(kPoison, buffer[original_size]);
+ EXPECT_EQ(kConcatenatedContents,
+ std::string(reinterpret_cast<char *>(buffer), original_size));
+
+ free(reinterpret_cast<void *>(entry));
+}
+
+// Tests that Concatenator creates huge (>4GB original/compressed sizes)
+// correctly. This test is slow.
+TEST_F(CombinersTest, ConcatenatorHuge) {
+ Concatenator concatenator("huge");
+
+ // Append 5,000,000,000 bytes to the concatenator.
+ const int kBufSize = 1000000;
+ char *buf = reinterpret_cast<char *>(malloc(kBufSize));
+ memset(buf, kPoison, kBufSize);
+ for (int i = 0; i < 5000; ++i) {
+ concatenator.Append(buf, kBufSize);
+ }
+ free(buf);
+
+ // Now hope that we have enough memory :-)
+ LH *entry = reinterpret_cast<LH *>(concatenator.OutputEntry());
+ ASSERT_NE(nullptr, entry);
+ ASSERT_TRUE(entry->is());
+ ASSERT_EQ(20, entry->version());
+ EXPECT_EQ(Z_DEFLATED, entry->compression_method());
+ uint64_t original_size = entry->uncompressed_file_size();
+ uint64_t compressed_size = entry->compressed_file_size();
+ ASSERT_EQ(5000000000, original_size);
+ ASSERT_LE(compressed_size, original_size);
+ free(reinterpret_cast<void *>(entry));
+}
+
+// Test XmlCombiner.
+TEST_F(CombinersTest, XmlCombiner) {
+ InputJar input_jar;
+ XmlCombiner xml_combiner("combined.xml", "toplevel");
+ ASSERT_TRUE(input_jar.Open("combiners.zip"));
+ const LH *lh;
+ const CDH *cdh;
+ while ((cdh = input_jar.NextEntry(&lh))) {
+ if (cdh->file_name_is("tag1.xml") || cdh->file_name_is("tag2.xml")) {
+ ASSERT_TRUE(xml_combiner.Merge(cdh, lh));
+ }
+ }
+
+ // Create output, verify Local Header contents.
+ LH *entry = reinterpret_cast<LH *>(xml_combiner.OutputEntry());
+ EXPECT_TRUE(entry->is());
+ EXPECT_EQ(20, entry->version());
+ EXPECT_EQ(Z_DEFLATED, entry->compression_method());
+ uint64_t original_size = entry->uncompressed_file_size();
+ uint64_t compressed_size = entry->compressed_file_size();
+ EXPECT_EQ(strlen(kCombinedXmlContents), original_size);
+ EXPECT_LE(compressed_size, original_size);
+ EXPECT_TRUE(entry->file_name_is("combined.xml"));
+ EXPECT_EQ(0, entry->extra_fields_length());
+
+ // Decompress and check contents.
+ Inflater inflater;
+ inflater.DataToInflate(entry->data(), compressed_size);
+ uint8_t buffer[256];
+ memset(buffer, kPoison, sizeof(buffer));
+ ASSERT_EQ(Z_STREAM_END, inflater.Inflate((buffer), sizeof(buffer)));
+ EXPECT_EQ(kPoison, buffer[original_size]);
+ EXPECT_EQ(kCombinedXmlContents,
+ std::string(reinterpret_cast<char *>(buffer), original_size));
+
+ free(reinterpret_cast<void *>(entry));
+}
+// Test PropertyCombiner.
+TEST_F(CombinersTest, PropertyCombiner) {
+ static char kProperties[] =
+ "name=value\n"
+ "name_str=value_str\n";
+ PropertyCombiner property_combiner("properties");
+ property_combiner.AddProperty("name", "value");
+ property_combiner.AddProperty(std::string("name_str"),
+ std::string("value_str"));
+
+ // Create output, verify Local Header contents.
+ LH *entry = reinterpret_cast<LH *>(property_combiner.OutputEntry());
+ EXPECT_TRUE(entry->is());
+ EXPECT_EQ(20, entry->version());
+ EXPECT_EQ(Z_DEFLATED, entry->compression_method());
+ uint64_t original_size = entry->uncompressed_file_size();
+ uint64_t compressed_size = entry->compressed_file_size();
+ EXPECT_EQ(strlen(kProperties), original_size);
+ EXPECT_LE(compressed_size, original_size);
+ EXPECT_EQ("properties", entry->file_name_string());
+ EXPECT_EQ(0, entry->extra_fields_length());
+
+ // Decompress and check contents.
+ Inflater inflater;
+ inflater.DataToInflate(entry->data(), compressed_size);
+ uint8_t buffer[256];
+ memset(buffer, kPoison, sizeof(buffer));
+ ASSERT_EQ(Z_STREAM_END, inflater.Inflate((buffer), sizeof(buffer)));
+ EXPECT_EQ(kPoison, buffer[original_size]);
+ EXPECT_EQ(kProperties,
+ std::string(reinterpret_cast<char *>(buffer), original_size));
+
+ free(reinterpret_cast<void *>(entry));
+}
+
+} // namespace