You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@orc.apache.org by om...@apache.org on 2015/07/06 23:52:41 UTC
[12/23] orc git commit: ORC-23. Simplify directory structure.
http://git-wip-us.apache.org/repos/asf/orc/blob/7f55b453/c++/test/TestCompression.cc
----------------------------------------------------------------------
diff --git a/c++/test/TestCompression.cc b/c++/test/TestCompression.cc
new file mode 100644
index 0000000..0f6eb3c
--- /dev/null
+++ b/c++/test/TestCompression.cc
@@ -0,0 +1,647 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 "Compression.hh"
+#include "Exceptions.hh"
+#include "OrcTest.hh"
+#include "wrap/gtest-wrapper.h"
+
+#include <cstdio>
+#include <fstream>
+#include <iostream>
+#include <sstream>
+
+#include "zlib.h"
+#include "wrap/snappy-wrapper.h"
+
+namespace orc {
+
+ class TestCompression : public ::testing::Test {
+ public:
+ ~TestCompression();
+ protected:
+ // Per-test-case set-up.
+ static void SetUpTestCase() {
+ simpleFile = "simple-file.binary";
+ remove(simpleFile);
+ std::ofstream file;
+ file.exceptions(std::ofstream::failbit | std::ofstream::badbit);
+ file.open(simpleFile,
+ std::ios::out | std::ios::binary | std::ios::trunc);
+ for(unsigned int i = 0; i < 200; ++i) {
+ file.put(static_cast<char>(i));
+ }
+ file.close();
+ }
+
+ // Per-test-case tear-down.
+ static void TearDownTestCase() {
+ simpleFile = 0;
+ }
+
+ static const char *simpleFile;
+ };
+
+ const char *TestCompression::simpleFile;
+
+ TestCompression::~TestCompression() {
+ // PASS
+ }
+
+ TEST_F(TestCompression, testPrintBufferEmpty) {
+ std::ostringstream str;
+ printBuffer(str, 0, 0);
+ EXPECT_EQ("", str.str());
+ }
+
+ TEST_F(TestCompression, testPrintBufferSmall) {
+ std::vector<char> buffer(10);
+ std::ostringstream str;
+ for(size_t i=0; i < 10; ++i) {
+ buffer[i] = static_cast<char>(i);
+ }
+ printBuffer(str, buffer.data(), 10);
+ EXPECT_EQ("0000000 00 01 02 03 04 05 06 07 08 09\n", str.str());
+ }
+
+ TEST_F(TestCompression, testPrintBufferLong) {
+ std::vector<char> buffer(300);
+ std::ostringstream str;
+ for(size_t i=0; i < 300; ++i) {
+ buffer[i] = static_cast<char>(i);
+ }
+ printBuffer(str, buffer.data(), 300);
+ std::ostringstream expected;
+ expected << "0000000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10"
+ << " 11 12 13 14 15 16 17\n"
+ << "0000018 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28"
+ << " 29 2a 2b 2c 2d 2e 2f\n"
+ << "0000030 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40"
+ << " 41 42 43 44 45 46 47\n"
+ << "0000048 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58"
+ << " 59 5a 5b 5c 5d 5e 5f\n"
+ << "0000060 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70"
+ << " 71 72 73 74 75 76 77\n"
+ << "0000078 78 79 7a 7b 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88"
+ << " 89 8a 8b 8c 8d 8e 8f\n"
+ << "0000090 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f a0"
+ << " a1 a2 a3 a4 a5 a6 a7\n"
+ << "00000a8 a8 a9 aa ab ac ad ae af b0 b1 b2 b3 b4 b5 b6 b7 b8"
+ << " b9 ba bb bc bd be bf\n"
+ << "00000c0 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0"
+ << " d1 d2 d3 d4 d5 d6 d7\n"
+ << "00000d8 d8 d9 da db dc dd de df e0 e1 e2 e3 e4 e5 e6 e7 e8"
+ << " e9 ea eb ec ed ee ef\n"
+ << "00000f0 f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff 00"
+ << " 01 02 03 04 05 06 07\n"
+ << "0000108 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18"
+ << " 19 1a 1b 1c 1d 1e 1f\n"
+ << "0000120 20 21 22 23 24 25 26 27 28 29 2a 2b\n";
+ EXPECT_EQ(expected.str(), str.str());
+ }
+
+ TEST_F(TestCompression, testArrayBackup) {
+ std::vector<char> bytes(200);
+ for(size_t i=0; i < bytes.size(); ++i) {
+ bytes[i] = static_cast<char>(i);
+ }
+ SeekableArrayInputStream stream(bytes.data(), bytes.size(), 20);
+ const void *ptr;
+ int len;
+ ASSERT_THROW(stream.BackUp(10), std::logic_error);
+ EXPECT_EQ(true, stream.Next(&ptr, &len));
+ EXPECT_EQ(bytes.data(), static_cast<const char *>(ptr));
+ EXPECT_EQ(20, len);
+ stream.BackUp(0);
+ EXPECT_EQ(true, stream.Next(&ptr, &len));
+ EXPECT_EQ(bytes.data() + 20, static_cast<const char *>(ptr));
+ EXPECT_EQ(20, len);
+ stream.BackUp(10);
+ for(unsigned int i=0; i < 8; ++i) {
+ EXPECT_EQ(true, stream.Next(&ptr, &len));
+ unsigned int consumedBytes = 30 + 20 * i;
+ EXPECT_EQ(bytes.data() + consumedBytes, static_cast<const char *>(ptr));
+ EXPECT_EQ(consumedBytes + 20, stream.ByteCount());
+ EXPECT_EQ(20, len);
+ }
+ EXPECT_EQ(true, stream.Next(&ptr, &len));
+ EXPECT_EQ(bytes.data() + 190, static_cast<const char *>(ptr));
+ EXPECT_EQ(10, len);
+ EXPECT_EQ(true, !stream.Next(&ptr, &len));
+ EXPECT_EQ(0, len);
+ ASSERT_THROW(stream.BackUp(30), std::logic_error);
+ EXPECT_EQ(200, stream.ByteCount());
+ }
+
+ TEST_F(TestCompression, testArraySkip) {
+ std::vector<char> bytes(200);
+ for(size_t i=0; i < bytes.size(); ++i) {
+ bytes[i] = static_cast<char>(i);
+ }
+ SeekableArrayInputStream stream(bytes.data(), bytes.size(), 20);
+ const void *ptr;
+ int len;
+ ASSERT_EQ(true, stream.Next(&ptr, &len));
+ EXPECT_EQ(bytes.data(), static_cast<const char *>(ptr));
+ EXPECT_EQ(20, len);
+ ASSERT_EQ(true, !stream.Skip(-10));
+ ASSERT_EQ(true, stream.Skip(80));
+ ASSERT_EQ(true, stream.Next(&ptr, &len));
+ EXPECT_EQ(bytes.data() + 100, static_cast<const char *>(ptr));
+ EXPECT_EQ(20, len);
+ ASSERT_EQ(true, stream.Skip(80));
+ ASSERT_EQ(true, !stream.Next(&ptr, &len));
+ ASSERT_EQ(true, !stream.Skip(181));
+ EXPECT_EQ("SeekableArrayInputStream 200 of 200", stream.getName());
+ }
+
+ TEST_F(TestCompression, testArrayCombo) {
+ std::vector<char> bytes(200);
+ for(size_t i=0; i < bytes.size(); ++i) {
+ bytes[i] = static_cast<char>(i);
+ }
+ SeekableArrayInputStream stream(bytes.data(), bytes.size(), 20);
+ const void *ptr;
+ int len;
+ ASSERT_EQ(true, stream.Next(&ptr, &len));
+ EXPECT_EQ(bytes.data(), static_cast<const char *>(ptr));
+ EXPECT_EQ(20, len);
+ stream.BackUp(10);
+ EXPECT_EQ(10, stream.ByteCount());
+ stream.Skip(4);
+ EXPECT_EQ(14, stream.ByteCount());
+ ASSERT_EQ(true, stream.Next(&ptr, &len));
+ EXPECT_EQ(bytes.data() + 14, static_cast<const char *>(ptr));
+ EXPECT_EQ(true, !stream.Skip(320));
+ EXPECT_EQ(200, stream.ByteCount());
+ EXPECT_EQ(true, !stream.Next(&ptr, &len));
+ }
+
+ // this checks to make sure that a given set of bytes are ascending
+ void checkBytes(const char*data, int length,
+ unsigned int startValue) {
+ for(unsigned int i=0; static_cast<int>(i) < length; ++i) {
+ EXPECT_EQ(startValue + i, static_cast<unsigned char>(data[i]))
+ << "Output wrong at " << startValue << " + " << i;
+ }
+ }
+
+ TEST_F(TestCompression, testFileBackup) {
+ SCOPED_TRACE("testFileBackup");
+ std::unique_ptr<InputStream> file = readLocalFile(simpleFile);
+ SeekableFileInputStream stream(file.get(), 0, 200, *getDefaultPool(), 20);
+ const void *ptr;
+ int len;
+ ASSERT_THROW(stream.BackUp(10), std::logic_error);
+ EXPECT_EQ(true, stream.Next(&ptr, &len));
+ EXPECT_EQ(20, len);
+ checkBytes(static_cast<const char*>(ptr), len, 0);
+ stream.BackUp(0);
+ EXPECT_EQ(true, stream.Next(&ptr, &len));
+ EXPECT_EQ(20, len);
+ checkBytes(static_cast<const char*>(ptr), len, 20);
+ stream.BackUp(10);
+ EXPECT_EQ(30, stream.ByteCount());
+ EXPECT_EQ(true, stream.Next(&ptr, &len));
+ EXPECT_EQ(10, len);
+ checkBytes(static_cast<const char*>(ptr), len, 30);
+ for(unsigned int i=0; i < 8; ++i) {
+ EXPECT_EQ(20 * i + 40, stream.ByteCount());
+ EXPECT_EQ(true, stream.Next(&ptr, &len));
+ EXPECT_EQ(20, len);
+ checkBytes(static_cast<const char*>(ptr), len, 20 * i + 40);
+ }
+ EXPECT_EQ(true, !stream.Next(&ptr, &len));
+ EXPECT_EQ(0, len);
+ ASSERT_THROW(stream.BackUp(30), std::logic_error);
+ EXPECT_EQ(200, stream.ByteCount());
+ }
+
+ TEST_F(TestCompression, testFileSkip) {
+ SCOPED_TRACE("testFileSkip");
+ std::unique_ptr<InputStream> file = readLocalFile(simpleFile);
+ SeekableFileInputStream stream(file.get(), 0, 200, *getDefaultPool(), 20);
+ const void *ptr;
+ int len;
+ ASSERT_EQ(true, stream.Next(&ptr, &len));
+ checkBytes(static_cast<const char*>(ptr), len, 0);
+ EXPECT_EQ(20, len);
+ ASSERT_EQ(true, !stream.Skip(-10));
+ ASSERT_EQ(true, stream.Skip(80));
+ ASSERT_EQ(true, stream.Next(&ptr, &len));
+ checkBytes(static_cast<const char*>(ptr), len, 100);
+ EXPECT_EQ(20, len);
+ ASSERT_EQ(true, !stream.Skip(80));
+ ASSERT_EQ(true, !stream.Next(&ptr, &len));
+ ASSERT_EQ(true, !stream.Skip(181));
+ EXPECT_EQ("simple-file.binary from 0 for 200", stream.getName());
+ }
+
+ TEST_F(TestCompression, testFileCombo) {
+ SCOPED_TRACE("testFileCombo");
+ std::unique_ptr<InputStream> file = readLocalFile(simpleFile);
+ SeekableFileInputStream stream(file.get(), 0, 200, *getDefaultPool(), 20);
+ const void *ptr;
+ int len;
+ ASSERT_EQ(true, stream.Next(&ptr, &len));
+ checkBytes(static_cast<const char*>(ptr), len, 0);
+ EXPECT_EQ(20, len);
+ stream.BackUp(10);
+ EXPECT_EQ(10, stream.ByteCount());
+ stream.Skip(4);
+ EXPECT_EQ(14, stream.ByteCount());
+ ASSERT_EQ(true, stream.Next(&ptr, &len));
+ checkBytes(static_cast<const char*>(ptr), len, 14);
+ EXPECT_EQ(true, !stream.Skip(320));
+ EXPECT_EQ(200, stream.ByteCount());
+ EXPECT_EQ(true, !stream.Next(&ptr, &len));
+ }
+
+ TEST_F(TestCompression, testFileSeek) {
+ SCOPED_TRACE("testFileSeek");
+ std::unique_ptr<InputStream> file = readLocalFile(simpleFile);
+ SeekableFileInputStream stream(file.get(), 0, 200, *getDefaultPool(), 20);
+ const void *ptr;
+ int len;
+ EXPECT_EQ(0, stream.ByteCount());
+ ASSERT_EQ(true, stream.Next(&ptr, &len));
+ checkBytes(static_cast<const char*>(ptr), len, 0);
+ EXPECT_EQ(20, len);
+ EXPECT_EQ(20, stream.ByteCount());
+ {
+ std::list<uint64_t> offsets(1, 100);
+ PositionProvider posn(offsets);
+ stream.seek(posn);
+ }
+ EXPECT_EQ(100, stream.ByteCount());
+ {
+ std::list<uint64_t> offsets(1, 5);
+ PositionProvider posn(offsets);
+ stream.seek(posn);
+ }
+ EXPECT_EQ(5, stream.ByteCount());
+ ASSERT_EQ(true, stream.Next(&ptr, &len));
+ checkBytes(static_cast<const char*>(ptr), len, 5);
+ EXPECT_EQ(20, len);
+ {
+ std::list<uint64_t> offsets(1, 201);
+ PositionProvider posn(offsets);
+ EXPECT_THROW(stream.seek(posn), std::logic_error);
+ EXPECT_EQ(200, stream.ByteCount());
+ }
+ }
+
+ TEST_F(TestCompression, testCreateNone) {
+ std::vector<char> bytes(10);
+ for(unsigned int i=0; i < bytes.size(); ++i) {
+ bytes[i] = static_cast<char>(i);
+ }
+ std::unique_ptr<SeekableInputStream> result =
+ createDecompressor(CompressionKind_NONE,
+ std::unique_ptr<SeekableInputStream>
+ (new SeekableArrayInputStream(bytes.data(),
+ bytes.size())),
+ 32768,
+ *getDefaultPool());
+ const void *ptr;
+ int length;
+ result->Next(&ptr, &length);
+ for(unsigned int i=0; i < bytes.size(); ++i) {
+ EXPECT_EQ(static_cast<char>(i), static_cast<const char*>(ptr)[i]);
+ }
+ }
+
+ TEST_F(TestCompression, testCreateLzo) {
+ const unsigned char buffer[] = {0};
+ EXPECT_THROW(createDecompressor(CompressionKind_LZO,
+ std::unique_ptr<SeekableInputStream>
+ (new SeekableArrayInputStream(buffer, 0)),
+ 32768, *getDefaultPool()),
+ NotImplementedYet);
+ }
+
+ TEST(Zlib, testCreateZlib) {
+ const unsigned char buffer[] = {0x0b, 0x0, 0x0, 0x0, 0x1, 0x2, 0x3, 0x4};
+ std::unique_ptr<SeekableInputStream> result =
+ createDecompressor(CompressionKind_ZLIB,
+ std::unique_ptr<SeekableInputStream>
+ (new SeekableArrayInputStream
+ (buffer, ARRAY_SIZE(buffer))),
+ 32768, *getDefaultPool());
+ EXPECT_EQ("zlib(SeekableArrayInputStream 0 of 8)", result->getName());
+ const void *ptr;
+ int length;
+ ASSERT_EQ(true, result->Next(&ptr, &length));
+ ASSERT_EQ(5, length);
+ for(unsigned int i=0; i < 5; ++i) {
+ EXPECT_EQ(static_cast<char>(i), static_cast<const char*>(ptr)[i]);
+ }
+ EXPECT_EQ("zlib(SeekableArrayInputStream 8 of 8)", result->getName());
+ EXPECT_EQ(5, result->ByteCount());
+ result->BackUp(3);
+ EXPECT_EQ(2, result->ByteCount());
+ ASSERT_EQ(true, result->Next(&ptr, &length));
+ ASSERT_EQ(3, length);
+ for(unsigned int i=0; i < 3; ++i) {
+ EXPECT_EQ(static_cast<char>(i+2), static_cast<const char*>(ptr)[i]);
+ }
+ }
+
+ TEST(Zlib, testLiteralBlocks) {
+ const unsigned char buffer[] = {0x19, 0x0, 0x0, 0x0, 0x1,
+ 0x2, 0x3, 0x4, 0x5, 0x6,
+ 0x7, 0x8, 0x9, 0xa, 0xb,
+ 0xb, 0x0, 0x0, 0xc, 0xd,
+ 0xe, 0xf, 0x10};
+ std::unique_ptr<SeekableInputStream> result =
+ createDecompressor(CompressionKind_ZLIB,
+ std::unique_ptr<SeekableInputStream>
+ (new SeekableArrayInputStream
+ (buffer, ARRAY_SIZE(buffer), 5)),
+ 5, *getDefaultPool());
+ EXPECT_EQ("zlib(SeekableArrayInputStream 0 of 23)", result->getName());
+ const void *ptr;
+ int length;
+ ASSERT_EQ(true, result->Next(&ptr, &length));
+ ASSERT_EQ(2, length);
+ EXPECT_EQ(0, static_cast<const char*>(ptr)[0]);
+ EXPECT_EQ(1, static_cast<const char*>(ptr)[1]);
+ ASSERT_EQ(true, result->Next(&ptr, &length));
+ ASSERT_EQ(5, length);
+ EXPECT_EQ(2, static_cast<const char*>(ptr)[0]);
+ EXPECT_EQ(3, static_cast<const char*>(ptr)[1]);
+ EXPECT_EQ(4, static_cast<const char*>(ptr)[2]);
+ EXPECT_EQ(5, static_cast<const char*>(ptr)[3]);
+ EXPECT_EQ(6, static_cast<const char*>(ptr)[4]);
+ ASSERT_EQ(true, result->Next(&ptr, &length));
+ ASSERT_EQ(5, length);
+ EXPECT_EQ(7, static_cast<const char*>(ptr)[0]);
+ EXPECT_EQ(8, static_cast<const char*>(ptr)[1]);
+ EXPECT_EQ(9, static_cast<const char*>(ptr)[2]);
+ EXPECT_EQ(10, static_cast<const char*>(ptr)[3]);
+ EXPECT_EQ(11, static_cast<const char*>(ptr)[4]);
+ ASSERT_EQ(true, result->Next(&ptr, &length));
+ ASSERT_EQ(2, length);
+ EXPECT_EQ(12, static_cast<const char*>(ptr)[0]);
+ EXPECT_EQ(13, static_cast<const char*>(ptr)[1]);
+ ASSERT_EQ(true, result->Next(&ptr, &length));
+ ASSERT_EQ(3, length);
+ EXPECT_EQ(14, static_cast<const char*>(ptr)[0]);
+ EXPECT_EQ(15, static_cast<const char*>(ptr)[1]);
+ EXPECT_EQ(16, static_cast<const char*>(ptr)[2]);
+ }
+
+ TEST(Zlib, testInflate) {
+ const unsigned char buffer [] = {0xe, 0x0, 0x0, 0x63, 0x60, 0x64, 0x62,
+ 0xc0, 0x8d, 0x0};
+ std::unique_ptr<SeekableInputStream> result =
+ createDecompressor(CompressionKind_ZLIB,
+ std::unique_ptr<SeekableInputStream>
+ (new SeekableArrayInputStream
+ (buffer, ARRAY_SIZE(buffer))), 1000,
+ *getDefaultPool());
+ const void *ptr;
+ int length;
+ ASSERT_EQ(true, result->Next(&ptr, &length));
+ ASSERT_EQ(30, length);
+ for(int i=0; i < 10; ++i) {
+ for(int j=0; j < 3; ++j) {
+ EXPECT_EQ(j, static_cast<const char*>(ptr)[i * 3 + j]);
+ }
+ }
+ }
+
+ TEST(Zlib, testInflateSequence) {
+ const unsigned char buffer[] = {0xe, 0x0, 0x0, 0x63, 0x60,
+ 0x64, 0x62, 0xc0, 0x8d, 0x0,
+ 0xe, 0x0, 0x0, 0x63, 0x60,
+ 0x64, 0x62, 0xc0, 0x8d, 0x0};
+ std::unique_ptr<SeekableInputStream> result =
+ createDecompressor(CompressionKind_ZLIB,
+ std::unique_ptr<SeekableInputStream>
+ (new SeekableArrayInputStream
+ (buffer, ARRAY_SIZE(buffer), 3)),
+ 1000,
+ *getDefaultPool());
+ const void *ptr;
+ int length;
+ ASSERT_THROW(result->BackUp(20), std::logic_error);
+ ASSERT_EQ(true, result->Next(&ptr, &length));
+ ASSERT_EQ(30, length);
+ for(int i=0; i < 10; ++i) {
+ for(int j=0; j < 3; ++j) {
+ EXPECT_EQ(j, static_cast<const char*>(ptr)[i * 3 + j]);
+ }
+ }
+ result->BackUp(10);
+ ASSERT_THROW(result->BackUp(2), std::logic_error);
+ ASSERT_EQ(true, result->Next(&ptr, &length));
+ ASSERT_EQ(10, length);
+ for(int i=0; i < 10; ++i) {
+ EXPECT_EQ((i + 2) % 3, static_cast<const char*>(ptr)[i]);
+ }
+ ASSERT_EQ(true, result->Next(&ptr, &length));
+ ASSERT_EQ(30, length);
+ for(int i=0; i < 10; ++i) {
+ for(int j=0; j < 3; ++j) {
+ EXPECT_EQ(j, static_cast<const char*>(ptr)[i * 3 + j]);
+ }
+ }
+ }
+
+ TEST(Zlib, testSkip) {
+ const unsigned char buffer[] = {0x19, 0x0, 0x0, 0x0, 0x1,
+ 0x2, 0x3, 0x4, 0x5, 0x6,
+ 0x7, 0x8, 0x9, 0xa, 0xb,
+ 0xb, 0x0, 0x0, 0xc, 0xd,
+ 0xe, 0xf, 0x10};
+ std::unique_ptr<SeekableInputStream> result =
+ createDecompressor(CompressionKind_ZLIB,
+ std::unique_ptr<SeekableInputStream>
+ (new SeekableArrayInputStream
+ (buffer, ARRAY_SIZE(buffer), 5)),
+ 5, *getDefaultPool());
+ const void *ptr;
+ int length;
+ ASSERT_EQ(true, result->Next(&ptr, &length));
+ ASSERT_EQ(2, length);
+ result->Skip(2);
+ ASSERT_EQ(true, result->Next(&ptr, &length));
+ ASSERT_EQ(3, length);
+ EXPECT_EQ(4, static_cast<const char*>(ptr)[0]);
+ EXPECT_EQ(5, static_cast<const char*>(ptr)[1]);
+ EXPECT_EQ(6, static_cast<const char*>(ptr)[2]);
+ result->BackUp(2);
+ ASSERT_EQ(true, result->Next(&ptr, &length));
+ ASSERT_EQ(2, length);
+ EXPECT_EQ(5, static_cast<const char*>(ptr)[0]);
+ EXPECT_EQ(6, static_cast<const char*>(ptr)[1]);
+ result->Skip(8);
+ ASSERT_EQ(true, result->Next(&ptr, &length));
+ ASSERT_EQ(2, length);
+ EXPECT_EQ(15, static_cast<const char*>(ptr)[0]);
+ EXPECT_EQ(16, static_cast<const char*>(ptr)[1]);
+ }
+
+#define HEADER_SIZE 3
+
+ class CompressBuffer {
+ std::vector<char> buf;
+
+ public:
+ CompressBuffer(size_t capacity) :
+ buf(capacity + HEADER_SIZE)
+ {}
+
+ char *getCompressed() {
+ return buf.data() + HEADER_SIZE;
+ }
+ char *getBuffer() {
+ return buf.data();
+ }
+
+ void writeHeader(size_t compressedSize) {
+ buf[0] = static_cast<char>(compressedSize << 1);
+ buf[1] = static_cast<char>(compressedSize >> 7);
+ buf[2] = static_cast<char>(compressedSize >> 15);
+ }
+
+ size_t getCompressedSize() const {
+ size_t header = static_cast<unsigned char>(buf[0]);
+ header |= static_cast<size_t>(static_cast<unsigned char>(buf[1])) << 8;
+ header |= static_cast<size_t>(static_cast<unsigned char>(buf[2])) << 16;
+ return header >> 1;
+ }
+
+ size_t getBufferSize() const {
+ return getCompressedSize() + HEADER_SIZE;
+ }
+ };
+
+ TEST(Snappy, testBasic) {
+ const int N = 1024;
+ std::vector<char> buf(N * sizeof(int));
+ for (int i=0; i < N; ++i) {
+ (reinterpret_cast<int *>(buf.data()))[i] = i % 8;
+ }
+
+ CompressBuffer compressBuffer(snappy::MaxCompressedLength(buf.size()));
+ size_t compressedSize;
+ snappy::RawCompress(buf.data(), buf.size(), compressBuffer.getCompressed(),
+ &compressedSize);
+ // compressed size must be < original
+ ASSERT_LT(compressedSize, buf.size());
+ compressBuffer.writeHeader(compressedSize);
+
+ const long blockSize = 3;
+ std::unique_ptr<SeekableInputStream> result = createDecompressor
+ (CompressionKind_SNAPPY,
+ std::unique_ptr<SeekableInputStream>
+ (new SeekableArrayInputStream(compressBuffer.getBuffer(),
+ compressBuffer.getBufferSize(),
+ blockSize)),
+ buf.size(),
+ *getDefaultPool());
+ const void *data;
+ int length;
+ ASSERT_TRUE(result->Next(&data, &length));
+ ASSERT_EQ(N * sizeof(int), length);
+ for (int i=0; i < N; ++i) {
+ EXPECT_EQ(i % 8, (reinterpret_cast<const int *>(data))[i]);
+ }
+ }
+
+ TEST(Snappy, testMultiBuffer) {
+ const int N = 1024;
+ std::vector<char> buf(N * sizeof(int));
+ for (int i=0; i < N; ++i) {
+ (reinterpret_cast<int *>(buf.data()))[i] = i % 8;
+ }
+
+ CompressBuffer compressBuffer(snappy::MaxCompressedLength(buf.size()));
+ size_t compressedSize;
+ snappy::RawCompress(buf.data(), buf.size(), compressBuffer.getCompressed(),
+ &compressedSize);
+ // compressed size must be < original
+ ASSERT_LT(compressedSize, buf.size());
+ compressBuffer.writeHeader(compressedSize);
+
+ std::vector<char> input(compressBuffer.getBufferSize() * 4);
+ ::memcpy(input.data(), compressBuffer.getBuffer(),
+ compressBuffer.getBufferSize());
+ ::memcpy(input.data() + compressBuffer.getBufferSize(),
+ compressBuffer.getBuffer(), compressBuffer.getBufferSize());
+ ::memcpy(input.data() + 2 * compressBuffer.getBufferSize(),
+ compressBuffer.getBuffer(), compressBuffer.getBufferSize());
+ ::memcpy(input.data() + 3 * compressBuffer.getBufferSize(),
+ compressBuffer.getBuffer(), compressBuffer.getBufferSize());
+
+ const long blockSize = 3;
+ std::unique_ptr<SeekableInputStream> result = createDecompressor
+ (CompressionKind_SNAPPY,
+ std::unique_ptr<SeekableInputStream>
+ (new SeekableArrayInputStream(input.data(), input.size(), blockSize)),
+ buf.size(),
+ *getDefaultPool());
+ for (int i=0; i < 4; ++i) {
+ const void *data;
+ int length;
+ ASSERT_TRUE(result->Next(&data, &length));
+ for (int j=0; j < N; ++j) {
+ EXPECT_EQ(j % 8, (reinterpret_cast<const int *>(data))[j]);
+ }
+ }
+ }
+
+ TEST(Snappy, testSkip) {
+ const int N = 1024;
+ std::vector<char> buf(N * sizeof(int));
+ for (int i=0; i < N; ++i) {
+ (reinterpret_cast<int *>(buf.data()))[i] = i % 8;
+ }
+
+ CompressBuffer compressBuffer(snappy::MaxCompressedLength(buf.size()));
+ size_t compressedSize;
+ snappy::RawCompress(buf.data(), buf.size(), compressBuffer.getCompressed(),
+ &compressedSize);
+ // compressed size must be < original
+ ASSERT_LT(compressedSize, buf.size());
+ compressBuffer.writeHeader(compressedSize);
+
+ const long blockSize = 3;
+ std::unique_ptr<SeekableInputStream> result = createDecompressor
+ (CompressionKind_SNAPPY,
+ std::unique_ptr<SeekableInputStream>
+ (new SeekableArrayInputStream(compressBuffer.getBuffer(),
+ compressBuffer.getBufferSize(),
+ blockSize)),
+ buf.size(),
+ *getDefaultPool());
+ const void *data;
+ int length;
+ // skip 1/2; in 2 jumps
+ ASSERT_TRUE(result->Skip(static_cast<int>(((N / 2) - 2) * sizeof(int))));
+ ASSERT_TRUE(result->Skip(static_cast<int>(2 * sizeof(int))));
+ ASSERT_TRUE(result->Next(&data, &length));
+ ASSERT_EQ((N / 2) * sizeof(int), length);
+ for (int i=N/2; i < N; ++i) {
+ EXPECT_EQ(i % 8, (reinterpret_cast<const int *>(data))[i - N/2]);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/orc/blob/7f55b453/c++/test/TestDriver.cc
----------------------------------------------------------------------
diff --git a/c++/test/TestDriver.cc b/c++/test/TestDriver.cc
new file mode 100644
index 0000000..a34ff07
--- /dev/null
+++ b/c++/test/TestDriver.cc
@@ -0,0 +1,33 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 "orc/orc-config.hh"
+
+#include "wrap/orc-proto-wrapper.hh"
+#include "wrap/gtest-wrapper.h"
+
+#include <iostream>
+
+GTEST_API_ int main(int argc, char **argv) {
+ GOOGLE_PROTOBUF_VERIFY_VERSION;
+ std::cout << "ORC version: " << ORC_VERSION << "\n";
+ testing::InitGoogleTest(&argc, argv);
+ int result = RUN_ALL_TESTS();
+ return result;
+}
http://git-wip-us.apache.org/repos/asf/orc/blob/7f55b453/c++/test/TestInt128.cc
----------------------------------------------------------------------
diff --git a/c++/test/TestInt128.cc b/c++/test/TestInt128.cc
new file mode 100644
index 0000000..cc3b30f
--- /dev/null
+++ b/c++/test/TestInt128.cc
@@ -0,0 +1,587 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 "orc/Int128.hh"
+
+#include "wrap/gtest-wrapper.h"
+#include "OrcTest.hh"
+
+#include <iostream>
+
+namespace orc {
+
+ TEST(Int128, simpleTest) {
+ Int128 x = 12;
+ Int128 y = 13;
+ x += y;
+ EXPECT_EQ(25, x.toLong());
+ EXPECT_EQ("0x00000000000000000000000000000019", x.toHexString());
+ y -= 1;
+ EXPECT_EQ("0x0000000000000000000000000000000c", y.toHexString());
+ EXPECT_EQ(12, y.toLong());
+ EXPECT_EQ(0, y.getHighBits());
+ EXPECT_EQ(12, y.getLowBits());
+ y -= 20;
+ EXPECT_EQ("0xfffffffffffffffffffffffffffffff8", y.toHexString());
+ EXPECT_EQ(-8, y.toLong());
+ EXPECT_EQ(-1, y.getHighBits());
+ EXPECT_EQ(static_cast<uint64_t>(-8), y.getLowBits());
+ Int128 z;
+ EXPECT_EQ(0, z.toLong());
+ }
+
+ TEST(Int128, testNegate) {
+ Int128 n = -1000000000000;
+ EXPECT_EQ("0xffffffffffffffffffffff172b5af000", n.toHexString());
+ n.negate();
+ EXPECT_EQ(1000000000000, n.toLong());
+ n.abs();
+ EXPECT_EQ(1000000000000, n.toLong());
+ n.negate();
+ EXPECT_EQ(-1000000000000, n.toLong());
+ n.abs();
+ EXPECT_EQ(1000000000000, n.toLong());
+
+ Int128 big(0x12345678, 0x9abcdef0);
+ EXPECT_EQ("0x0000000012345678000000009abcdef0", big.toHexString());
+ EXPECT_EQ(305419896, big.getHighBits());
+ EXPECT_EQ(2596069104, big.getLowBits());
+ big.negate();
+ EXPECT_EQ("0xffffffffedcba987ffffffff65432110", big.toHexString());
+ EXPECT_EQ(0xffffffffedcba987, big.getHighBits());
+ EXPECT_EQ(0xffffffff65432110, big.getLowBits());
+ big.negate();
+ EXPECT_EQ("0x0000000012345678000000009abcdef0", big.toHexString());
+ big.invert();
+ EXPECT_EQ("0xffffffffedcba987ffffffff6543210f", big.toHexString());
+ big.invert();
+ EXPECT_EQ("0x0000000012345678000000009abcdef0", big.toHexString());
+ }
+
+ TEST(Int128, testPlus) {
+ Int128 n(0x1000, 0xfffffffffffffff0);
+ EXPECT_EQ("0x0000000000001000fffffffffffffff0", n.toHexString());
+ n += 0x20;
+ EXPECT_EQ("0x00000000000010010000000000000010", n.toHexString());
+ n -= 0x20;
+ EXPECT_EQ("0x0000000000001000fffffffffffffff0", n.toHexString());
+ n += Int128(2,3);
+ EXPECT_EQ("0x0000000000001002fffffffffffffff3", n.toHexString());
+
+ Int128 x(static_cast<int64_t>(0xffffffffffffff00), 0x200);
+ EXPECT_EQ("0xffffffffffffff000000000000000200", x.toHexString());
+ x -= 0x300;
+ EXPECT_EQ("0xfffffffffffffeffffffffffffffff00", x.toHexString());
+ x -= 0x100;
+ EXPECT_EQ("0xfffffffffffffefffffffffffffffe00", x.toHexString());
+ x += 0x400;
+ EXPECT_EQ("0xffffffffffffff000000000000000200", x.toHexString());
+ x -= Int128(1,2);
+ EXPECT_EQ("0xfffffffffffffeff00000000000001fe", x.toHexString());
+ }
+
+ TEST(Int128, testLogic) {
+ Int128 n = Int128(0x00000000100000002, 0x0000000400000008);
+ n |= Int128(0x0000001000000020, 0x0000004000000080);
+ EXPECT_EQ("0x00000011000000220000004400000088", n.toHexString());
+ n = Int128(0x0000111100002222, 0x0000333300004444);
+ n &= Int128(0x0000f00000000f00, 0x000000f00000000f);
+ EXPECT_EQ( "0x00001000000002000000003000000004", n.toHexString());
+ }
+
+ TEST(Int128, testShift) {
+ Int128 n(0x123456789abcdef0,0xfedcba9876543210);
+ EXPECT_EQ("0x123456789abcdef0fedcba9876543210", n.toHexString());
+ n <<= 0;
+ EXPECT_EQ("0x123456789abcdef0fedcba9876543210", n.toHexString());
+ n <<= 4;
+ EXPECT_EQ("0x23456789abcdef0fedcba98765432100", n.toHexString());
+ n <<= 8;
+ EXPECT_EQ("0x456789abcdef0fedcba9876543210000", n.toHexString());
+ n += 0x99;
+ EXPECT_EQ("0x456789abcdef0fedcba9876543210099", n.toHexString());
+ n <<= 64;
+ EXPECT_EQ("0xcba98765432100990000000000000000", n.toHexString());
+ n += 0x312;
+ EXPECT_EQ("0xcba98765432100990000000000000312", n.toHexString());
+ n <<= 120;
+ EXPECT_EQ("0x12000000000000000000000000000000", n.toHexString());
+ n += 0x411;
+ EXPECT_EQ("0x12000000000000000000000000000411", n.toHexString());
+ n <<= 128;
+ EXPECT_EQ(0, n.toLong());
+
+ n = Int128(0x123456789abcdef0,0xfedcba9876543210);
+ EXPECT_EQ("0x123456789abcdef0fedcba9876543210", n.toHexString());
+ n >>= 0;
+ EXPECT_EQ("0x123456789abcdef0fedcba9876543210", n.toHexString());
+ n >>= 4;
+ EXPECT_EQ("0x0123456789abcdef0fedcba987654321", n.toHexString());
+ n >>= 8;
+ EXPECT_EQ("0x000123456789abcdef0fedcba9876543", n.toHexString());
+ n += Int128(0x2400000000000000, 0x0);
+ EXPECT_EQ("0x240123456789abcdef0fedcba9876543", n.toHexString());
+ n >>= 64;
+ EXPECT_EQ("0x0000000000000000240123456789abcd", n.toHexString());
+ n += Int128(0x2400000000000000, 0x0);
+ EXPECT_EQ("0x2400000000000000240123456789abcd", n.toHexString());
+ n >>= 129;
+ EXPECT_EQ(0, n.toLong());
+ n = Int128(static_cast<int64_t>(0xfedcba0987654321),0x1234567890abcdef);
+ EXPECT_EQ("0xfedcba09876543211234567890abcdef", n.toHexString());
+ n >>= 64;
+ EXPECT_EQ("0xfffffffffffffffffedcba0987654321", n.toHexString());
+ n = Int128(static_cast<int64_t>(0xfedcba0987654321),0x1234567890abcdef);
+ n >>= 129;
+ EXPECT_EQ("0xffffffffffffffffffffffffffffffff", n.toHexString());
+ n = Int128(-1, 0xffffffffffffffff);
+ n >>= 4;
+ EXPECT_EQ("0x0fffffffffffffffffffffffffffffff", n.toHexString());
+ n = Int128(-0x100, 0xffffffffffffffff);
+ n >>= 68;
+ EXPECT_EQ("0xfffffffffffffffffffffffffffffff0", n.toHexString());
+ }
+
+ TEST(Int128, testCompare) {
+ Int128 x = 123;
+ EXPECT_EQ(Int128(123), x);
+ EXPECT_EQ(true, x == 123);
+ EXPECT_EQ(true, !(x == 124));
+ EXPECT_EQ(true, !(x == -124));
+ EXPECT_EQ(true, !(x == Int128(2, 123)));
+ EXPECT_EQ(true, !(x != 123));
+ EXPECT_EQ(true, x != -123);
+ EXPECT_EQ(true, x != 124);
+ EXPECT_EQ(true, x != Int128(-1, 123));
+ x = Int128(0x123, 0x456);
+ EXPECT_EQ(true, !(x < Int128(0x123, 0x455)));
+ EXPECT_EQ(true, !(x < Int128(0x123, 0x456)));
+ EXPECT_EQ(true, x < Int128(0x123, 0x457));
+ EXPECT_EQ(true, !(x < Int128(0x122, 0x456)));
+ EXPECT_EQ(true, x < Int128(0x124, 0x456));
+
+ EXPECT_EQ(true, !(x <= Int128(0x123, 0x455)));
+ EXPECT_EQ(true, x <= Int128(0x123, 0x456));
+ EXPECT_EQ(true, x <= Int128(0x123, 0x457));
+ EXPECT_EQ(true, !(x <= Int128(0x122, 0x456)));
+ EXPECT_EQ(true, x <= Int128(0x124, 0x456));
+
+ EXPECT_EQ(true, x > Int128(0x123, 0x455));
+ EXPECT_EQ(true, !(x > Int128(0x123, 0x456)));
+ EXPECT_EQ(true, !(x > Int128(0x123, 0x457)));
+ EXPECT_EQ(true, x > Int128(0x122, 0x456));
+ EXPECT_EQ(true, !(x > Int128(0x124, 0x456)));
+
+ EXPECT_EQ(true, x >= Int128(0x123, 0x455));
+ EXPECT_EQ(true, x >= Int128(0x123, 0x456));
+ EXPECT_EQ(true, !(x >= Int128(0x123, 0x457)));
+ EXPECT_EQ(true, x >= Int128(0x122, 0x456));
+ EXPECT_EQ(true, !(x >= Int128(0x124, 0x456)));
+
+ EXPECT_EQ(true, Int128(-3) < Int128(-2));
+ EXPECT_EQ(true, Int128(-3) < Int128(0));
+ EXPECT_EQ(true, Int128(-3) < Int128(3));
+ EXPECT_EQ(true, Int128(0) < Int128(5));
+ EXPECT_EQ(true, Int128::minimumValue() < 0);
+ EXPECT_EQ(true, Int128(0) < Int128::maximumValue());
+ EXPECT_EQ(true, Int128::minimumValue() < Int128::maximumValue());
+ }
+
+ TEST(Int128, testHash) {
+ EXPECT_EQ(0, Int128().hash());
+ EXPECT_EQ(0x123, Int128(0x123).hash());
+ EXPECT_EQ(0xc3c3c3c3,
+ Int128(0x0101010102020202, 0x4040404080808080).hash());
+ EXPECT_EQ(0x122, Int128(-0x123).hash());
+ EXPECT_EQ(0x12345678, Int128(0x1234567800000000, 0x0).hash());
+ EXPECT_EQ(0x12345678, Int128(0x12345678, 0x0).hash());
+ EXPECT_EQ(0x12345678, Int128(0x0, 0x1234567800000000).hash());
+ EXPECT_EQ(0x12345678, Int128(0x0, 0x12345678).hash());
+ }
+
+ TEST(Int128, testFitsInLong) {
+ EXPECT_EQ(true, Int128(0x0, 0x7fffffffffffffff).fitsInLong());
+ EXPECT_EQ(true, !Int128(0x0, 0x8000000000000000).fitsInLong());
+ EXPECT_EQ(true, !Int128(-1, 0x7fffffffffffffff).fitsInLong());
+ EXPECT_EQ(true, Int128(-1, 0x8000000000000000).fitsInLong());
+ EXPECT_EQ(true, !Int128(1, 0x8000000000000000).fitsInLong());
+ EXPECT_EQ(true, !Int128(1, 0x7fffffffffffffff).fitsInLong());
+ EXPECT_EQ(true, !Int128(-2, 0x8000000000000000).fitsInLong());
+ EXPECT_EQ(true, !Int128(-2, 0x7fffffffffffffff).fitsInLong());
+
+ EXPECT_EQ(0x7fffffffffffffff, Int128(0x0, 0x7fffffffffffffff).toLong());
+ EXPECT_THROW(Int128(1,1).toLong(), std::runtime_error);
+ EXPECT_EQ(0x8000000000000000, Int128(-1, 0x8000000000000000).toLong());
+ }
+
+ TEST(Int128, testMultiply) {
+ Int128 x = 2;
+ x *= 3;
+ EXPECT_EQ(6, x.toLong());
+ x *= -4;
+ EXPECT_EQ(-24, x.toLong());
+ x *= 5;
+ EXPECT_EQ(-120, x.toLong());
+ x *= -7;
+ EXPECT_EQ(840, x.toLong());
+ x = Int128(0x0123456776543210,0x1111222233334444);
+ x *= 2;
+ EXPECT_EQ(0x02468aceeca86420, x.getHighBits());
+ EXPECT_EQ(0x2222444466668888, x.getLowBits());
+
+ x = Int128(0x0534AB4C, 0x59D109ADF9892FCA);
+ x *= Int128(0, 0x9033b8c7a);
+ EXPECT_EQ("0x2eead9afd0c6e0e929c18da753113e44", x.toHexString());
+ }
+
+ TEST(Int128, testMultiplyInt) {
+ Int128 x = 2;
+ x *= 1;
+ EXPECT_EQ(2, x.toLong());
+ x *= 2;
+ EXPECT_EQ(4, x.toLong());
+
+ x = 5;
+ x *= 6432346;
+ EXPECT_EQ(6432346 * 5, x.toLong());
+
+ x = (1L << 62) + (3L << 34) + 3L;
+ x *= 96;
+ EXPECT_EQ("0x00000000000000180000048000000120", x.toHexString());
+
+ x = 1;
+ x <<= 126;
+ EXPECT_EQ("0x40000000000000000000000000000000", x.toHexString());
+ x *= 2;
+ EXPECT_EQ("0x80000000000000000000000000000000", x.toHexString());
+ x *= 2;
+ EXPECT_EQ("0x00000000000000000000000000000000", x.toHexString());
+ }
+
+ TEST(Int128, testFillInArray) {
+ Int128 x(0x123456789abcdef0, 0x23456789abcdef01);
+ uint32_t array[4];
+ bool wasNegative;
+ EXPECT_EQ(4, x.fillInArray(array, wasNegative));
+ EXPECT_EQ(true, !wasNegative);
+ EXPECT_EQ(0x12345678, array[0]);
+ EXPECT_EQ(0x9abcdef0, array[1]);
+ EXPECT_EQ(0x23456789, array[2]);
+ EXPECT_EQ(0xabcdef01, array[3]);
+
+ x = 0;
+ EXPECT_EQ(0, x.fillInArray(array, wasNegative));
+ EXPECT_EQ(true, !wasNegative);
+
+ x = 1;
+ EXPECT_EQ(1, x.fillInArray(array, wasNegative));
+ EXPECT_EQ(true, !wasNegative);
+ EXPECT_EQ(1, array[0]);
+
+ x = -12345;
+ EXPECT_EQ(1, x.fillInArray(array, wasNegative));
+ EXPECT_EQ(true, wasNegative);
+ EXPECT_EQ(12345, array[0]);
+
+ x = 0x80000000;
+ EXPECT_EQ(1, x.fillInArray(array, wasNegative));
+ EXPECT_EQ(true, !wasNegative);
+ EXPECT_EQ(0x80000000, array[0]);
+
+ x = Int128(0, 0x8000000000000000);
+ EXPECT_EQ(2, x.fillInArray(array, wasNegative));
+ EXPECT_EQ(true, !wasNegative);
+ EXPECT_EQ(0x80000000, array[0]);
+ EXPECT_EQ(0x0, array[1]);
+
+ x = Int128(0x80000000, 0x123456789abcdef0);
+ EXPECT_EQ(3, x.fillInArray(array, wasNegative));
+ EXPECT_EQ(true, !wasNegative);
+ EXPECT_EQ(0x80000000, array[0]);
+ EXPECT_EQ(0x12345678, array[1]);
+ EXPECT_EQ(0x9abcdef0, array[2]);
+ }
+
+ int fls(uint32_t x);
+
+ TEST(Int128, testFindLastSet) {
+ EXPECT_EQ(0, fls(0));
+ EXPECT_EQ(1, fls(1));
+ EXPECT_EQ(8, fls(0xff));
+ EXPECT_EQ(9, fls(0x100));
+ EXPECT_EQ(29, fls(0x12345678));
+ EXPECT_EQ(31, fls(0x40000000));
+ EXPECT_EQ(32, fls(0x80000000));
+ }
+
+ void shiftArrayLeft(uint32_t* array, int64_t length, int64_t bits);
+
+ TEST(Int128, testShiftArrayLeft) {
+ uint32_t array[5];
+ // make sure nothing blows up
+ array[0] = 0x12345678;
+ shiftArrayLeft(0, 0, 30);
+ EXPECT_EQ(0x12345678, array[0]);
+
+ array[0] = 0x12345678;
+ shiftArrayLeft(array, 1, 0);
+ EXPECT_EQ(0x12345678, array[0]);
+
+ array[0] = 0x12345678;
+ array[1] = 0x9abcdef0;
+ shiftArrayLeft(array, 1, 3);
+ EXPECT_EQ(0x91a2b3c0, array[0]);
+ EXPECT_EQ(0x9abcdef0, array[1]);
+
+ array[0] = 0x12345678;
+ array[1] = 0x9abcdeff;
+ array[2] = 0xfedcba98;
+ array[3] = 0x76543210;
+ shiftArrayLeft(array, 4, 4);
+ EXPECT_EQ(0x23456789, array[0]);
+ EXPECT_EQ(0xabcdefff, array[1]);
+ EXPECT_EQ(0xedcba987, array[2]);
+ EXPECT_EQ(0x65432100, array[3]);
+
+ array[0] = 0;
+ array[1] = 0x12345678;
+ array[2] = 0x9abcdeff;
+ array[3] = 0xfedcba98;
+ array[4] = 0x76543210;
+ shiftArrayLeft(array, 5, 8);
+ EXPECT_EQ(0x00000012, array[0]);
+ EXPECT_EQ(0x3456789a, array[1]);
+ EXPECT_EQ(0xbcdefffe, array[2]);
+ EXPECT_EQ(0xdcba9876, array[3]);
+ EXPECT_EQ(0x54321000, array[4]);
+ }
+
+ void shiftArrayRight(uint32_t* array, int64_t length, int64_t bits);
+
+ TEST(Int128, testShiftArrayRight) {
+ uint32_t array[4];
+ // make sure nothing blows up
+ array[0] = 0x12345678;
+ shiftArrayRight(0, 0, 30);
+ EXPECT_EQ(0x12345678, array[0]);
+
+ array[0] = 0x12345678;
+ array[1] = 0x9abcdef0;
+ shiftArrayRight(array, 1, 3);
+ EXPECT_EQ(0x2468acf, array[0]);
+ EXPECT_EQ(0x9abcdef0, array[1]);
+
+ array[0] = 0x12345678;
+ array[1] = 0x9abcdeff;
+ array[2] = 0xfedcba98;
+ array[3] = 0x76543210;
+ shiftArrayRight(array, 4, 4);
+ EXPECT_EQ(0x01234567, array[0]);
+ EXPECT_EQ(0x89abcdef, array[1]);
+ EXPECT_EQ(0xffedcba9, array[2]);
+ EXPECT_EQ(0x87654321, array[3]);
+ }
+
+ void fixDivisionSigns(Int128 &result, Int128 &remainder,
+ bool dividendWasNegative, bool divisorWasNegative);
+
+ TEST(Int128, testFixDivisionSigns) {
+ Int128 x = 123;
+ Int128 y = 456;
+ fixDivisionSigns(x, y, false, false);
+ EXPECT_EQ(123, x.toLong());
+ EXPECT_EQ(456, y.toLong());
+
+ x = 123;
+ y = 456;
+ fixDivisionSigns(x, y, false, true);
+ EXPECT_EQ(-123, x.toLong());
+ EXPECT_EQ(456, y.toLong());
+
+ x = 123;
+ y = 456;
+ fixDivisionSigns(x, y, true, false);
+ EXPECT_EQ(-123, x.toLong());
+ EXPECT_EQ(-456, y.toLong());
+
+ x = 123;
+ y = 456;
+ fixDivisionSigns(x, y, true, true);
+ EXPECT_EQ(123, x.toLong());
+ EXPECT_EQ(-456, y.toLong());
+
+ }
+
+ void buildFromArray(Int128& value, uint32_t* array, int64_t length);
+
+ TEST(Int128, testBuildFromArray) {
+ Int128 result;
+ uint32_t array[4]={0x12345678, 0x9abcdef0, 0xfedcba98, 0x76543210};
+
+ buildFromArray(result, array, 0);
+ EXPECT_EQ(0, result.toLong());
+
+ buildFromArray(result, array, 1);
+ EXPECT_EQ(0x12345678, result.toLong());
+
+ buildFromArray(result, array, 2);
+ EXPECT_EQ(0x123456789abcdef0, result.toLong());
+
+ buildFromArray(result, array, 3);
+ EXPECT_EQ("0x00000000123456789abcdef0fedcba98", result.toHexString());
+
+ buildFromArray(result, array, 4);
+ EXPECT_EQ("0x123456789abcdef0fedcba9876543210", result.toHexString());
+
+ EXPECT_THROW(buildFromArray(result, array, 5), std::logic_error);
+ }
+
+ Int128 singleDivide(uint32_t* dividend, int64_t dividendLength,
+ uint32_t divisor, Int128& remainder,
+ bool dividendWasNegative, bool divisorWasNegative);
+
+ TEST(Int128, testSingleDivide) {
+ Int128 remainder;
+ uint32_t dividend[4];
+
+ dividend[0] = 23;
+ Int128 result = singleDivide(dividend, 1, 5, remainder, true, false);
+ EXPECT_EQ(-4, result.toLong());
+ EXPECT_EQ(-3, remainder.toLong());
+
+ dividend[0] = 0x100;
+ dividend[1] = 0x120;
+ dividend[2] = 0x140;
+ dividend[3] = 0x160;
+ result = singleDivide(dividend, 4, 0x20, remainder, false, false);
+ EXPECT_EQ("0x00000008000000090000000a0000000b", result.toHexString());
+ EXPECT_EQ(0, remainder.toLong());
+
+ dividend[0] = 0x101;
+ dividend[1] = 0x122;
+ dividend[2] = 0x143;
+ dividend[3] = 0x164;
+ result = singleDivide(dividend, 4, 0x20, remainder, false, false);
+ EXPECT_EQ("0x00000008080000091000000a1800000b", result.toHexString());
+ EXPECT_EQ(4, remainder.toLong());
+
+ dividend[0] = 0x12345678;
+ dividend[1] = 0x9abcdeff;
+ dividend[2] = 0xfedcba09;
+ dividend[3] = 0x87654321;
+ result = singleDivide(dividend, 4, 123, remainder, false, false);
+ EXPECT_EQ("0x0025e390971c97aaaaa84c7077bc23ed", result.toHexString());
+ EXPECT_EQ(0x42, remainder.toLong());
+ }
+
+ TEST(Int128, testDivide) {
+ Int128 dividend;
+ Int128 result;
+ Int128 remainder;
+
+ dividend = 0x12345678;
+ result = dividend.divide(0x123456789abcdef0, remainder);
+ EXPECT_EQ(0, result.toLong());
+ EXPECT_EQ(0x12345678, remainder.toLong());
+
+ EXPECT_THROW(dividend.divide(0, remainder), std::runtime_error);
+
+ dividend = Int128(0x123456789abcdeff, 0xfedcba0987654321);
+ result = dividend.divide(123, remainder);
+ EXPECT_EQ("0x0025e390971c97aaaaa84c7077bc23ed", result.toHexString());
+ EXPECT_EQ(0x42, remainder.toLong());
+
+ dividend = Int128(0x111111112fffffff, 0xeeeeeeeedddddddd);
+ result = dividend.divide(0x1111111123456789, remainder);
+ EXPECT_EQ("0x000000000000000100000000beeeeef7", result.toHexString());
+ EXPECT_EQ("0x0000000000000000037d3b3d60479aae", remainder.toHexString());
+
+ dividend = 1234234662345;
+ result = dividend.divide(642337, remainder);
+ EXPECT_EQ(1921475, result.toLong());
+ EXPECT_EQ(175270, remainder.toLong());
+
+ dividend = Int128(0x42395ADC0534AB4C, 0x59D109ADF9892FCA);
+ result = dividend.divide(0x1234F09DC19A, remainder);
+ EXPECT_EQ("0x000000000003a327c1348bccd2f06c27", result.toHexString());
+ EXPECT_EQ("0x000000000000000000000cacef73b954", remainder.toHexString());
+
+ dividend = Int128(0xfffffffffffffff, 0xf000000000000000);
+ result = dividend.divide(Int128(0, 0x1000000000000000), remainder);
+ EXPECT_EQ("0x0000000000000000ffffffffffffffff", result.toHexString());
+ EXPECT_EQ(0, remainder.toLong());
+
+ dividend = Int128(0x4000000000000000, 0);
+ result = dividend.divide(Int128(0, 0x400000007fffffff), remainder);
+ EXPECT_EQ("0x0000000000000000fffffffe00000007", result.toHexString());
+ EXPECT_EQ("0x00000000000000003ffffffa80000007", remainder.toHexString());
+ }
+
+ TEST(Int128, testToString) {
+ Int128 num = Int128(0x123456789abcdef0, 0xfedcba0987654321);
+ EXPECT_EQ("24197857203266734881846307133640229665", num.toString());
+
+ num = Int128(0, 0xab54a98ceb1f0ad2);
+ EXPECT_EQ("12345678901234567890", num.toString());
+
+ num = 12345678;
+ EXPECT_EQ("12345678", num.toString());
+
+ num = -1234;
+ EXPECT_EQ("-1234", num.toString());
+
+ num = Int128(0x13f20d9c2, 0xfff89d38e1c70cb1);
+ EXPECT_EQ("98765432109876543210987654321", num.toString());
+ num.negate();
+ EXPECT_EQ("-98765432109876543210987654321", num.toString());
+
+ num = Int128("10000000000000000000000000000000000000");
+ EXPECT_EQ("10000000000000000000000000000000000000", num.toString());
+
+ num = Int128("-1234");
+ EXPECT_EQ("-1234", num.toString());
+
+ num = Int128("-12345678901122334455667788990011122233");
+ EXPECT_EQ("-12345678901122334455667788990011122233", num.toString());
+ }
+
+ TEST(Int128, testToDecimalString) {
+ Int128 num = Int128("98765432109876543210987654321098765432");
+ EXPECT_EQ("98765432109876543210987654321098765432",
+ num.toDecimalString(0));
+ EXPECT_EQ("987654321098765432109876543210987.65432",
+ num.toDecimalString(5));
+ num.negate();
+ EXPECT_EQ("-98765432109876543210987654321098765432",
+ num.toDecimalString(0));
+ EXPECT_EQ("-987654321098765432109876543210987.65432",
+ num.toDecimalString(5));
+ num = 123;
+ EXPECT_EQ("12.3", num.toDecimalString(1));
+ EXPECT_EQ("0.123", num.toDecimalString(3));
+ EXPECT_EQ("0.0123", num.toDecimalString(4));
+ EXPECT_EQ("0.00123", num.toDecimalString(5));
+
+ num = -123;
+ EXPECT_EQ("-123", num.toDecimalString(0));
+ EXPECT_EQ("-12.3", num.toDecimalString(1));
+ EXPECT_EQ("-0.123", num.toDecimalString(3));
+ EXPECT_EQ("-0.0123", num.toDecimalString(4));
+ EXPECT_EQ("-0.00123", num.toDecimalString(5));
+ }
+} // namespace orc