/** * Copyright (C) 2014 MongoDB Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . * * As a special exception, the copyright holders give permission to link the * code of portions of this program with the OpenSSL library under certain * conditions as described in each individual source file and distribute * linked combinations including the program with the OpenSSL library. You * must comply with the GNU Affero General Public License in all respects * for all of the code used other than as permitted herein. If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. If you do not * wish to do so, delete this exception statement from your version. If you * delete this exception statement from all source files in the program, * then also delete it in the license file. */ #include "mongo/base/encoded_value_storage.h" #include #include "mongo/base/data_type_endian.h" #include "mongo/base/static_assert.h" #include "mongo/platform/endian.h" #include "mongo/unittest/unittest.h" namespace mongo { // Simplistic encoded value view and value classes to test EncodedValueStorage namespace EncodedValueStorageTest { #pragma pack(1) struct Layout { uint32_t native; uint32_t le; uint32_t be; }; #pragma pack() class ConstView { public: typedef ConstDataView view_type; ConstView(const char* data) : _data(data) {} const char* view2ptr() const { return data().view(); } uint32_t getNative() { return data().read(offsetof(Layout, native)); } uint32_t getLE() { return data().read>(offsetof(Layout, le)); } uint32_t getBE() { return data().read>(offsetof(Layout, be)); } protected: const view_type& data() const { return _data; } private: view_type _data; }; class View : public ConstView { public: typedef DataView view_type; View(char* data) : ConstView(data) {} using ConstView::view2ptr; char* view2ptr() { return data().view(); } void setNative(uint32_t value) { data().write(value, offsetof(Layout, native)); } void setLE(uint32_t value) { data().write(tagLittleEndian(value), offsetof(Layout, le)); } void setBE(uint32_t value) { data().write(tagBigEndian(value), offsetof(Layout, be)); } private: view_type data() const { return const_cast(ConstView::view2ptr()); } }; class Value : public EncodedValueStorage { public: Value() { MONGO_STATIC_ASSERT(sizeof(Value) == sizeof(Layout)); } Value(ZeroInitTag_t zit) : EncodedValueStorage(zit) {} }; } TEST(EncodedValueStorage, EncodedValueStorage) { EncodedValueStorageTest::Value raw; EncodedValueStorageTest::Value zerod(kZeroInitTag); char buf[sizeof(EncodedValueStorageTest::Layout)] = {0}; ASSERT_EQUALS(raw.view().view2ptr(), raw.constView().view2ptr()); // ensure zeroing with the init tag works ASSERT_EQUALS(std::memcmp(zerod.view().view2ptr(), buf, sizeof(buf)), 0); // see if value assignment and view() works zerod.view().setNative(1234); EncodedValueStorageTest::View(buf).setNative(1234); raw = zerod; ASSERT_EQUALS(std::memcmp(raw.view().view2ptr(), buf, sizeof(buf)), 0); // see if view() and constView() work appropriately raw.view().setNative(1); raw.view().setLE(2); raw.view().setBE(3); ASSERT_EQUALS(static_cast(1), raw.constView().getNative()); ASSERT_EQUALS(static_cast(2), raw.constView().getLE()); ASSERT_EQUALS(static_cast(3), raw.constView().getBE()); } } // namespace mongo