summaryrefslogtreecommitdiffstats
path: root/staging_vespalib/src/tests
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@yahoo-inc.com>2016-06-15 23:09:44 +0200
committerJon Bratseth <bratseth@yahoo-inc.com>2016-06-15 23:09:44 +0200
commit72231250ed81e10d66bfe70701e64fa5fe50f712 (patch)
tree2728bba1131a6f6e5bdf95afec7d7ff9358dac50 /staging_vespalib/src/tests
Publish
Diffstat (limited to 'staging_vespalib/src/tests')
-rw-r--r--staging_vespalib/src/tests/.gitignore4
-rw-r--r--staging_vespalib/src/tests/array/.gitignore5
-rw-r--r--staging_vespalib/src/tests/array/CMakeLists.txt22
-rw-r--r--staging_vespalib/src/tests/array/DESC1
-rw-r--r--staging_vespalib/src/tests/array/FILES1
-rw-r--r--staging_vespalib/src/tests/array/allocinarray_benchmark.cpp124
-rw-r--r--staging_vespalib/src/tests/array/allocinarray_test.cpp75
-rw-r--r--staging_vespalib/src/tests/array/sort_benchmark.cpp182
-rw-r--r--staging_vespalib/src/tests/benchmark/.gitignore4
-rw-r--r--staging_vespalib/src/tests/benchmark/CMakeLists.txt9
-rw-r--r--staging_vespalib/src/tests/benchmark/DESC1
-rw-r--r--staging_vespalib/src/tests/benchmark/FILES1
-rw-r--r--staging_vespalib/src/tests/benchmark/benchmark.cpp30
-rwxr-xr-xstaging_vespalib/src/tests/benchmark/benchmark_test.sh19
-rw-r--r--staging_vespalib/src/tests/benchmark/testbase.cpp278
-rw-r--r--staging_vespalib/src/tests/benchmark/testbase.h169
-rw-r--r--staging_vespalib/src/tests/bits/.gitignore4
-rw-r--r--staging_vespalib/src/tests/bits/CMakeLists.txt8
-rw-r--r--staging_vespalib/src/tests/bits/DESC1
-rw-r--r--staging_vespalib/src/tests/bits/FILES1
-rw-r--r--staging_vespalib/src/tests/bits/bits_test.cpp58
-rw-r--r--staging_vespalib/src/tests/clock/.gitignore4
-rw-r--r--staging_vespalib/src/tests/clock/CMakeLists.txt8
-rw-r--r--staging_vespalib/src/tests/clock/DESC1
-rw-r--r--staging_vespalib/src/tests/clock/FILES1
-rw-r--r--staging_vespalib/src/tests/clock/clock_test.cpp38
-rw-r--r--staging_vespalib/src/tests/cpu/.gitignore4
-rw-r--r--staging_vespalib/src/tests/cpu/CMakeLists.txt8
-rw-r--r--staging_vespalib/src/tests/cpu/DESC1
-rw-r--r--staging_vespalib/src/tests/cpu/FILES1
-rw-r--r--staging_vespalib/src/tests/cpu/cpu_test.cpp33
-rw-r--r--staging_vespalib/src/tests/crc/.gitignore4
-rw-r--r--staging_vespalib/src/tests/crc/CMakeLists.txt8
-rw-r--r--staging_vespalib/src/tests/crc/DESC1
-rw-r--r--staging_vespalib/src/tests/crc/FILES1
-rw-r--r--staging_vespalib/src/tests/crc/crc_test.cpp80
-rwxr-xr-xstaging_vespalib/src/tests/create-test.sh65
-rw-r--r--staging_vespalib/src/tests/databuffer/.gitignore1
-rw-r--r--staging_vespalib/src/tests/databuffer/CMakeLists.txt8
-rw-r--r--staging_vespalib/src/tests/databuffer/databuffer_test.cpp145
-rw-r--r--staging_vespalib/src/tests/directio/.gitignore1
-rw-r--r--staging_vespalib/src/tests/directio/CMakeLists.txt8
-rw-r--r--staging_vespalib/src/tests/directio/directio.cpp58
-rw-r--r--staging_vespalib/src/tests/dotproduct/.gitignore2
-rw-r--r--staging_vespalib/src/tests/dotproduct/CMakeLists.txt21
-rw-r--r--staging_vespalib/src/tests/dotproduct/dotproductbenchmark.cpp179
-rw-r--r--staging_vespalib/src/tests/encoding/.gitignore3
-rw-r--r--staging_vespalib/src/tests/encoding/base64/.gitignore1
-rw-r--r--staging_vespalib/src/tests/encoding/base64/CMakeLists.txt8
-rw-r--r--staging_vespalib/src/tests/encoding/base64/DESC1
-rw-r--r--staging_vespalib/src/tests/encoding/base64/FILES1
-rw-r--r--staging_vespalib/src/tests/encoding/base64/base64_test.cpp89
-rw-r--r--staging_vespalib/src/tests/fileheader/.gitignore6
-rw-r--r--staging_vespalib/src/tests/fileheader/CMakeLists.txt8
-rw-r--r--staging_vespalib/src/tests/fileheader/DESC1
-rw-r--r--staging_vespalib/src/tests/fileheader/FILES1
-rw-r--r--staging_vespalib/src/tests/fileheader/fileheader.datbin0 -> 56 bytes
-rw-r--r--staging_vespalib/src/tests/fileheader/fileheader_test.cpp694
-rw-r--r--staging_vespalib/src/tests/floatingpointtype/.gitignore4
-rw-r--r--staging_vespalib/src/tests/floatingpointtype/CMakeLists.txt8
-rw-r--r--staging_vespalib/src/tests/floatingpointtype/DESC1
-rw-r--r--staging_vespalib/src/tests/floatingpointtype/FILES1
-rw-r--r--staging_vespalib/src/tests/floatingpointtype/floatingpointtypetest.cpp75
-rw-r--r--staging_vespalib/src/tests/growablebytebuffer/.gitignore4
-rw-r--r--staging_vespalib/src/tests/growablebytebuffer/CMakeLists.txt8
-rw-r--r--staging_vespalib/src/tests/growablebytebuffer/growablebytebuffer_test.cpp39
-rw-r--r--staging_vespalib/src/tests/health_server/.gitignore0
-rw-r--r--staging_vespalib/src/tests/json/.gitignore1
-rw-r--r--staging_vespalib/src/tests/json/CMakeLists.txt8
-rw-r--r--staging_vespalib/src/tests/json/json.cpp473
-rw-r--r--staging_vespalib/src/tests/librarypool/.gitignore1
-rw-r--r--staging_vespalib/src/tests/librarypool/CMakeLists.txt8
-rw-r--r--staging_vespalib/src/tests/librarypool/DESC1
-rw-r--r--staging_vespalib/src/tests/librarypool/FILES1
-rw-r--r--staging_vespalib/src/tests/librarypool/librarypool_test.cpp41
-rw-r--r--staging_vespalib/src/tests/memorydatastore/.gitignore1
-rw-r--r--staging_vespalib/src/tests/memorydatastore/CMakeLists.txt8
-rw-r--r--staging_vespalib/src/tests/memorydatastore/memorydatastore.cpp75
-rw-r--r--staging_vespalib/src/tests/objectdump/.gitignore4
-rw-r--r--staging_vespalib/src/tests/objectdump/CMakeLists.txt8
-rw-r--r--staging_vespalib/src/tests/objectdump/DESC1
-rw-r--r--staging_vespalib/src/tests/objectdump/FILES1
-rw-r--r--staging_vespalib/src/tests/objectdump/objectdump.cpp107
-rw-r--r--staging_vespalib/src/tests/objects/.gitignore5
-rw-r--r--staging_vespalib/src/tests/objects/CMakeLists.txt8
-rw-r--r--staging_vespalib/src/tests/objects/DESC2
-rw-r--r--staging_vespalib/src/tests/objects/FILES2
-rw-r--r--staging_vespalib/src/tests/objects/identifiable_test.cpp339
-rw-r--r--staging_vespalib/src/tests/objectselection/.gitignore4
-rw-r--r--staging_vespalib/src/tests/objectselection/CMakeLists.txt8
-rw-r--r--staging_vespalib/src/tests/objectselection/DESC1
-rw-r--r--staging_vespalib/src/tests/objectselection/FILES1
-rw-r--r--staging_vespalib/src/tests/objectselection/objectselection.cpp93
-rw-r--r--staging_vespalib/src/tests/polymorphicarray/.gitignore1
-rw-r--r--staging_vespalib/src/tests/polymorphicarray/CMakeLists.txt8
-rw-r--r--staging_vespalib/src/tests/polymorphicarray/DESC1
-rw-r--r--staging_vespalib/src/tests/polymorphicarray/FILES1
-rw-r--r--staging_vespalib/src/tests/polymorphicarray/polymorphicarray_test.cpp123
-rw-r--r--staging_vespalib/src/tests/programoptions/.gitignore4
-rw-r--r--staging_vespalib/src/tests/programoptions/CMakeLists.txt8
-rw-r--r--staging_vespalib/src/tests/programoptions/DESC1
-rw-r--r--staging_vespalib/src/tests/programoptions/FILES1
-rw-r--r--staging_vespalib/src/tests/programoptions/programoptions_test.cpp362
-rw-r--r--staging_vespalib/src/tests/rusage/.gitignore1
-rw-r--r--staging_vespalib/src/tests/rusage/CMakeLists.txt8
-rw-r--r--staging_vespalib/src/tests/rusage/DESC1
-rw-r--r--staging_vespalib/src/tests/rusage/FILES1
-rw-r--r--staging_vespalib/src/tests/rusage/rusage_test.cpp76
-rw-r--r--staging_vespalib/src/tests/shutdownguard/.gitignore1
-rw-r--r--staging_vespalib/src/tests/shutdownguard/CMakeLists.txt8
-rw-r--r--staging_vespalib/src/tests/shutdownguard/DESC1
-rw-r--r--staging_vespalib/src/tests/shutdownguard/FILES1
-rw-r--r--staging_vespalib/src/tests/shutdownguard/shutdownguard_test.cpp40
-rw-r--r--staging_vespalib/src/tests/state_server/.gitignore1
-rw-r--r--staging_vespalib/src/tests/state_server/CMakeLists.txt8
-rw-r--r--staging_vespalib/src/tests/state_server/FILES1
-rw-r--r--staging_vespalib/src/tests/state_server/state_server_test.cpp444
-rw-r--r--staging_vespalib/src/tests/stllike/.gitignore6
-rw-r--r--staging_vespalib/src/tests/stllike/CMakeLists.txt15
-rw-r--r--staging_vespalib/src/tests/stllike/DESC1
-rw-r--r--staging_vespalib/src/tests/stllike/FILES3
-rw-r--r--staging_vespalib/src/tests/stllike/avl.cpp265
-rw-r--r--staging_vespalib/src/tests/stllike/cache_test.cpp165
-rw-r--r--staging_vespalib/src/tests/stllike/lrucache.cpp192
-rw-r--r--staging_vespalib/src/tests/timer/.gitignore1
-rw-r--r--staging_vespalib/src/tests/timer/CMakeLists.txt8
-rw-r--r--staging_vespalib/src/tests/timer/timer_test.cpp60
-rw-r--r--staging_vespalib/src/tests/trace/.gitignore1
-rw-r--r--staging_vespalib/src/tests/trace/CMakeLists.txt8
-rw-r--r--staging_vespalib/src/tests/trace/trace.cpp110
-rw-r--r--staging_vespalib/src/tests/util/process_memory_stats/.gitignore2
-rw-r--r--staging_vespalib/src/tests/util/process_memory_stats/CMakeLists.txt8
-rw-r--r--staging_vespalib/src/tests/util/process_memory_stats/DESC1
-rw-r--r--staging_vespalib/src/tests/util/process_memory_stats/FILES1
-rw-r--r--staging_vespalib/src/tests/util/process_memory_stats/process_memory_stats_test.cpp79
-rwxr-xr-xstaging_vespalib/src/tests/util/process_memory_stats/process_memory_stats_test.sh4
-rw-r--r--staging_vespalib/src/tests/xmlserializable/.gitignore4
-rw-r--r--staging_vespalib/src/tests/xmlserializable/CMakeLists.txt8
-rw-r--r--staging_vespalib/src/tests/xmlserializable/DESC1
-rw-r--r--staging_vespalib/src/tests/xmlserializable/FILES1
-rw-r--r--staging_vespalib/src/tests/xmlserializable/xmlserializabletest.cpp165
141 files changed, 6044 insertions, 0 deletions
diff --git a/staging_vespalib/src/tests/.gitignore b/staging_vespalib/src/tests/.gitignore
new file mode 100644
index 00000000000..c473b24b98a
--- /dev/null
+++ b/staging_vespalib/src/tests/.gitignore
@@ -0,0 +1,4 @@
+.depend
+Makefile
+testrunner
+*_test
diff --git a/staging_vespalib/src/tests/array/.gitignore b/staging_vespalib/src/tests/array/.gitignore
new file mode 100644
index 00000000000..154e6464c50
--- /dev/null
+++ b/staging_vespalib/src/tests/array/.gitignore
@@ -0,0 +1,5 @@
+/sort_benchmark
+/allocinarray_benchmark
+staging_vespalib_allocinarray_test_app
+staging_vespalib_allocinarray_benchmark_app
+staging_vespalib_sort_benchmark_app
diff --git a/staging_vespalib/src/tests/array/CMakeLists.txt b/staging_vespalib/src/tests/array/CMakeLists.txt
new file mode 100644
index 00000000000..7b9841d474a
--- /dev/null
+++ b/staging_vespalib/src/tests/array/CMakeLists.txt
@@ -0,0 +1,22 @@
+# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(staging_vespalib_allocinarray_test_app
+ SOURCES
+ allocinarray_test.cpp
+ DEPENDS
+ staging_vespalib
+)
+vespa_add_test(NAME staging_vespalib_allocinarray_test_app COMMAND staging_vespalib_allocinarray_test_app)
+vespa_add_executable(staging_vespalib_sort_benchmark_app
+ SOURCES
+ sort_benchmark.cpp
+ DEPENDS
+ staging_vespalib
+)
+vespa_add_test(NAME staging_vespalib_sort_benchmark_app COMMAND staging_vespalib_sort_benchmark_app BENCHMARK)
+vespa_add_executable(staging_vespalib_allocinarray_benchmark_app
+ SOURCES
+ allocinarray_benchmark.cpp
+ DEPENDS
+ staging_vespalib
+)
+vespa_add_test(NAME staging_vespalib_allocinarray_benchmark_app COMMAND staging_vespalib_allocinarray_benchmark_app BENCHMARK)
diff --git a/staging_vespalib/src/tests/array/DESC b/staging_vespalib/src/tests/array/DESC
new file mode 100644
index 00000000000..59c59c2c50a
--- /dev/null
+++ b/staging_vespalib/src/tests/array/DESC
@@ -0,0 +1 @@
+Array test. Take a look at array_test.cpp for details.
diff --git a/staging_vespalib/src/tests/array/FILES b/staging_vespalib/src/tests/array/FILES
new file mode 100644
index 00000000000..fa3825f832f
--- /dev/null
+++ b/staging_vespalib/src/tests/array/FILES
@@ -0,0 +1 @@
+array_test.cpp
diff --git a/staging_vespalib/src/tests/array/allocinarray_benchmark.cpp b/staging_vespalib/src/tests/array/allocinarray_benchmark.cpp
new file mode 100644
index 00000000000..9f365ff937c
--- /dev/null
+++ b/staging_vespalib/src/tests/array/allocinarray_benchmark.cpp
@@ -0,0 +1,124 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/fastos/fastos.h>
+#include <vespa/vespalib/testkit/testapp.h>
+#include <vespa/vespalib/util/rusage.h>
+#include <vespa/vespalib/util/optimized.h>
+#include <vespa/vespalib/util/allocinarray.h>
+#include <vespa/log/log.h>
+LOG_SETUP("allocinarray_benchmark");
+
+using namespace vespalib;
+
+class Test : public TestApp
+{
+public:
+private:
+ void benchmarkTree(size_t count);
+ void benchmarkTreeInArray(size_t count);
+ int Main();
+};
+
+template <typename T>
+class TreeNode
+{
+public:
+ typedef TreeNode * P;
+ TreeNode(const T & p) :_left(NULL), _right(NULL), _payLoad(p) { }
+ ~TreeNode() {
+ if (_left) {
+ delete _left;
+ }
+ if (_right) {
+ delete _right;
+ }
+ }
+ P left() { return _left; }
+ P right() { return _right; }
+ void left(P l) { _left = l; }
+ void right(P l) { _right = l; }
+private:
+ P _left;
+ P _right;
+ T _payLoad;
+};
+
+template <typename T>
+class RefTreeNode
+{
+public:
+ typedef uint32_t P;
+ RefTreeNode(const T & p) :_left(-1), _right(-1), _payLoad(p) { }
+ P left() { return _left; }
+ P right() { return _right; }
+ void left(P l) { _left = l; }
+ void right(P l) { _right = l; }
+private:
+ P _left;
+ P _right;
+ T _payLoad;
+};
+
+typedef TreeNode<long> N;
+typedef RefTreeNode<long> R;
+typedef AllocInArray<R, vespalib::Array<R, MMapAlloc> > Store;
+
+void populate(Store & store, uint32_t parent, size_t depth)
+{
+ if (depth > 0) {
+ store[parent].left(store.alloc(R(0)));
+ populate(store, store[parent].left(), depth-1);
+ store[parent].right(store.alloc(R(1)));
+ populate(store, store[parent].right(), depth-1);
+ }
+}
+
+void populate(N * parent, size_t depth)
+{
+ if (depth > 0) {
+ parent->left(new N(0));
+ populate(parent->left(), depth-1);
+ parent->right(new N(1));
+ populate(parent->right(), depth-1);
+ }
+}
+
+void Test::benchmarkTree(size_t count)
+{
+ N root(0);
+ size_t depth = Optimized::msbIdx(count);
+ populate(&root, depth);
+}
+
+void Test::benchmarkTreeInArray(size_t count)
+{
+ Store store;
+ store.alloc(R(0));
+ size_t depth = Optimized::msbIdx(count);
+ populate(store, 0, depth);
+}
+
+int
+Test::Main()
+{
+ std::string type("direct");
+ size_t count = 1000000;
+ if (_argc > 1) {
+ type = _argv[1];
+ }
+ if (_argc > 2) {
+ count = strtol(_argv[2], NULL, 0);
+ }
+ TEST_INIT("allocinarray_benchmark");
+ fastos::TimeStamp start(fastos::ClockSystem::now());
+ if (type == "direct") {
+ benchmarkTree(count);
+ } else {
+ benchmarkTreeInArray(count);
+ }
+ LOG(info, "rusage = {\n%s\n}", vespalib::RUsage::createSelf(start).toString().c_str());
+ ASSERT_EQUAL(0, kill(0, SIGPROF));
+ TEST_DONE();
+}
+
+TEST_APPHOOK(Test);
+
diff --git a/staging_vespalib/src/tests/array/allocinarray_test.cpp b/staging_vespalib/src/tests/array/allocinarray_test.cpp
new file mode 100644
index 00000000000..3a40a71f288
--- /dev/null
+++ b/staging_vespalib/src/tests/array/allocinarray_test.cpp
@@ -0,0 +1,75 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/fastos/fastos.h>
+#include <vespa/log/log.h>
+#include <vespa/vespalib/util/array.h>
+#include <vespa/vespalib/util/allocinarray.h>
+#include <vespa/vespalib/stllike/string.h>
+#include <vespa/vespalib/testkit/testapp.h>
+#include <deque>
+
+LOG_SETUP("array_test");
+
+using namespace vespalib;
+
+class Test : public TestApp
+{
+public:
+ int Main();
+private:
+ template <typename T, typename V>
+ void testAllocInArray();
+};
+
+int
+Test::Main()
+{
+ TEST_INIT("allocinarray_test");
+
+ testAllocInArray<int64_t, vespalib::Array<int64_t> >();
+ testAllocInArray<int64_t, vespalib::Array<int64_t, vespalib::DefaultAlloc> >();
+ testAllocInArray<int64_t, std::vector<int64_t> >();
+ testAllocInArray<int64_t, std::deque<int64_t> >();
+
+ TEST_DONE();
+}
+
+template <typename T, typename V>
+void Test::testAllocInArray()
+{
+ typedef AllocInArray<T, V> AA;
+ AA alloc;
+ EXPECT_EQUAL(0ul, alloc.size());
+ EXPECT_EQUAL(0ul, alloc.alloc(1));
+ EXPECT_EQUAL(1ul, alloc.size());
+ EXPECT_EQUAL(1, alloc[0]);
+ alloc.free(0);
+ EXPECT_EQUAL(0ul, alloc.size());
+ alloc.free(0);
+ EXPECT_EQUAL(0ul, alloc.size());
+ alloc.free(1);
+ EXPECT_EQUAL(0ul, alloc.size());
+
+ alloc.alloc(7);
+ alloc.alloc(17);
+ alloc.alloc(-17);
+ EXPECT_EQUAL(3ul, alloc.size());
+ EXPECT_EQUAL(7, alloc[0]);
+ EXPECT_EQUAL(17, alloc[1]);
+ EXPECT_EQUAL(-17, alloc[2]);
+ alloc[1] = 99;
+ EXPECT_EQUAL(99, alloc[1]);
+ alloc.free(1);
+ EXPECT_EQUAL(2ul, alloc.size());
+ EXPECT_EQUAL(7, alloc[0]);
+ EXPECT_EQUAL(-17, alloc[2]);
+ EXPECT_EQUAL(1ul, alloc.alloc(103));
+ EXPECT_EQUAL(3ul, alloc.size());
+ EXPECT_EQUAL(7, alloc[0]);
+ EXPECT_EQUAL(103, alloc[1]);
+ EXPECT_EQUAL(-17, alloc[2]);
+
+ alloc.clear();
+ EXPECT_EQUAL(0ul, alloc.size());
+}
+
+TEST_APPHOOK(Test)
diff --git a/staging_vespalib/src/tests/array/sort_benchmark.cpp b/staging_vespalib/src/tests/array/sort_benchmark.cpp
new file mode 100644
index 00000000000..bb304f92d58
--- /dev/null
+++ b/staging_vespalib/src/tests/array/sort_benchmark.cpp
@@ -0,0 +1,182 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/fastos/fastos.h>
+#include <vespa/vespalib/testkit/testapp.h>
+#include <vespa/vespalib/util/rusage.h>
+#include <vespa/vespalib/util/array.h>
+#include <vespa/log/log.h>
+LOG_SETUP("sort_benchmark");
+
+using namespace vespalib;
+
+class Test : public TestApp
+{
+public:
+private:
+ template<typename T>
+ vespalib::Array<T> create(size_t count);
+ template<typename T>
+ void sortDirect(size_t count);
+ template<typename T>
+ void sortInDirect(size_t count);
+ int Main();
+};
+
+template<size_t N>
+class TT
+{
+public:
+ TT(uint64_t v) : _v(v) { }
+ bool operator < (const TT & rhs) const { return _v < rhs._v; }
+private:
+ uint64_t _v;
+ uint8_t _payLoad[N - sizeof(uint64_t)];
+};
+
+template <typename T>
+class I
+{
+public:
+ I(const T * p) : _p(p) { }
+ bool operator < (const I & rhs) const { return *_p < *rhs._p; }
+private:
+ const T * _p;
+};
+
+template<typename T>
+vespalib::Array<T>
+Test::create(size_t count)
+{
+ vespalib::Array<T> v;
+ v.reserve(count);
+ srand(0);
+ for (size_t i(0); i < count; i++) {
+ v.push_back(rand());
+ }
+ return v;
+}
+
+template<typename T>
+void Test::sortDirect(size_t count)
+{
+ vespalib::Array<T> v(create<T>(count));
+ LOG(info, "Running sortDirect with %ld count and payload of %ld", v.size(), sizeof(T));
+ for (size_t j=0; j < 10; j++) {
+ vespalib::Array<T> t(v);
+ std::sort(t.begin(), t.end());
+ }
+}
+
+template<typename T>
+void Test::sortInDirect(size_t count)
+{
+ vespalib::Array<T> k(create<T>(count));
+ LOG(info, "Running sortInDirect with %ld count and payload of %ld", k.size(), sizeof(T));
+ vespalib::Array< I<T> > v;
+ v.reserve(k.size());
+ for (size_t i(0), m(k.size()); i < m; i++) {
+ v.push_back(&k[i]);
+ }
+ for (size_t j=0; j < 10; j++) {
+ vespalib::Array< I<T> > t(v);
+ std::sort(t.begin(), t.end());
+ }
+}
+
+int
+Test::Main()
+{
+ std::string type("sortdirect");
+ size_t count = 1000000;
+ size_t payLoad = 0;
+ if (_argc > 1) {
+ type = _argv[1];
+ }
+ if (_argc > 2) {
+ count = strtol(_argv[2], NULL, 0);
+ }
+ if (_argc > 3) {
+ payLoad = strtol(_argv[3], NULL, 0);
+ }
+ TEST_INIT("sort_benchmark");
+ fastos::TimeStamp start(fastos::ClockSystem::now());
+ if (payLoad < 8) {
+ typedef TT<8> T;
+ if (type == "sortdirect") {
+ sortDirect<T>(count);
+ } else if (type == "sortindirect") {
+ sortInDirect<T>(count);
+ } else {
+ LOG(warning, "type '%s' is unknown", type.c_str());
+ }
+ } else if (payLoad < 16) {
+ typedef TT<16> T;
+ if (type == "sortdirect") {
+ sortDirect<T>(count);
+ } else if (type == "sortindirect") {
+ sortInDirect<T>(count);
+ } else {
+ LOG(warning, "type '%s' is unknown", type.c_str());
+ }
+ } else if (payLoad < 32) {
+ typedef TT<32> T;
+ if (type == "sortdirect") {
+ sortDirect<T>(count);
+ } else if (type == "sortindirect") {
+ sortInDirect<T>(count);
+ } else {
+ LOG(warning, "type '%s' is unknown", type.c_str());
+ }
+ } else if (payLoad < 64) {
+ typedef TT<64> T;
+ if (type == "sortdirect") {
+ sortDirect<T>(count);
+ } else if (type == "sortindirect") {
+ sortInDirect<T>(count);
+ } else {
+ LOG(warning, "type '%s' is unknown", type.c_str());
+ }
+ } else if (payLoad < 128) {
+ typedef TT<128> T;
+ if (type == "sortdirect") {
+ sortDirect<T>(count);
+ } else if (type == "sortindirect") {
+ sortInDirect<T>(count);
+ } else {
+ LOG(warning, "type '%s' is unknown", type.c_str());
+ }
+ } else if (payLoad < 256) {
+ typedef TT<256> T;
+ if (type == "sortdirect") {
+ sortDirect<T>(count);
+ } else if (type == "sortindirect") {
+ sortInDirect<T>(count);
+ } else {
+ LOG(warning, "type '%s' is unknown", type.c_str());
+ }
+ } else if (payLoad < 512) {
+ typedef TT<512> T;
+ if (type == "sortdirect") {
+ sortDirect<T>(count);
+ } else if (type == "sortindirect") {
+ sortInDirect<T>(count);
+ } else {
+ LOG(warning, "type '%s' is unknown", type.c_str());
+ }
+ } else {
+ typedef TT<1024> T;
+ LOG(info, "Payload %ld is too big to make any sense. Using %ld.", payLoad, sizeof(T));
+ if (type == "sortdirect") {
+ sortDirect<T>(count);
+ } else if (type == "sortindirect") {
+ sortInDirect<T>(count);
+ } else {
+ LOG(warning, "type '%s' is unknown", type.c_str());
+ }
+ }
+ LOG(info, "rusage = {\n%s\n}", vespalib::RUsage::createSelf(start).toString().c_str());
+ ASSERT_EQUAL(0, kill(0, SIGPROF));
+ TEST_DONE();
+}
+
+TEST_APPHOOK(Test);
+
diff --git a/staging_vespalib/src/tests/benchmark/.gitignore b/staging_vespalib/src/tests/benchmark/.gitignore
new file mode 100644
index 00000000000..789e52c1370
--- /dev/null
+++ b/staging_vespalib/src/tests/benchmark/.gitignore
@@ -0,0 +1,4 @@
+.depend
+Makefile
+benchmark_test
+staging_vespalib_benchmark_test_app
diff --git a/staging_vespalib/src/tests/benchmark/CMakeLists.txt b/staging_vespalib/src/tests/benchmark/CMakeLists.txt
new file mode 100644
index 00000000000..be8ea976c1d
--- /dev/null
+++ b/staging_vespalib/src/tests/benchmark/CMakeLists.txt
@@ -0,0 +1,9 @@
+# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(staging_vespalib_benchmark_test_app
+ SOURCES
+ benchmark.cpp
+ testbase.cpp
+ DEPENDS
+ staging_vespalib
+)
+vespa_add_test(NAME staging_vespalib_benchmark_test NO_VALGRIND COMMAND sh benchmark_test.sh BENCHMARK)
diff --git a/staging_vespalib/src/tests/benchmark/DESC b/staging_vespalib/src/tests/benchmark/DESC
new file mode 100644
index 00000000000..cc3b175dace
--- /dev/null
+++ b/staging_vespalib/src/tests/benchmark/DESC
@@ -0,0 +1 @@
+This is so far a test to show benchmarks of different programming techniques.
diff --git a/staging_vespalib/src/tests/benchmark/FILES b/staging_vespalib/src/tests/benchmark/FILES
new file mode 100644
index 00000000000..30525d50897
--- /dev/null
+++ b/staging_vespalib/src/tests/benchmark/FILES
@@ -0,0 +1 @@
+benchmark.cpp
diff --git a/staging_vespalib/src/tests/benchmark/benchmark.cpp b/staging_vespalib/src/tests/benchmark/benchmark.cpp
new file mode 100644
index 00000000000..1c4c5a59c63
--- /dev/null
+++ b/staging_vespalib/src/tests/benchmark/benchmark.cpp
@@ -0,0 +1,30 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/fastos/fastos.h>
+#include <vespa/log/log.h>
+LOG_SETUP("benchmark_test");
+#include <vespa/vespalib/testkit/testapp.h>
+#include "testbase.h"
+
+using namespace vespalib;
+
+TEST_SETUP(Test)
+
+int
+Test::Main()
+{
+ TEST_INIT("benchmark_test");
+
+ if (_argc > 1) {
+ size_t concurrency(1);
+ size_t numRuns(1000);
+ if (_argc > 2) {
+ numRuns = strtoul(_argv[2], NULL, 0);
+ if (_argc > 3) {
+ concurrency = strtoul(_argv[3], NULL, 0);
+ }
+ }
+ Benchmark::run(_argv[1], numRuns, concurrency);
+ }
+
+ TEST_DONE();
+}
diff --git a/staging_vespalib/src/tests/benchmark/benchmark_test.sh b/staging_vespalib/src/tests/benchmark/benchmark_test.sh
new file mode 100755
index 00000000000..ce0a56ee545
--- /dev/null
+++ b/staging_vespalib/src/tests/benchmark/benchmark_test.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+TIME=time
+
+$TIME ./staging_vespalib_benchmark_test_app vespalib::ParamByReferenceVectorInt 200000 1
+$TIME ./staging_vespalib_benchmark_test_app vespalib::ParamByValueVectorInt 4000 1
+$TIME ./staging_vespalib_benchmark_test_app vespalib::ParamByReferenceVectorString 30000 1
+$TIME ./staging_vespalib_benchmark_test_app vespalib::ParamByValueVectorString 40 1
+$TIME ./staging_vespalib_benchmark_test_app vespalib::ReturnByReferenceVectorString 10 1
+$TIME ./staging_vespalib_benchmark_test_app vespalib::ReturnByValueVectorString 10 1
+$TIME ./staging_vespalib_benchmark_test_app vespalib::ReturnByValueMultiVectorString 10 1
+$TIME ./staging_vespalib_benchmark_test_app vespalib::ClockSystem 1000 1
+$TIME ./staging_vespalib_benchmark_test_app vespalib::ClockGToD 1000 1
+$TIME ./staging_vespalib_benchmark_test_app vespalib::ClockGToD 20000 1
+$TIME./staging_vespalib_benchmark_test_app vespalib::ClockREALTIME 1000 1
+$TIME ./staging_vespalib_benchmark_test_app vespalib::ClockMONOTONIC 1000 1
+$TIME ./staging_vespalib_benchmark_test_app vespalib::ClockMONOTONIC_RAW 1000 1
+$TIME ./staging_vespalib_benchmark_test_app vespalib::ClockPROCESS_CPUTIME_ID 2500 1
+$TIME ./staging_vespalib_benchmark_test_app vespalib::ClockTHREAD_CPUTIME_ID 2500 1
+$TIME ./staging_vespalib_benchmark_test_app vespalib::CreateVespalibString 20000 1
diff --git a/staging_vespalib/src/tests/benchmark/testbase.cpp b/staging_vespalib/src/tests/benchmark/testbase.cpp
new file mode 100644
index 00000000000..9ac20638218
--- /dev/null
+++ b/staging_vespalib/src/tests/benchmark/testbase.cpp
@@ -0,0 +1,278 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/fastos/fastos.h>
+//#include <linux/time.h>
+#include <vespa/log/log.h>
+#include <vespa/fastos/timestamp.h>
+#include "testbase.h"
+
+LOG_SETUP(".testbase");
+
+namespace vespalib {
+
+IMPLEMENT_IDENTIFIABLE_ABSTRACT_NS(vespalib, Benchmark, Identifiable);
+
+IMPLEMENT_BENCHMARK(ParamByReferenceVectorInt, Benchmark);
+IMPLEMENT_BENCHMARK(ParamByValueVectorInt, Benchmark);
+IMPLEMENT_BENCHMARK(ParamByReferenceVectorString, Benchmark);
+IMPLEMENT_BENCHMARK(ParamByValueVectorString, Benchmark);
+IMPLEMENT_BENCHMARK(ReturnByReferenceVectorString, Benchmark);
+IMPLEMENT_BENCHMARK(ReturnByValueVectorString, Benchmark);
+IMPLEMENT_BENCHMARK(ReturnByValueMultiVectorString, Benchmark);
+IMPLEMENT_BENCHMARK(ClockSystem, Benchmark);
+IMPLEMENT_BENCHMARK(ClockREALTIME, Benchmark);
+IMPLEMENT_BENCHMARK(ClockMONOTONIC, Benchmark);
+IMPLEMENT_BENCHMARK(ClockMONOTONIC_RAW, Benchmark);
+IMPLEMENT_BENCHMARK(ClockPROCESS_CPUTIME_ID, Benchmark);
+IMPLEMENT_BENCHMARK(ClockTHREAD_CPUTIME_ID, Benchmark);
+IMPLEMENT_BENCHMARK(CreateVespalibString, Benchmark);
+
+void Benchmark::run(const char *name, size_t numRuns, size_t concurrency)
+{
+ const Identifiable::RuntimeClass * cInfo = Identifiable::classFromName(name);
+ if (cInfo) {
+ std::unique_ptr<Benchmark> test(static_cast<Benchmark *>(cInfo->create()));
+ test->run(numRuns, concurrency);
+ } else {
+ LOG(warning, "Could not find any test with the name %s", name);
+ }
+}
+void Benchmark::run(size_t numRuns, size_t concurrency)
+{
+ LOG(info, "Starting benchmark %s with %ld threads and %ld rep", getClass().name(), concurrency, numRuns);
+ for (size_t i(0); i < numRuns; i++) {
+ onRun();
+ }
+ LOG(info, "Stopping benchmark %s", getClass().name());
+}
+
+size_t ParamByReferenceVectorInt::callByReference(const Vector & values) const
+{
+ return values.size();
+}
+
+size_t ParamByReferenceVectorInt::onRun()
+{
+ Vector values(1000);
+ size_t sum(0);
+ for (size_t i=0; i < 1000; i++) {
+ sum += callByReference(values);
+ }
+ return sum;
+}
+
+size_t ParamByValueVectorInt::callByValue(Vector values) const
+{
+ return values.size();
+}
+
+size_t ParamByValueVectorInt::onRun()
+{
+ Vector values(1000);
+ size_t sum(0);
+ for (size_t i=0; i < 1000; i++) {
+ sum += callByValue(values);
+ }
+ return sum;
+}
+
+size_t ParamByReferenceVectorString::callByReference(const Vector & values) const
+{
+ return values.size();
+}
+
+size_t ParamByReferenceVectorString::onRun()
+{
+ Vector values(1000, "This is a simple string copy test");
+ size_t sum(0);
+ for (size_t i=0; i < 1000; i++) {
+ sum += callByReference(values);
+ }
+ return sum;
+}
+
+size_t ParamByValueVectorString::callByValue(Vector values) const
+{
+ return values.size();
+}
+
+size_t ParamByValueVectorString::onRun()
+{
+ Vector values(1000, "This is a simple string copy test");
+ size_t sum(0);
+ for (size_t i=0; i < 1000; i++) {
+ sum += callByValue(values);
+ }
+ return sum;
+}
+
+const ReturnByReferenceVectorString::Vector & ReturnByReferenceVectorString::returnByReference(Vector & param) const
+{
+ Vector values(1000, "return by value");
+ param.swap(values);
+ return param;
+}
+
+size_t ReturnByReferenceVectorString::onRun()
+{
+ size_t sum(0);
+ for (size_t i=0; i < 1000; i++) {
+ Vector values;
+ sum += returnByReference(values).size();
+ }
+ return sum;
+}
+
+ReturnByValueVectorString::Vector ReturnByValueVectorString::returnByValue() const
+{
+ Vector values;
+ if (rand() % 7) {
+ Vector tmp(1000, "return by value");
+ values.swap(tmp);
+ } else {
+ Vector tmp(1000, "Return by value");
+ values.swap(tmp);
+ }
+ return values;
+}
+
+size_t ReturnByValueVectorString::onRun()
+{
+ size_t sum(0);
+ for (size_t i=0; i < 1000; i++) {
+ sum += returnByValue().size();
+ }
+ return sum;
+}
+
+ReturnByValueMultiVectorString::Vector ReturnByValueMultiVectorString::returnByValue() const
+{
+ if (rand() % 7) {
+ Vector values(1000, "return by value");
+ return values;
+ } else {
+ Vector values(1000, "Return by value");
+ return values;
+ }
+}
+
+size_t ReturnByValueMultiVectorString::onRun()
+{
+ size_t sum(0);
+ for (size_t i=0; i < 1000; i++) {
+ sum += returnByValue().size();
+ }
+ return sum;
+}
+
+size_t ClockSystem::onRun()
+{
+ fastos::TimeStamp start(fastos::ClockSystem::now());
+ fastos::TimeStamp end(start);
+ for (size_t i=0; i < 1000; i++) {
+ end = fastos::ClockSystem::now();
+ }
+ return (start - end).ns();
+}
+
+size_t ClockREALTIME::onRun()
+{
+ struct timespec ts;
+ int foo = clock_gettime(CLOCK_REALTIME, &ts);
+ assert(foo == 0);
+ (void) foo;
+ fastos::TimeStamp start(ts.tv_sec*1000L*1000L*1000L + ts.tv_nsec);
+ fastos::TimeStamp end(start);
+ for (size_t i=0; i < 1000; i++) {
+ clock_gettime(CLOCK_REALTIME, &ts);
+ end = ts.tv_sec*1000L*1000L*1000L + ts.tv_nsec;
+ }
+ return (start - end).ns();
+}
+
+size_t ClockMONOTONIC::onRun()
+{
+ struct timespec ts;
+ int foo = clock_gettime(CLOCK_MONOTONIC, &ts);
+ assert(foo == 0);
+ (void) foo;
+ fastos::TimeStamp start(ts.tv_sec*1000L*1000L*1000L + ts.tv_nsec);
+ fastos::TimeStamp end(start);
+ for (size_t i=0; i < 1000; i++) {
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ end = ts.tv_sec*1000L*1000L*1000L + ts.tv_nsec;
+ }
+ return (start - end).ns();
+}
+
+ClockMONOTONIC_RAW::ClockMONOTONIC_RAW()
+{
+#ifndef CLOCK_MONOTONIC_RAW
+ LOG(warning, "CLOCK_MONOTONIC_RAW is not defined, using CLOCK_MONOTONIC instead.");
+#endif
+}
+
+#ifndef CLOCK_MONOTONIC_RAW
+ #define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC
+#endif
+
+size_t ClockMONOTONIC_RAW::onRun()
+{
+ struct timespec ts;
+ int foo = clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
+ assert(foo == 0);
+ (void) foo;
+ fastos::TimeStamp start(ts.tv_sec*1000L*1000L*1000L + ts.tv_nsec);
+ fastos::TimeStamp end(start);
+ for (size_t i=0; i < 1000; i++) {
+ clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
+ end = ts.tv_sec*1000L*1000L*1000L + ts.tv_nsec;
+ }
+ return (start - end).ns();
+}
+
+size_t ClockPROCESS_CPUTIME_ID::onRun()
+{
+ struct timespec ts;
+ int foo = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
+ assert(foo == 0);
+ (void) foo;
+ fastos::TimeStamp start(ts.tv_sec*1000L*1000L*1000L + ts.tv_nsec);
+ fastos::TimeStamp end(start);
+ for (size_t i=0; i < 1000; i++) {
+ clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
+ end = ts.tv_sec*1000L*1000L*1000L + ts.tv_nsec;
+ }
+ return (start - end).ns();
+}
+
+size_t ClockTHREAD_CPUTIME_ID::onRun()
+{
+ struct timespec ts;
+ int foo = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
+ assert(foo == 0);
+ (void) foo;
+ fastos::TimeStamp start(ts.tv_sec*1000L*1000L*1000L + ts.tv_nsec);
+ fastos::TimeStamp end(start);
+ for (size_t i=0; i < 1000; i++) {
+ clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
+ end = ts.tv_sec*1000L*1000L*1000L + ts.tv_nsec;
+ }
+ return (start - end).ns();
+}
+
+size_t CreateVespalibString::onRun()
+{
+ size_t sum(0);
+ const char * text1("Dette er en passe");
+ const char * text2(" kort streng som passer paa stacken");
+ char text[100];
+ strcpy(text, text1);
+ strcat(text, text2);
+ for (size_t i=0; i < 1000; i++) {
+ string s(text);
+ sum += s.size();
+ }
+ return sum;
+}
+
+}
diff --git a/staging_vespalib/src/tests/benchmark/testbase.h b/staging_vespalib/src/tests/benchmark/testbase.h
new file mode 100644
index 00000000000..45b0e30019e
--- /dev/null
+++ b/staging_vespalib/src/tests/benchmark/testbase.h
@@ -0,0 +1,169 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#pragma once
+
+#include <vespa/vespalib/objects/identifiable.h>
+#include <vector>
+#include <string>
+
+#define BENCHMARK_BASE_CID(n) (0x1000000 + n)
+
+#define CID_vespalib_Benchmark BENCHMARK_BASE_CID(0)
+#define CID_vespalib_ParamByReferenceVectorInt BENCHMARK_BASE_CID(1)
+#define CID_vespalib_ParamByReferenceVectorString BENCHMARK_BASE_CID(2)
+#define CID_vespalib_ParamByValueVectorInt BENCHMARK_BASE_CID(3)
+#define CID_vespalib_ParamByValueVectorString BENCHMARK_BASE_CID(4)
+#define CID_vespalib_ReturnByReferenceVectorString BENCHMARK_BASE_CID(5)
+#define CID_vespalib_ReturnByValueVectorString BENCHMARK_BASE_CID(6)
+#define CID_vespalib_ReturnByValueMultiVectorString BENCHMARK_BASE_CID(7)
+#define CID_vespalib_ClockSystem BENCHMARK_BASE_CID(8)
+#define CID_vespalib_ClockREALTIME BENCHMARK_BASE_CID(10)
+#define CID_vespalib_ClockMONOTONIC BENCHMARK_BASE_CID(11)
+#define CID_vespalib_ClockMONOTONIC_RAW BENCHMARK_BASE_CID(12)
+#define CID_vespalib_ClockPROCESS_CPUTIME_ID BENCHMARK_BASE_CID(13)
+#define CID_vespalib_ClockTHREAD_CPUTIME_ID BENCHMARK_BASE_CID(14)
+#define CID_vespalib_CreateVespalibString BENCHMARK_BASE_CID(15)
+
+#define DECLARE_BENCHMARK(a) DECLARE_IDENTIFIABLE_NS(vespalib, a)
+#define IMPLEMENT_BENCHMARK(a, d) IMPLEMENT_IDENTIFIABLE_NS(vespalib, a, d)
+
+namespace vespalib {
+
+class Benchmark : public Identifiable
+{
+public:
+ DECLARE_IDENTIFIABLE_ABSTRACT_NS(vespalib, Benchmark);
+ void run(size_t numRuns, size_t concurrency=1);
+ static void run(const char * testName, size_t numRuns, size_t concurrency);
+private:
+ virtual size_t onRun() = 0;
+};
+
+class ParamByReferenceVectorInt : public Benchmark
+{
+public:
+ DECLARE_BENCHMARK(ParamByReferenceVectorInt);
+private:
+ typedef std::vector<int> Vector;
+ size_t callByReference(const Vector & values) const __attribute__((noinline));
+ virtual size_t onRun();
+};
+
+class ParamByValueVectorInt : public Benchmark
+{
+public:
+ DECLARE_BENCHMARK(ParamByValueVectorInt);
+private:
+ typedef std::vector<int> Vector;
+ size_t callByValue(Vector values) const __attribute__((noinline));
+ virtual size_t onRun();
+};
+
+class ParamByReferenceVectorString : public Benchmark
+{
+public:
+ DECLARE_BENCHMARK(ParamByReferenceVectorString);
+private:
+ typedef std::vector<std::string> Vector;
+ size_t callByReference(const Vector & values) const __attribute__((noinline));
+ virtual size_t onRun();
+};
+
+class ParamByValueVectorString : public Benchmark
+{
+public:
+ DECLARE_BENCHMARK(ParamByValueVectorString);
+private:
+ typedef std::vector<std::string> Vector;
+ size_t callByValue(Vector values) const __attribute__((noinline));
+ virtual size_t onRun();
+};
+
+class ReturnByReferenceVectorString : public Benchmark
+{
+public:
+ DECLARE_BENCHMARK(ReturnByReferenceVectorString);
+private:
+ typedef std::vector<std::string> Vector;
+ const Vector & returnByReference(Vector & values) const __attribute__((noinline));
+ virtual size_t onRun();
+};
+
+class ReturnByValueVectorString : public Benchmark
+{
+public:
+ DECLARE_BENCHMARK(ReturnByValueVectorString);
+private:
+ typedef std::vector<std::string> Vector;
+ Vector returnByValue() const __attribute__((noinline));
+ virtual size_t onRun();
+};
+
+class ReturnByValueMultiVectorString : public Benchmark
+{
+public:
+ DECLARE_BENCHMARK(ReturnByValueMultiVectorString);
+private:
+ typedef std::vector<std::string> Vector;
+ Vector returnByValue() const __attribute__((noinline));
+ virtual size_t onRun();
+};
+
+class CreateVespalibString : public Benchmark
+{
+public:
+ DECLARE_BENCHMARK(CreateVespalibString);
+private:
+ virtual size_t onRun();
+};
+
+class ClockSystem : public Benchmark
+{
+public:
+ DECLARE_BENCHMARK(ClockSystem);
+private:
+ virtual size_t onRun();
+};
+
+class ClockREALTIME : public Benchmark
+{
+public:
+ DECLARE_BENCHMARK(ClockREALTIME);
+private:
+ virtual size_t onRun();
+};
+
+class ClockMONOTONIC : public Benchmark
+{
+public:
+ DECLARE_BENCHMARK(ClockMONOTONIC);
+private:
+ virtual size_t onRun();
+};
+
+class ClockMONOTONIC_RAW : public Benchmark
+{
+public:
+ DECLARE_BENCHMARK(ClockMONOTONIC_RAW);
+ ClockMONOTONIC_RAW();
+private:
+ virtual size_t onRun();
+};
+
+class ClockPROCESS_CPUTIME_ID : public Benchmark
+{
+public:
+ DECLARE_BENCHMARK(ClockPROCESS_CPUTIME_ID);
+private:
+ virtual size_t onRun();
+};
+
+class ClockTHREAD_CPUTIME_ID : public Benchmark
+{
+public:
+ DECLARE_BENCHMARK(ClockTHREAD_CPUTIME_ID);
+private:
+ virtual size_t onRun();
+};
+
+}
+
diff --git a/staging_vespalib/src/tests/bits/.gitignore b/staging_vespalib/src/tests/bits/.gitignore
new file mode 100644
index 00000000000..82481fe3c30
--- /dev/null
+++ b/staging_vespalib/src/tests/bits/.gitignore
@@ -0,0 +1,4 @@
+.depend
+Makefile
+bits_test
+staging_vespalib_bits_test_app
diff --git a/staging_vespalib/src/tests/bits/CMakeLists.txt b/staging_vespalib/src/tests/bits/CMakeLists.txt
new file mode 100644
index 00000000000..693b6cbb6cc
--- /dev/null
+++ b/staging_vespalib/src/tests/bits/CMakeLists.txt
@@ -0,0 +1,8 @@
+# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(staging_vespalib_bits_test_app
+ SOURCES
+ bits_test.cpp
+ DEPENDS
+ staging_vespalib
+)
+vespa_add_test(NAME staging_vespalib_bits_test_app COMMAND staging_vespalib_bits_test_app)
diff --git a/staging_vespalib/src/tests/bits/DESC b/staging_vespalib/src/tests/bits/DESC
new file mode 100644
index 00000000000..2ea242366ff
--- /dev/null
+++ b/staging_vespalib/src/tests/bits/DESC
@@ -0,0 +1 @@
+bit manipultaion test. Take a look at bits.cpp for details.
diff --git a/staging_vespalib/src/tests/bits/FILES b/staging_vespalib/src/tests/bits/FILES
new file mode 100644
index 00000000000..95ad604b592
--- /dev/null
+++ b/staging_vespalib/src/tests/bits/FILES
@@ -0,0 +1 @@
+bits.cpp
diff --git a/staging_vespalib/src/tests/bits/bits_test.cpp b/staging_vespalib/src/tests/bits/bits_test.cpp
new file mode 100644
index 00000000000..83e60f0f214
--- /dev/null
+++ b/staging_vespalib/src/tests/bits/bits_test.cpp
@@ -0,0 +1,58 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/fastos/fastos.h>
+#include <vespa/log/log.h>
+LOG_SETUP("bits_test");
+#include <vespa/vespalib/testkit/testapp.h>
+#include <vespa/vespalib/util/bits.h>
+#include <boost/crc.hpp>
+
+using namespace vespalib;
+
+class Test : public TestApp
+{
+public:
+ int Main();
+ template <typename T>
+ void testFixed(const T * v, size_t sz);
+ void testBuffer();
+};
+
+int
+Test::Main()
+{
+ TEST_INIT("bits_test");
+ uint8_t u8[5] = { 0, 1, 127, 135, 255 };
+ testFixed(u8, sizeof(u8)/sizeof(u8[0]));
+ uint16_t u16[5] = { 0, 1, 127, 135, 255 };
+ testFixed(u16, sizeof(u16)/sizeof(u16[0]));
+ uint32_t u32[5] = { 0, 1, 127, 135, 255 };
+ testFixed(u32, sizeof(u32)/sizeof(u32[0]));
+ uint64_t u64[5] = { 0, 1, 127, 135, 255 };
+ testFixed(u64, sizeof(u64)/sizeof(u64[0]));
+ testBuffer();
+ TEST_DONE();
+}
+
+template <typename T>
+void Test::testFixed(const T * v, size_t sz)
+{
+ EXPECT_EQUAL(0u, Bits::reverse(static_cast<T>(0)));
+ EXPECT_EQUAL(1ul << (sizeof(T)*8 - 1), Bits::reverse(static_cast<T>(1)));
+ EXPECT_EQUAL(static_cast<T>(-1), Bits::reverse(static_cast<T>(-1)));
+ for (size_t i(0); i < sz; i++) {
+ EXPECT_EQUAL(Bits::reverse(v[i]), boost::detail::reflector<sizeof(T)*8>::reflect(v[i]));
+ EXPECT_EQUAL(Bits::reverse(Bits::reverse(v[i])), v[i]);
+ }
+}
+
+void Test::testBuffer()
+{
+ uint64_t a(0x0102040810204080ul);
+ uint64_t b(a);
+ Bits::reverse(&a, sizeof(a));
+ EXPECT_EQUAL(a, Bits::reverse(b));
+ Bits::reverse(&a, sizeof(a));
+ EXPECT_EQUAL(a, b);
+}
+
+TEST_APPHOOK(Test)
diff --git a/staging_vespalib/src/tests/clock/.gitignore b/staging_vespalib/src/tests/clock/.gitignore
new file mode 100644
index 00000000000..1826ba1563b
--- /dev/null
+++ b/staging_vespalib/src/tests/clock/.gitignore
@@ -0,0 +1,4 @@
+.depend
+Makefile
+clock_test
+staging_vespalib_clock_test_app
diff --git a/staging_vespalib/src/tests/clock/CMakeLists.txt b/staging_vespalib/src/tests/clock/CMakeLists.txt
new file mode 100644
index 00000000000..8717a6411ab
--- /dev/null
+++ b/staging_vespalib/src/tests/clock/CMakeLists.txt
@@ -0,0 +1,8 @@
+# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(staging_vespalib_clock_test_app
+ SOURCES
+ clock_test.cpp
+ DEPENDS
+ staging_vespalib
+)
+vespa_add_test(NAME staging_vespalib_clock_test_app COMMAND staging_vespalib_clock_test_app)
diff --git a/staging_vespalib/src/tests/clock/DESC b/staging_vespalib/src/tests/clock/DESC
new file mode 100644
index 00000000000..061f9af2d0a
--- /dev/null
+++ b/staging_vespalib/src/tests/clock/DESC
@@ -0,0 +1 @@
+Unit tests for the clock.
diff --git a/staging_vespalib/src/tests/clock/FILES b/staging_vespalib/src/tests/clock/FILES
new file mode 100644
index 00000000000..c0a2e8e47ea
--- /dev/null
+++ b/staging_vespalib/src/tests/clock/FILES
@@ -0,0 +1 @@
+clock.cpp
diff --git a/staging_vespalib/src/tests/clock/clock_test.cpp b/staging_vespalib/src/tests/clock/clock_test.cpp
new file mode 100644
index 00000000000..f7f15dd3d24
--- /dev/null
+++ b/staging_vespalib/src/tests/clock/clock_test.cpp
@@ -0,0 +1,38 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/fastos/fastos.h>
+#include <vespa/log/log.h>
+LOG_SETUP("sharedptr_test");
+#include <vespa/vespalib/util/clock.h>
+#include <vespa/vespalib/testkit/testapp.h>
+
+using vespalib::Clock;
+using fastos::TimeStamp;
+
+class Test : public vespalib::TestApp
+{
+public:
+ int Main();
+};
+
+
+int
+Test::Main()
+{
+ TEST_INIT("clock_test");
+
+ Clock clock(0.050);
+ FastOS_ThreadPool pool(0x10000);
+ ASSERT_TRUE(pool.NewThread(&clock, NULL) != NULL);
+ uint64_t start = clock.getTimeNS();
+ FastOS_Thread::Sleep(5000);
+ uint64_t stop = clock.getTimeNS();
+ EXPECT_TRUE(stop > start);
+ FastOS_Thread::Sleep(6000);
+ clock.stop();
+ uint64_t stop2 = clock.getTimeNS();
+ EXPECT_TRUE(stop2 > stop);
+ EXPECT_TRUE((stop2 - stop)/TimeStamp::MICRO > 1000);
+ TEST_DONE();
+}
+
+TEST_APPHOOK(Test)
diff --git a/staging_vespalib/src/tests/cpu/.gitignore b/staging_vespalib/src/tests/cpu/.gitignore
new file mode 100644
index 00000000000..eea6ced9753
--- /dev/null
+++ b/staging_vespalib/src/tests/cpu/.gitignore
@@ -0,0 +1,4 @@
+.depend
+Makefile
+cpu_test
+staging_vespalib_cpu_test_app
diff --git a/staging_vespalib/src/tests/cpu/CMakeLists.txt b/staging_vespalib/src/tests/cpu/CMakeLists.txt
new file mode 100644
index 00000000000..13bc4014d85
--- /dev/null
+++ b/staging_vespalib/src/tests/cpu/CMakeLists.txt
@@ -0,0 +1,8 @@
+# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(staging_vespalib_cpu_test_app
+ SOURCES
+ cpu_test.cpp
+ DEPENDS
+ staging_vespalib
+)
+vespa_add_test(NAME staging_vespalib_cpu_test_app COMMAND staging_vespalib_cpu_test_app)
diff --git a/staging_vespalib/src/tests/cpu/DESC b/staging_vespalib/src/tests/cpu/DESC
new file mode 100644
index 00000000000..19de1b44450
--- /dev/null
+++ b/staging_vespalib/src/tests/cpu/DESC
@@ -0,0 +1 @@
+cpu special instructions test. Take a look at cpu.cpp for details.
diff --git a/staging_vespalib/src/tests/cpu/FILES b/staging_vespalib/src/tests/cpu/FILES
new file mode 100644
index 00000000000..6abb996b510
--- /dev/null
+++ b/staging_vespalib/src/tests/cpu/FILES
@@ -0,0 +1 @@
+cpu.cpp
diff --git a/staging_vespalib/src/tests/cpu/cpu_test.cpp b/staging_vespalib/src/tests/cpu/cpu_test.cpp
new file mode 100644
index 00000000000..56f109e47a4
--- /dev/null
+++ b/staging_vespalib/src/tests/cpu/cpu_test.cpp
@@ -0,0 +1,33 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/fastos/fastos.h>
+#include <vespa/log/log.h>
+LOG_SETUP("cpu_test");
+#include <vespa/vespalib/testkit/testapp.h>
+#include <vespa/vespalib/util/cpu.h>
+
+using namespace vespalib;
+
+class Test : public vespalib::TestApp
+{
+public:
+ int Main();
+};
+
+int Test::Main()
+{
+ TEST_INIT("cpu_test");
+
+ const X86CpuInfo & cpu = X86CpuInfo::cpuInfo();
+ EXPECT_TRUE(cpu.hasMMX());
+ EXPECT_TRUE(cpu.hasSSE());
+ EXPECT_TRUE(cpu.hasSSE2());
+ EXPECT_TRUE(cpu.hasSSE3());
+ EXPECT_TRUE(cpu.hasCX16());
+
+ X86CpuInfo::print(stdout);
+
+ TEST_FLUSH();
+ TEST_DONE();
+}
+
+TEST_APPHOOK(Test)
diff --git a/staging_vespalib/src/tests/crc/.gitignore b/staging_vespalib/src/tests/crc/.gitignore
new file mode 100644
index 00000000000..448fa141b03
--- /dev/null
+++ b/staging_vespalib/src/tests/crc/.gitignore
@@ -0,0 +1,4 @@
+.depend
+Makefile
+crc_test
+staging_vespalib_crc_test_app
diff --git a/staging_vespalib/src/tests/crc/CMakeLists.txt b/staging_vespalib/src/tests/crc/CMakeLists.txt
new file mode 100644
index 00000000000..cc8e828d0d4
--- /dev/null
+++ b/staging_vespalib/src/tests/crc/CMakeLists.txt
@@ -0,0 +1,8 @@
+# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(staging_vespalib_crc_test_app
+ SOURCES
+ crc_test.cpp
+ DEPENDS
+ staging_vespalib
+)
+vespa_add_test(NAME staging_vespalib_crc_test_app COMMAND staging_vespalib_crc_test_app boost)
diff --git a/staging_vespalib/src/tests/crc/DESC b/staging_vespalib/src/tests/crc/DESC
new file mode 100644
index 00000000000..587969f7773
--- /dev/null
+++ b/staging_vespalib/src/tests/crc/DESC
@@ -0,0 +1 @@
+crc test. Take a look at crc.cpp for details.
diff --git a/staging_vespalib/src/tests/crc/FILES b/staging_vespalib/src/tests/crc/FILES
new file mode 100644
index 00000000000..2e867a09e10
--- /dev/null
+++ b/staging_vespalib/src/tests/crc/FILES
@@ -0,0 +1 @@
+crc.cpp
diff --git a/staging_vespalib/src/tests/crc/crc_test.cpp b/staging_vespalib/src/tests/crc/crc_test.cpp
new file mode 100644
index 00000000000..6c028cc09ce
--- /dev/null
+++ b/staging_vespalib/src/tests/crc/crc_test.cpp
@@ -0,0 +1,80 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/fastos/fastos.h>
+#include <vespa/log/log.h>
+LOG_SETUP("crc_test");
+#include <vespa/vespalib/testkit/testapp.h>
+#include <vespa/vespalib/util/crc.h>
+#include <boost/crc.hpp>
+#include <vector>
+
+using namespace vespalib;
+
+class Test : public TestApp
+{
+public:
+ int Main();
+ void testCorrectNess();
+ void testBenchmark(bool our, size_t bufSz, size_t numRep);
+};
+
+int
+Test::Main()
+{
+ TEST_INIT("crc_test");
+ testCorrectNess();
+ if (_argc >= 2) {
+ testBenchmark(false, 1024, 1000*1000);
+ } else {
+ testBenchmark(true, 1024, 1000*1000);
+ }
+ TEST_DONE();
+}
+
+void Test::testCorrectNess()
+{
+ const char *a[7] = { "", "a", "ab", "abc", "abcd", "abcde", "doc:crawler:http://www.ntnu.no/" };
+ for (size_t i(0); i < sizeof(a)/sizeof(a[0]); i++) {
+ uint32_t vespaCrc32 = crc_32_type::crc(a[i], strlen(a[i]));
+ boost::crc_32_type calculator;
+ calculator.process_bytes(a[i], strlen(a[i]));
+ EXPECT_EQUAL(vespaCrc32, calculator.checksum());
+ vespalib::crc_32_type calculator2;
+ calculator2.process_bytes(a[i], strlen(a[i]));
+ EXPECT_EQUAL(vespaCrc32, calculator2.checksum());
+ EXPECT_EQUAL(calculator.checksum(), calculator2.checksum());
+ }
+ vespalib::crc_32_type calculator2;
+ boost::crc_32_type calculator;
+ for (size_t i(0); i < sizeof(a)/sizeof(a[0]); i++) {
+ calculator.process_bytes(a[i], strlen(a[i]));
+ calculator2.process_bytes(a[i], strlen(a[i]));
+ EXPECT_EQUAL(calculator.checksum(), calculator2.checksum());
+ }
+ EXPECT_EQUAL(calculator.checksum(), calculator2.checksum());
+}
+
+void Test::testBenchmark(bool our, size_t bufSz, size_t numRep)
+{
+ std::vector<char> a(numRep+bufSz);
+ for(size_t i(0), m(a.size()); i < m; i++) {
+ a[i] = i&0xff;
+ }
+ uint32_t sum(0);
+ if (our) {
+ for (size_t i(0); i < (numRep); i++) {
+ //sum ^= crc_32_type::crc(&a[i], bufSz);
+ vespalib::crc_32_type calculator;
+ calculator.process_bytes(&a[i], bufSz);
+ sum ^=calculator.checksum();
+ }
+ } else {
+ for (size_t i(0); i < (numRep); i++) {
+ boost::crc_32_type calculator;
+ calculator.process_bytes(&a[i], bufSz);
+ sum ^=calculator.checksum();
+ }
+ }
+ printf("sum = %x\n", sum);
+}
+
+TEST_APPHOOK(Test)
diff --git a/staging_vespalib/src/tests/create-test.sh b/staging_vespalib/src/tests/create-test.sh
new file mode 100755
index 00000000000..56234dbab30
--- /dev/null
+++ b/staging_vespalib/src/tests/create-test.sh
@@ -0,0 +1,65 @@
+#!/bin/sh
+# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+gen_project_file() {
+ echo "generating '$1' ..."
+ echo "APPLICATION ${test}_test" > $1
+ echo "OBJS ${test}_test" >> $1
+ echo "LIBS vespalib/staging_vespalib" >> $1
+ echo "EXTERNALLIBS vespalib vespalog" >> $1
+ echo "" >> $1
+ echo "CUSTOMMAKE" >> $1
+ echo "test: depend ${test}_test" >> $1
+ echo -e "\t@./${test}_test" >> $1
+}
+
+gen_source() {
+ echo "generating '$1' ..."
+ echo "#include <vespa/log/log.h>" > $1
+ echo "LOG_SETUP(\"${test}_test\");" >> $1
+ echo "#include <vespa/fastos/fastos.h>" >> $1
+ echo "#include <vespa/vespalib/testkit/testapp.h>" >> $1
+ echo "" >> $1
+ echo "using namespace vespalib;" >> $1
+ echo "" >> $1
+ echo "TEST_SETUP(Test);" >> $1
+ echo "" >> $1
+ echo "int" >> $1
+ echo "Test::Main()" >> $1
+ echo "{" >> $1
+ echo " TEST_INIT(\"${test}_test\");" >> $1
+ echo " TEST_DONE();" >> $1
+ echo "}" >> $1
+}
+
+gen_desc() {
+ echo "generating '$1' ..."
+ echo "$test test. Take a look at ${test}_test.cpp for details." > $1
+}
+
+gen_file_list() {
+ echo "generating '$1' ..."
+ echo "${test}_test.cpp" > $1
+}
+
+if [ $# -ne 1 ]; then
+ echo "usage: $0 <name>"
+ echo " name: name of the test to create"
+ exit 1
+fi
+
+test=$1
+if [ -e $test ]; then
+ echo "$test already present, don't want to mess it up..."
+ exit 1
+fi
+
+echo "creating directory '$test' ..."
+mkdir -p $test || exit 1
+cd $test || exit 1
+test=`basename $test`
+
+gen_project_file fastos.project
+gen_source ${test}_test.cpp
+gen_desc DESC
+gen_file_list FILES
diff --git a/staging_vespalib/src/tests/databuffer/.gitignore b/staging_vespalib/src/tests/databuffer/.gitignore
new file mode 100644
index 00000000000..e7b0e69c372
--- /dev/null
+++ b/staging_vespalib/src/tests/databuffer/.gitignore
@@ -0,0 +1 @@
+staging_vespalib_databuffer_test_app
diff --git a/staging_vespalib/src/tests/databuffer/CMakeLists.txt b/staging_vespalib/src/tests/databuffer/CMakeLists.txt
new file mode 100644
index 00000000000..65eae47a502
--- /dev/null
+++ b/staging_vespalib/src/tests/databuffer/CMakeLists.txt
@@ -0,0 +1,8 @@
+# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(staging_vespalib_databuffer_test_app
+ SOURCES
+ databuffer_test.cpp
+ DEPENDS
+ staging_vespalib
+)
+vespa_add_test(NAME staging_vespalib_databuffer_test_app COMMAND staging_vespalib_databuffer_test_app)
diff --git a/staging_vespalib/src/tests/databuffer/databuffer_test.cpp b/staging_vespalib/src/tests/databuffer/databuffer_test.cpp
new file mode 100644
index 00000000000..3793af27aa7
--- /dev/null
+++ b/staging_vespalib/src/tests/databuffer/databuffer_test.cpp
@@ -0,0 +1,145 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/fastos/fastos.h>
+#include <vespa/log/log.h>
+LOG_SETUP("databuffer_test");
+
+#include <vespa/vespalib/testkit/testapp.h>
+#include <vespa/vespalib/data/databuffer.h>
+#include <iostream>
+
+using namespace vespalib;
+
+class Test : public vespalib::TestApp {
+private:
+ void testBasic();
+public:
+ int Main() {
+ TEST_INIT("databuffer_test");
+
+ testBasic(); TEST_FLUSH();
+
+ TEST_DONE();
+ }
+};
+
+TEST_APPHOOK(Test);
+
+void
+Test::testBasic()
+{
+ DataBuffer a(50);
+ EXPECT_EQUAL(256u, a.getBufSize());
+ EXPECT_EQUAL(a.getFreeLen(), a.getBufSize());
+ a.ensureFree(1000);
+ EXPECT_EQUAL(1024u, a.getBufSize());
+ EXPECT_EQUAL(a.getFreeLen(), a.getBufSize());
+ EXPECT_EQUAL(0u, a.getDeadLen());
+ EXPECT_EQUAL(0u, a.getDataLen());
+ EXPECT_EQUAL(a.getData(), a.getDead());
+ EXPECT_EQUAL(a.getData(), a.getFree());
+ EXPECT_EQUAL(a.getBufSize(), a.getFreeLen());
+ a.assertValid();
+
+ a.writeInt16(7);
+ EXPECT_EQUAL(0u, a.getDeadLen());
+ EXPECT_EQUAL(2u, a.getDataLen());
+ EXPECT_EQUAL(a.getBufSize()-2, a.getFreeLen());
+ EXPECT_EQUAL(a.getData(), a.getDead());
+ EXPECT_EQUAL(a.getData()+2, a.getFree());
+ a.clear();
+ EXPECT_EQUAL(0u, a.getDeadLen());
+ EXPECT_EQUAL(0u, a.getDataLen());
+ EXPECT_EQUAL(a.getBufSize(), a.getFreeLen());
+
+ a.writeInt8(0xaau);
+ EXPECT_EQUAL(1u, a.getDataLen());
+ EXPECT_EQUAL(0xaau, a.peekInt8(0));
+ EXPECT_EQUAL(1u, a.getDataLen());
+ EXPECT_EQUAL(0xaau, a.readInt8());
+ EXPECT_EQUAL(0u, a.getDataLen());
+
+ a.writeInt16(0xaabbu);
+ EXPECT_EQUAL(2u, a.getDataLen());
+ EXPECT_EQUAL(0xaabbu, a.peekInt16(0));
+ EXPECT_EQUAL(2u, a.getDataLen());
+ EXPECT_EQUAL(0xaabbu, a.readInt16());
+ EXPECT_EQUAL(0u, a.getDataLen());
+ a.writeInt16(0xaabbu);
+ EXPECT_EQUAL(2u, a.getDataLen());
+ EXPECT_EQUAL(0xbbaau, a.peekInt16Reverse(0));
+ EXPECT_EQUAL(2u, a.getDataLen());
+ EXPECT_EQUAL(0xbbaau, a.readInt16Reverse());
+ EXPECT_EQUAL(0u, a.getDataLen());
+
+ a.writeInt32(0xaabbccddu);
+ EXPECT_EQUAL(4u, a.getDataLen());
+ EXPECT_EQUAL(0xaabbccddu, a.peekInt32(0));
+ EXPECT_EQUAL(4u, a.getDataLen());
+ EXPECT_EQUAL(0xaabbccddu, a.readInt32());
+ EXPECT_EQUAL(0u, a.getDataLen());
+ a.writeInt32(0xaabbccddu);
+ EXPECT_EQUAL(4u, a.getDataLen());
+ EXPECT_EQUAL(0xddccbbaau, a.peekInt32Reverse(0));
+ EXPECT_EQUAL(4u, a.getDataLen());
+ EXPECT_EQUAL(0xddccbbaau, a.readInt32Reverse());
+ EXPECT_EQUAL(0u, a.getDataLen());
+
+ a.writeInt64(0xaabbccddeeff9988ul);
+ EXPECT_EQUAL(8u, a.getDataLen());
+ EXPECT_EQUAL(0xaabbccddeeff9988ul, a.peekInt64(0));
+ EXPECT_EQUAL(8u, a.getDataLen());
+ EXPECT_EQUAL(0xaabbccddeeff9988ul, a.readInt64());
+ EXPECT_EQUAL(0u, a.getDataLen());
+ a.writeInt64(0xaabbccddeeff9988ul);
+ EXPECT_EQUAL(8u, a.getDataLen());
+ EXPECT_EQUAL(0x8899ffeeddccbbaaul, a.peekInt64Reverse(0));
+ EXPECT_EQUAL(8u, a.getDataLen());
+ EXPECT_EQUAL(0x8899ffeeddccbbaaul, a.readInt64Reverse());
+ EXPECT_EQUAL(0u, a.getDataLen());
+
+ a.writeFloat(8.9f);
+ EXPECT_EQUAL(4u, a.getDataLen());
+ EXPECT_EQUAL(8.9f, a.readFloat());
+ EXPECT_EQUAL(0u, a.getDataLen());
+
+ a.writeDouble(8.9);
+ EXPECT_EQUAL(8u, a.getDataLen());
+ EXPECT_EQUAL(8.9, a.readDouble());
+ EXPECT_EQUAL(0u, a.getDataLen());
+
+ const char *c = "abc";
+ char b[3];
+ a.writeBytes(c, 3);
+ EXPECT_EQUAL(3u, a.getDataLen());
+ EXPECT_EQUAL(0, memcmp(c, a.getData(), a.getDataLen()));
+ a.peekBytes(b, 3, 0);
+ EXPECT_EQUAL(3u, a.getDataLen());
+ EXPECT_EQUAL(0, memcmp(c, b, sizeof(b)));
+ a.readBytes(b, sizeof(b));
+ EXPECT_EQUAL(0u, a.getDataLen());
+ EXPECT_EQUAL(0, memcmp(c, b, sizeof(b)));
+
+ a.writeInt64(67);
+ EXPECT_EQUAL(8u, a.getDataLen());
+ EXPECT_FALSE(a.shrink(1025));
+ EXPECT_FALSE(a.shrink(7));
+ EXPECT_TRUE(a.shrink(16));
+ EXPECT_EQUAL(8u, a.getDataLen());
+ EXPECT_EQUAL(16u, a.getBufSize());
+
+ a.writeInt64(89);
+ EXPECT_EQUAL(16u, a.getDataLen());
+ EXPECT_EQUAL(16u, a.getBufSize());
+ EXPECT_EQUAL(0u, a.getDeadLen());
+ EXPECT_EQUAL(67u, a.readInt64());
+ EXPECT_EQUAL(8u, a.getDataLen());
+ EXPECT_EQUAL(8u, a.getDeadLen());
+ EXPECT_EQUAL(16u, a.getBufSize());
+ a.pack(16);
+ EXPECT_EQUAL(8u, a.getDataLen());
+ EXPECT_EQUAL(0u, a.getDeadLen());
+ EXPECT_EQUAL(256u, a.getBufSize());
+ EXPECT_EQUAL(89u, a.readInt64());
+ EXPECT_EQUAL(0u, a.getDataLen());
+ EXPECT_EQUAL(256u, a.getBufSize());
+}
diff --git a/staging_vespalib/src/tests/directio/.gitignore b/staging_vespalib/src/tests/directio/.gitignore
new file mode 100644
index 00000000000..6e6dbe13324
--- /dev/null
+++ b/staging_vespalib/src/tests/directio/.gitignore
@@ -0,0 +1 @@
+staging_vespalib_directio_test_app
diff --git a/staging_vespalib/src/tests/directio/CMakeLists.txt b/staging_vespalib/src/tests/directio/CMakeLists.txt
new file mode 100644
index 00000000000..334ae825bf6
--- /dev/null
+++ b/staging_vespalib/src/tests/directio/CMakeLists.txt
@@ -0,0 +1,8 @@
+# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(staging_vespalib_directio_test_app
+ SOURCES
+ directio.cpp
+ DEPENDS
+ staging_vespalib
+)
+vespa_add_test(NAME staging_vespalib_directio_test_app COMMAND staging_vespalib_directio_test_app)
diff --git a/staging_vespalib/src/tests/directio/directio.cpp b/staging_vespalib/src/tests/directio/directio.cpp
new file mode 100644
index 00000000000..570d7276bc9
--- /dev/null
+++ b/staging_vespalib/src/tests/directio/directio.cpp
@@ -0,0 +1,58 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/fastos/fastos.h>
+#include <vespa/log/log.h>
+LOG_SETUP("directio_test");
+#include <vespa/vespalib/testkit/test_kit.h>
+#include <vespa/vespalib/stllike/string.h>
+#include <vespa/vespalib/data/databuffer.h>
+
+using namespace fastos;
+using namespace vespalib;
+
+TEST("that DirectIOException propagates the correct information.") {
+ const char *msg("The buffer");
+ DirectIOException e("file.a", msg, 10, 3);
+ EXPECT_EQUAL(10u, e.getLength());
+ EXPECT_EQUAL(3u, e.getOffset());
+ EXPECT_EQUAL(msg, e.getBuffer());
+ EXPECT_EQUAL(0u, string(e.what()).find("DirectIO failed for file 'file.a' buffer="));
+ EXPECT_EQUAL(string("file.a"), e.getFileName());
+}
+
+TEST("that DirectIOException is thrown on unaligned buf.") {
+ FastOS_File f("staging_vespalib_directio_test_app");
+ f.EnableDirectIO();
+ EXPECT_TRUE(f.OpenReadOnly());
+ DataBuffer buf(10000, 4096);
+ bool caught(false);
+ try {
+ f.ReadBuf(buf.getFree()+1, 4096, 0);
+ } catch (const DirectIOException & e) {
+ EXPECT_EQUAL(4096u, e.getLength());
+ EXPECT_EQUAL(0u, e.getOffset());
+ EXPECT_EQUAL(buf.getFree()+1, e.getBuffer());
+ EXPECT_EQUAL(string(f.GetFileName()), e.getFileName());
+ caught = true;
+ }
+ EXPECT_TRUE(caught);
+}
+
+TEST("that DirectIOException is thrown on unaligned offset.") {
+ FastOS_File f("staging_vespalib_directio_test_app");
+ f.EnableDirectIO();
+ EXPECT_TRUE(f.OpenReadOnly());
+ DataBuffer buf(10000, 4096);
+ bool caught(false);
+ try {
+ f.ReadBuf(buf.getFree(), 4096, 1);
+ } catch (const DirectIOException & e) {
+ EXPECT_EQUAL(4096u, e.getLength());
+ EXPECT_EQUAL(1u, e.getOffset());
+ EXPECT_EQUAL(buf.getFree(), e.getBuffer());
+ EXPECT_EQUAL(string(f.GetFileName()), e.getFileName());
+ caught = true;
+ }
+ EXPECT_TRUE(caught);
+}
+
+TEST_MAIN() { TEST_RUN_ALL(); }
diff --git a/staging_vespalib/src/tests/dotproduct/.gitignore b/staging_vespalib/src/tests/dotproduct/.gitignore
new file mode 100644
index 00000000000..5d9432fbd08
--- /dev/null
+++ b/staging_vespalib/src/tests/dotproduct/.gitignore
@@ -0,0 +1,2 @@
+dotproductbenchmark
+staging_vespalib_dotproductbenchmark_app
diff --git a/staging_vespalib/src/tests/dotproduct/CMakeLists.txt b/staging_vespalib/src/tests/dotproduct/CMakeLists.txt
new file mode 100644
index 00000000000..30a02632f1c
--- /dev/null
+++ b/staging_vespalib/src/tests/dotproduct/CMakeLists.txt
@@ -0,0 +1,21 @@
+# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(staging_vespalib_dotproductbenchmark_app
+ SOURCES
+ dotproductbenchmark.cpp
+ DEPENDS
+ staging_vespalib
+)
+vespa_add_test(NAME staging_vespalib_dotproductbenchmark_app_sparse-ordered COMMAND staging_vespalib_dotproductbenchmark_app 10 10 1000 1000 BENCHMARK)
+vespa_add_test(NAME staging_vespalib_dotproductbenchmark_app_sparse-unordered COMMAND staging_vespalib_dotproductbenchmark_app 10 10 1000 1000 BENCHMARK)
+vespa_add_test(NAME staging_vespalib_dotproductbenchmark_app_full COMMAND staging_vespalib_dotproductbenchmark_app 10 10 1000 1000 BENCHMARK)
+
+# benchmark: dotproductbenchmark
+# $(HIDE)$(LDL) time $(VALGRIND) ./dotproductbenchmark sparse-ordered 1000 1000 1000 1000
+# $(HIDE)$(LDL) time $(VALGRIND) ./dotproductbenchmark sparse-unordered 1000 1000 1000 1000
+# $(HIDE)$(LDL) time $(VALGRIND) ./dotproductbenchmark full 1000 1000 1000 1000
+# $(HIDE)$(LDL) time $(VALGRIND) ./dotproductbenchmark sparse-ordered 1000 1000 100 1000
+# $(HIDE)$(LDL) time $(VALGRIND) ./dotproductbenchmark sparse-unordered 1000 1000 100 1000
+# $(HIDE)$(LDL) time $(VALGRIND) ./dotproductbenchmark full 1000 1000 100 1000
+# $(HIDE)$(LDL) time $(VALGRIND) ./dotproductbenchmark sparse-ordered 1000 1000 1000 100
+# $(HIDE)$(LDL) time $(VALGRIND) ./dotproductbenchmark sparse-unordered 1000 1000 1000 100
+# $(HIDE)$(LDL) time $(VALGRIND) ./dotproductbenchmark full 1000 1000 1000 100
diff --git a/staging_vespalib/src/tests/dotproduct/dotproductbenchmark.cpp b/staging_vespalib/src/tests/dotproduct/dotproductbenchmark.cpp
new file mode 100644
index 00000000000..9ef3d959f3b
--- /dev/null
+++ b/staging_vespalib/src/tests/dotproduct/dotproductbenchmark.cpp
@@ -0,0 +1,179 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/fastos/fastos.h>
+#include <vespa/vespalib/hwaccelrated/iaccelrated.h>
+#include <vespa/vespalib/stllike/string.h>
+#include <vespa/vespalib/stllike/hash_map.h>
+#include <iostream>
+
+using namespace vespalib;
+using vespalib::hwaccelrated::IAccelrated;
+
+class Benchmark {
+public:
+ virtual ~Benchmark() { }
+ virtual void compute(size_t docId) const = 0;
+};
+
+void
+runBenchmark(size_t count, size_t docs, const Benchmark & benchmark)
+{
+ for (size_t i(0); i < count; i++) {
+ for (size_t docId(0); docId < docs; docId++) {
+ benchmark.compute(docId);
+ }
+ }
+}
+
+template <typename T>
+class FullBenchmark : public Benchmark
+{
+public:
+ FullBenchmark(size_t numDocs, size_t numValues) :
+ _values(numDocs*numValues),
+ _query(numValues),
+ _dp(IAccelrated::getAccelrator())
+ {
+ for (size_t i(0); i < numDocs; i++) {
+ for (size_t j(0); j < numValues; j++) {
+ _values[i*numValues + j] = j;
+ }
+ }
+ for (size_t j(0); j < numValues; j++) {
+ _query[j] = j;
+ }
+ }
+ virtual void compute(size_t docId) const {
+ _dp->dotProduct(&_query[0], &_values[docId * _query.size()], _query.size());
+ }
+private:
+ std::vector<T> _values;
+ std::vector<T> _query;
+ IAccelrated::UP _dp;
+};
+
+class SparseBenchmark : public Benchmark
+{
+public:
+ SparseBenchmark(size_t numDocs, size_t numValues, size_t numQueryValues) :
+ _numValues(numValues),
+ _values(numDocs*numValues)
+ {
+ for (size_t i(0); i < numDocs; i++) {
+ for (size_t j(0); j < numValues; j++) {
+ size_t k(numValues < numQueryValues ? (j*numQueryValues)/numValues : j);
+ _values[i*numValues + j] = P(k, k);
+ }
+ }
+ }
+protected:
+ struct P {
+ P(uint32_t key=0, int32_t value=0) :
+ _key(key),
+ _value(value)
+ { }
+ uint32_t _key;
+ int32_t _value;
+ };
+ size_t _numValues;
+ std::vector<P> _values;
+};
+
+class UnorderedSparseBenchmark : public SparseBenchmark
+{
+private:
+ typedef hash_map<uint32_t, int32_t> map;
+public:
+ UnorderedSparseBenchmark(size_t numDocs, size_t numValues, size_t numQueryValues) :
+ SparseBenchmark(numDocs, numValues, numQueryValues)
+ {
+ for (size_t j(0); j < numQueryValues; j++) {
+ _query[j] = j;
+ }
+ }
+private:
+ virtual void compute(size_t docId) const {
+ int64_t sum(0);
+ size_t offset(docId*_numValues);
+ const auto e(_query.end());
+ for (size_t i(0); i < _numValues; i++) {
+ auto it = _query.find(_values[offset + i]._key);
+ if (it != e) {
+ sum += static_cast<int64_t>(_values[offset + i]._value) * it->second;
+ }
+ }
+ }
+ map _query;
+};
+
+class OrderedSparseBenchmark : public SparseBenchmark
+{
+private:
+public:
+ OrderedSparseBenchmark(size_t numDocs, size_t numValues, size_t numQueryValues) :
+ SparseBenchmark(numDocs, numValues, numQueryValues),
+ _query(numQueryValues)
+ {
+ for (size_t j(0); j < numQueryValues; j++) {
+ size_t k(numValues > numQueryValues ? j*numValues/numQueryValues : j);
+ _query[j] = P(k, k);
+ }
+ }
+private:
+ virtual void compute(size_t docId) const {
+ int64_t sum(0);
+ size_t offset(docId*_numValues);
+
+ for (size_t a(0), b(0); a < _query.size() && b < _numValues; b++) {
+ for (; a < _query.size() && (_query[a]._key <= _values[offset + b]._key); a++);
+ if (_query[a]._key == _values[offset + b]._key) {
+ sum += static_cast<int64_t>(_values[offset + b]._value) * _query[a]._value;
+ }
+ }
+ }
+ std::vector<P> _query;
+};
+
+int main(int argc, char *argv[])
+{
+ size_t numDocs(1);
+ size_t numValues(1000);
+ size_t numQueryValues(1000);
+ size_t numQueries(1000000);
+ string type("full");
+ if ( argc > 1) {
+ type = argv[1];
+ }
+ if ( argc > 2) {
+ numQueries = strtoul(argv[2], NULL, 0);
+ }
+ if ( argc > 3) {
+ numDocs = strtoul(argv[3], NULL, 0);
+ }
+ if ( argc > 4) {
+ numValues = strtoul(argv[4], NULL, 0);
+ }
+ if ( argc > 5) {
+ numQueryValues = strtoul(argv[5], NULL, 0);
+ }
+
+ std::cout << "type = " << type << std::endl;
+ std::cout << "numQueries = " << numQueries << std::endl;
+ std::cout << "numDocs = " << numDocs << std::endl;
+ std::cout << "numValues = " << numValues << std::endl;
+ std::cout << "numQueryValues = " << numQueryValues << std::endl;
+ if (type == "full") {
+ FullBenchmark<int32_t> bm(numDocs, numValues);
+ runBenchmark(numQueries, numDocs, bm);
+ } else if (type == "sparse-ordered") {
+ OrderedSparseBenchmark bm(numDocs, numValues, numQueryValues);
+ runBenchmark(numQueries, numDocs, bm);
+ } else if (type == "sparse-unordered") {
+ UnorderedSparseBenchmark bm(numDocs, numValues, numQueryValues);
+ runBenchmark(numQueries, numDocs, bm);
+ } else {
+ std::cerr << "type '" << type << "' is unknown." << std::endl;
+ }
+
+ return 0;
+}
+
diff --git a/staging_vespalib/src/tests/encoding/.gitignore b/staging_vespalib/src/tests/encoding/.gitignore
new file mode 100644
index 00000000000..a3e9c375723
--- /dev/null
+++ b/staging_vespalib/src/tests/encoding/.gitignore
@@ -0,0 +1,3 @@
+.depend
+Makefile
+*_test
diff --git a/staging_vespalib/src/tests/encoding/base64/.gitignore b/staging_vespalib/src/tests/encoding/base64/.gitignore
new file mode 100644
index 00000000000..04f2994a28f
--- /dev/null
+++ b/staging_vespalib/src/tests/encoding/base64/.gitignore
@@ -0,0 +1 @@
+staging_vespalib_base64_test_app
diff --git a/staging_vespalib/src/tests/encoding/base64/CMakeLists.txt b/staging_vespalib/src/tests/encoding/base64/CMakeLists.txt
new file mode 100644
index 00000000000..bc515aa26d6
--- /dev/null
+++ b/staging_vespalib/src/tests/encoding/base64/CMakeLists.txt
@@ -0,0 +1,8 @@
+# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(staging_vespalib_base64_test_app
+ SOURCES
+ base64_test.cpp
+ DEPENDS
+ staging_vespalib
+)
+vespa_add_test(NAME staging_vespalib_base64_test_app COMMAND staging_vespalib_base64_test_app)
diff --git a/staging_vespalib/src/tests/encoding/base64/DESC b/staging_vespalib/src/tests/encoding/base64/DESC
new file mode 100644
index 00000000000..e9ece74e119
--- /dev/null
+++ b/staging_vespalib/src/tests/encoding/base64/DESC
@@ -0,0 +1 @@
+base64 test. Take a look at base64.cpp for details.
diff --git a/staging_vespalib/src/tests/encoding/base64/FILES b/staging_vespalib/src/tests/encoding/base64/FILES
new file mode 100644
index 00000000000..475b11151a3
--- /dev/null
+++ b/staging_vespalib/src/tests/encoding/base64/FILES
@@ -0,0 +1 @@
+base64.cpp
diff --git a/staging_vespalib/src/tests/encoding/base64/base64_test.cpp b/staging_vespalib/src/tests/encoding/base64/base64_test.cpp
new file mode 100644
index 00000000000..e765ac7d601
--- /dev/null
+++ b/staging_vespalib/src/tests/encoding/base64/base64_test.cpp
@@ -0,0 +1,89 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#include <vespa/fastos/fastos.h>
+#include <vespa/vespalib/encoding/base64.h>
+
+#include <vespa/log/log.h>
+#include <iostream>
+#include <vector>
+#include <vespa/vespalib/testkit/testapp.h>
+
+LOG_SETUP("base64_test");
+
+using namespace vespalib;
+
+TEST_SETUP(Test);
+
+int
+Test::Main()
+{
+ TEST_INIT("base64_test");
+
+ // Basic test without padding
+ std::string source = "No need to pad this string.";
+ std::string encoded = Base64::encode(source);
+ std::string expected = "Tm8gbmVlZCB0byBwYWQgdGhpcyBzdHJpbmcu";
+ std::string decoded = Base64::decode(encoded);
+
+ EXPECT_EQUAL(expected, encoded);
+ EXPECT_EQUAL(source, decoded);
+
+ EXPECT_TRUE(static_cast<uint32_t>(
+ Base64::getMaximumEncodeLength(source.size())) >= encoded.size());
+ EXPECT_TRUE(static_cast<uint32_t>(
+ Base64::getMaximumDecodeLength(encoded.size())) >= source.size());
+
+ // Basic string that needs padding
+ source = "This string will need to be padded.";
+ encoded = Base64::encode(source);
+ expected = "VGhpcyBzdHJpbmcgd2lsbCBuZWVkIHRvIGJlIHBhZGRlZC4=";
+ decoded = Base64::decode(encoded);
+
+ EXPECT_EQUAL(expected, encoded);
+ EXPECT_EQUAL(source, decoded);
+
+ EXPECT_TRUE(static_cast<uint32_t>(
+ Base64::getMaximumEncodeLength(source.size())) >= encoded.size());
+ EXPECT_TRUE(static_cast<uint32_t>(
+ Base64::getMaximumDecodeLength(encoded.size())) >= source.size());
+
+ // Check that max sizes are good for whatever input sizes
+ source = "";
+ for (uint32_t i=0; i<100; ++i) {
+ source += "a";
+ // Code will assert if -1 is returned from either
+ // getMaximumEncodeLength() or getMaximumDecodeLength().
+ encoded = Base64::encode(source);
+ decoded = Base64::decode(encoded);
+ EXPECT_EQUAL(source, decoded);
+ }
+
+ // Check that -1 is returned on too little space when encoding
+ source = "Checking that -1 is returned when not enough space to encode";
+ std::vector<char> buffer(100, '\0');
+ uint32_t minSizeNeeded = 81;
+ for (uint32_t i=0; i<minSizeNeeded; ++i) {
+ EXPECT_EQUAL(-1, Base64::encode(source.c_str(), source.size(),
+ &buffer[0], i));
+ }
+ EXPECT_EQUAL(80, Base64::encode(source.c_str(), source.size(),
+ &buffer[0], minSizeNeeded));
+ EXPECT_EQUAL(Base64::encode(source), std::string(&buffer[0], 80));
+ EXPECT_TRUE(minSizeNeeded <= static_cast<uint32_t>(
+ Base64::getMaximumEncodeLength(source.size())));
+
+ EXPECT_TRUE(buffer[80] == '\0');
+
+ // Check that -1 is returned on too little space when decoding
+ encoded = Base64::encode(source);
+ minSizeNeeded = 60;
+ for (uint32_t i=0; i<minSizeNeeded; ++i) {
+ EXPECT_EQUAL(-1, Base64::decode(encoded.c_str(), encoded.size(),
+ &buffer[0], i));
+ }
+ EXPECT_EQUAL(60, Base64::decode(encoded.c_str(), encoded.size(),
+ &buffer[0], minSizeNeeded));
+ EXPECT_EQUAL(source, std::string(&buffer[0], 60));
+
+ TEST_DONE();
+}
diff --git a/staging_vespalib/src/tests/fileheader/.gitignore b/staging_vespalib/src/tests/fileheader/.gitignore
new file mode 100644
index 00000000000..909655ba711
--- /dev/null
+++ b/staging_vespalib/src/tests/fileheader/.gitignore
@@ -0,0 +1,6 @@
+*.So
+.depend*
+Makefile
+fileheader.tmp
+fileheader_test
+staging_vespalib_fileheader_test_app
diff --git a/staging_vespalib/src/tests/fileheader/CMakeLists.txt b/staging_vespalib/src/tests/fileheader/CMakeLists.txt
new file mode 100644
index 00000000000..9e8e834147e
--- /dev/null
+++ b/staging_vespalib/src/tests/fileheader/CMakeLists.txt
@@ -0,0 +1,8 @@
+# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(staging_vespalib_fileheader_test_app
+ SOURCES
+ fileheader_test.cpp
+ DEPENDS
+ staging_vespalib
+)
+vespa_add_test(NAME staging_vespalib_fileheader_test_app COMMAND staging_vespalib_fileheader_test_app)
diff --git a/staging_vespalib/src/tests/fileheader/DESC b/staging_vespalib/src/tests/fileheader/DESC
new file mode 100644
index 00000000000..feb98035803
--- /dev/null
+++ b/staging_vespalib/src/tests/fileheader/DESC
@@ -0,0 +1 @@
+fileheader test. Take a look at fileheader.cpp for details.
diff --git a/staging_vespalib/src/tests/fileheader/FILES b/staging_vespalib/src/tests/fileheader/FILES
new file mode 100644
index 00000000000..f1ade37b054
--- /dev/null
+++ b/staging_vespalib/src/tests/fileheader/FILES
@@ -0,0 +1 @@
+fileheader.cpp
diff --git a/staging_vespalib/src/tests/fileheader/fileheader.dat b/staging_vespalib/src/tests/fileheader/fileheader.dat
new file mode 100644
index 00000000000..90660f64b98
--- /dev/null
+++ b/staging_vespalib/src/tests/fileheader/fileheader.dat
Binary files differ
diff --git a/staging_vespalib/src/tests/fileheader/fileheader_test.cpp b/staging_vespalib/src/tests/fileheader/fileheader_test.cpp
new file mode 100644
index 00000000000..2aaeeea58a8
--- /dev/null
+++ b/staging_vespalib/src/tests/fileheader/fileheader_test.cpp
@@ -0,0 +1,694 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/fastos/fastos.h>
+#include <vespa/log/log.h>
+LOG_SETUP("fileheader_test");
+
+#include <vespa/vespalib/testkit/testapp.h>
+#include <vespa/vespalib/data/fileheader.h>
+#include <iostream>
+
+using namespace vespalib;
+
+class Test : public vespalib::TestApp {
+private:
+ void testTag();
+ void testTagErrors();
+ void testTagIteration();
+ void testGenericHeader();
+ void testBufferReader();
+ void testBufferWriter();
+ void testBufferAccess();
+ void testFileReader();
+ void testFileWriter();
+ void testFileHeader();
+ void testFileAlign();
+ void testFileSize();
+ void testReadErrors();
+ bool testReadError(DataBuffer &buf, const std::string &expected);
+ void testWriteErrors();
+ void testRewriteErrors();
+ void testLayout();
+
+ void
+ testReadSize(bool mapped);
+
+ void
+ testReadSizeErrors(bool mapped);
+
+ bool
+ testReadSizeError(DataBuffer &buf, const std::string &expected,
+ bool mapped);
+
+public:
+ int Main() {
+ TEST_INIT("fileheader_test");
+
+ testTag(); TEST_FLUSH();
+ testTagErrors(); TEST_FLUSH();
+ testTagIteration(); TEST_FLUSH();
+ testGenericHeader(); TEST_FLUSH();
+ testBufferReader(); TEST_FLUSH();
+ testBufferWriter(); TEST_FLUSH();
+ testBufferAccess(); TEST_FLUSH();
+ testFileReader(); TEST_FLUSH();
+ testFileWriter(); TEST_FLUSH();
+ testFileHeader(); TEST_FLUSH();
+ testFileAlign(); TEST_FLUSH();
+ testFileSize(); TEST_FLUSH();
+ testReadErrors(); TEST_FLUSH();
+ testWriteErrors(); TEST_FLUSH();
+ testRewriteErrors(); TEST_FLUSH();
+ testLayout(); TEST_FLUSH();
+ testReadSize(false); TEST_FLUSH();
+ testReadSizeErrors(false); TEST_FLUSH();
+ testReadSize(true); TEST_FLUSH();
+ testReadSizeErrors(true); TEST_FLUSH();
+
+ TEST_DONE();
+ }
+};
+
+TEST_APPHOOK(Test);
+
+void
+Test::testTag()
+{
+ {
+ std::vector<GenericHeader::Tag> tags;
+ tags.push_back(GenericHeader::Tag("foo", 6.9));
+ tags.push_back(GenericHeader::Tag("foo", 6.9f));
+ for (std::vector<GenericHeader::Tag>::iterator it = tags.begin();
+ it != tags.end(); ++it)
+ {
+ GenericHeader::Tag tag = *it;
+ for (uint32_t i = 0; i < 2; ++i) {
+ EXPECT_EQUAL(GenericHeader::Tag::TYPE_FLOAT, tag.getType());
+ EXPECT_EQUAL("foo", tag.getName());
+ EXPECT_TRUE(tag.asString().empty());
+ EXPECT_APPROX(6.9, tag.asFloat(), 1E-6);
+ EXPECT_EQUAL(0, tag.asInteger());
+
+ uint32_t len = tag.getSize();
+ DataBuffer buf(len);
+ EXPECT_EQUAL(len, tag.write(buf));
+
+ GenericHeader::Tag tmp;
+ EXPECT_EQUAL(len, tmp.read(buf));
+ tag = tmp;
+ }
+ }
+ }
+ {
+ std::vector<GenericHeader::Tag> tags;
+ tags.push_back(GenericHeader::Tag("foo", (int8_t)69));
+ tags.push_back(GenericHeader::Tag("foo", (uint8_t)69));
+ tags.push_back(GenericHeader::Tag("foo", (int16_t)69));
+ tags.push_back(GenericHeader::Tag("foo", (uint16_t)69));
+ tags.push_back(GenericHeader::Tag("foo", (int32_t)69));
+ tags.push_back(GenericHeader::Tag("foo", (uint32_t)69));
+ tags.push_back(GenericHeader::Tag("foo", (int64_t)69));
+ for (std::vector<GenericHeader::Tag>::iterator it = tags.begin();
+ it != tags.end(); ++it)
+ {
+ GenericHeader::Tag tag = *it;
+ for (uint32_t i = 0; i < 2; ++i) {
+ EXPECT_EQUAL(GenericHeader::Tag::TYPE_INTEGER, tag.getType());
+ EXPECT_EQUAL("foo", tag.getName());
+ EXPECT_TRUE(tag.asString().empty());
+ EXPECT_EQUAL(0.0, tag.asFloat());
+ EXPECT_EQUAL(69l, tag.asInteger());
+
+ uint32_t len = tag.getSize();
+ DataBuffer buf(len);
+ EXPECT_EQUAL(len, tag.write(buf));
+
+ GenericHeader::Tag tmp;
+ EXPECT_EQUAL(len, tmp.read(buf));
+ tag = tmp;
+ }
+ }
+ }
+ {
+ GenericHeader::Tag tag("foo", "bar");
+ for (uint32_t i = 0; i < 2; ++i) {
+ EXPECT_EQUAL(GenericHeader::Tag::TYPE_STRING, tag.getType());
+ EXPECT_EQUAL("foo", tag.getName());
+ EXPECT_EQUAL("bar", tag.asString());
+ EXPECT_EQUAL(0.0, tag.asFloat());
+ EXPECT_EQUAL(0, tag.asInteger());
+
+ uint32_t len = tag.getSize();
+ DataBuffer buf(len);
+ EXPECT_EQUAL(len, tag.write(buf));
+
+ GenericHeader::Tag tmp;
+ EXPECT_EQUAL(len, tmp.read(buf));
+ tag = tmp;
+ }
+ }
+}
+
+void
+Test::testTagErrors()
+{
+ DataBuffer buf(1024);
+ buf.writeBytes("foo", 3);
+ buf.writeInt8(0);
+ buf.writeInt8((uint8_t)GenericHeader::Tag::TYPE_EMPTY);
+
+ GenericHeader::Tag tag("bar", 6.9);
+ try {
+ tag.read(buf);
+ EXPECT_TRUE(false);
+ } catch (IllegalHeaderException &e) {
+ EXPECT_EQUAL("Can not deserialize empty tag.", e.getMessage());
+ }
+ EXPECT_EQUAL("bar", tag.getName());
+ EXPECT_EQUAL(GenericHeader::Tag::TYPE_FLOAT, tag.getType());
+ EXPECT_EQUAL(6.9, tag.asFloat());
+}
+
+void
+Test::testTagIteration()
+{
+ GenericHeader header;
+ header.putTag(GenericHeader::Tag("foo", 6.9));
+ header.putTag(GenericHeader::Tag("bar", 6699));
+ header.putTag(GenericHeader::Tag("baz", "666999"));
+
+ EXPECT_EQUAL(3u, header.getNumTags());
+ EXPECT_EQUAL("bar", header.getTag(0).getName());
+ EXPECT_EQUAL("baz", header.getTag(1).getName());
+ EXPECT_EQUAL("foo", header.getTag(2).getName());
+}
+
+void
+Test::testGenericHeader()
+{
+ GenericHeader header;
+ EXPECT_TRUE(header.isEmpty());
+ EXPECT_EQUAL(0u, header.getNumTags());
+ EXPECT_TRUE(!header.hasTag("foo"));
+ EXPECT_TRUE(header.getTag("foo").isEmpty());
+ EXPECT_TRUE(!header.hasTag("bar"));
+ EXPECT_TRUE(header.getTag("bar").isEmpty());
+ EXPECT_TRUE(!header.hasTag("baz"));
+ EXPECT_TRUE(header.getTag("baz").isEmpty());
+
+ header.putTag(GenericHeader::Tag("foo", 6.9));
+ EXPECT_TRUE(!header.isEmpty());
+ EXPECT_EQUAL(1u, header.getNumTags());
+ EXPECT_TRUE(header.hasTag("foo"));
+ EXPECT_EQUAL(6.9, header.getTag("foo").asFloat());
+ EXPECT_TRUE(!header.hasTag("bar"));
+ EXPECT_TRUE(header.getTag("bar").isEmpty());
+ EXPECT_TRUE(!header.hasTag("baz"));
+ EXPECT_TRUE(header.getTag("baz").isEmpty());
+
+ header.putTag(GenericHeader::Tag("bar", 6699));
+ EXPECT_TRUE(!header.isEmpty());
+ EXPECT_EQUAL(2u, header.getNumTags());
+ EXPECT_TRUE(header.hasTag("foo"));
+ EXPECT_EQUAL(6.9, header.getTag("foo").asFloat());
+ EXPECT_TRUE(header.hasTag("bar"));
+ EXPECT_EQUAL(6699, header.getTag("bar").asInteger());
+ EXPECT_TRUE(!header.hasTag("baz"));
+ EXPECT_TRUE(header.getTag("baz").isEmpty());
+
+ header.putTag(GenericHeader::Tag("baz", "666999"));
+ EXPECT_TRUE(header.hasTag("foo"));
+ EXPECT_EQUAL(6.9, header.getTag("foo").asFloat());
+ EXPECT_TRUE(header.hasTag("bar"));
+ EXPECT_EQUAL(6699, header.getTag("bar").asInteger());
+ EXPECT_TRUE(header.hasTag("baz"));
+ EXPECT_EQUAL("666999", header.getTag("baz").asString());
+
+ header.removeTag("bar");
+ EXPECT_TRUE(header.hasTag("foo"));
+ EXPECT_EQUAL(6.9, header.getTag("foo").asFloat());
+ EXPECT_TRUE(!header.hasTag("bar"));
+ EXPECT_TRUE(header.getTag("bar").isEmpty());
+ EXPECT_TRUE(header.hasTag("baz"));
+ EXPECT_EQUAL("666999", header.getTag("baz").asString());
+
+ header.removeTag("foo");
+ EXPECT_TRUE(!header.hasTag("foo"));
+ EXPECT_TRUE(header.getTag("foo").isEmpty());
+ EXPECT_TRUE(!header.hasTag("bar"));
+ EXPECT_TRUE(header.getTag("bar").isEmpty());
+ EXPECT_TRUE(header.hasTag("baz"));
+ EXPECT_EQUAL("666999", header.getTag("baz").asString());
+
+ header.removeTag("baz");
+ EXPECT_TRUE(!header.hasTag("foo"));
+ EXPECT_TRUE(header.getTag("foo").isEmpty());
+ EXPECT_TRUE(!header.hasTag("bar"));
+ EXPECT_TRUE(header.getTag("bar").isEmpty());
+ EXPECT_TRUE(!header.hasTag("baz"));
+ EXPECT_TRUE(header.getTag("baz").isEmpty());
+}
+
+void
+Test::testBufferReader()
+{
+ DataBuffer src(256);
+ for (uint32_t i = 0; i < 256; ++i) {
+ src.writeInt8((uint8_t)i);
+ }
+
+ GenericHeader::BufferReader reader(src);
+
+ char dst[7];
+ uint32_t sum = 0;
+ while (sum < 256) {
+ uint32_t len = (uint32_t)reader.getData(dst, 7);
+ for (uint32_t i = 0; i < len; ++i) {
+ EXPECT_EQUAL(sum + i, (uint8_t)dst[i]);
+ }
+ sum += len;
+ }
+ EXPECT_EQUAL(256u, sum);
+}
+
+void
+Test::testBufferWriter()
+{
+ DataBuffer dst(256);
+ GenericHeader::BufferWriter writer(dst);
+
+ uint32_t sum = 0;
+ while(sum < 256) {
+ char src[7];
+ for (uint32_t i = 0; i < 7; ++i) {
+ src[i] = (uint8_t)(sum + i);
+ }
+ uint32_t len = std::min(7u, 256 - sum);
+ EXPECT_EQUAL(len, (uint32_t)writer.putData(src, len));
+ sum += len;
+ }
+ EXPECT_EQUAL(256u, sum);
+
+ // flip dst
+ for (uint32_t i = 0; i < 256; ++i) {
+ uint8_t b = dst.readInt8();
+ EXPECT_EQUAL(i, (uint32_t)b);
+ }
+}
+
+void
+Test::testBufferAccess()
+{
+ DataBuffer buf;
+ uint32_t len = 0;
+ {
+ GenericHeader header;
+ header.putTag(GenericHeader::Tag("foo", 6.9));
+ header.putTag(GenericHeader::Tag("bar", 6699));
+ header.putTag(GenericHeader::Tag("baz", "666999"));
+
+ int64_t bval = 0x1234567890abcdefLL;
+ header.putTag(GenericHeader::Tag("big", bval));
+
+ len = header.getSize();
+ buf.ensureFree(len);
+ GenericHeader::BufferWriter writer(buf);
+ EXPECT_EQUAL(len, header.write(writer));
+ }
+ {
+ GenericHeader header;
+ GenericHeader::BufferReader reader(buf);
+ EXPECT_EQUAL(len, header.read(reader));
+
+ EXPECT_TRUE(header.hasTag("foo"));
+ EXPECT_EQUAL(6.9, header.getTag("foo").asFloat());
+ EXPECT_TRUE(header.hasTag("bar"));
+ EXPECT_EQUAL(6699, header.getTag("bar").asInteger());
+ EXPECT_TRUE(header.hasTag("baz"));
+ EXPECT_EQUAL("666999", header.getTag("baz").asString());
+ EXPECT_TRUE(header.hasTag("big"));
+ EXPECT_EQUAL(0x1234567890abcdefLL, header.getTag("big").asInteger());
+ }
+}
+
+void
+Test::testFileReader()
+{
+ {
+ FastOS_File file;
+ ASSERT_TRUE(file.OpenWriteOnlyTruncate("fileheader.tmp"));
+
+ uint8_t buf[256];
+ for (uint32_t i = 0; i < 256; ++i) {
+ buf[i] = (uint8_t)i;
+ }
+ EXPECT_EQUAL(256, file.Write2(buf, 256));
+
+ file.Close();
+ }
+ {
+ FastOS_File file;
+ ASSERT_TRUE(file.OpenReadOnly("fileheader.tmp"));
+ FileHeader::FileReader reader(file);
+
+ char buf[7];
+ uint32_t sum = 0;
+ while(sum < 256) {
+ uint32_t len = (uint32_t)reader.getData(buf, 7);
+ for (uint32_t i = 0; i < len; ++i) {
+ EXPECT_EQUAL(sum + i, (uint8_t)buf[i]);
+ }
+ sum += len;
+ }
+ EXPECT_EQUAL(256u, sum);
+
+ file.Close();
+ file.Delete();
+ }
+}
+
+void
+Test::testFileWriter()
+{
+ {
+ FastOS_File file;
+ ASSERT_TRUE(file.OpenWriteOnlyTruncate("fileheader.tmp"));
+ FileHeader::FileWriter writer(file);
+
+ uint32_t sum = 0;
+ while(sum < 256) {
+ char src[7];
+ for (uint32_t i = 0; i < 7; ++i) {
+ src[i] = (uint8_t)(sum + i);
+ }
+ uint32_t len = std::min(7u, 256 - sum);
+ EXPECT_EQUAL(len, (uint32_t)writer.putData(src, len));
+ sum += len;
+ }
+ EXPECT_EQUAL(256u, sum);
+ }
+ {
+ FastOS_File file;
+ ASSERT_TRUE(file.OpenReadOnly("fileheader.tmp"));
+
+ uint8_t buf[256];
+ EXPECT_EQUAL(256, file.Read(buf, 256));
+ for (uint32_t i = 0; i < 256; ++i) {
+ EXPECT_EQUAL(i, (uint32_t)buf[i]);
+ }
+
+ file.Close();
+ file.Delete();
+ }
+}
+
+void
+Test::testFileHeader()
+{
+ uint32_t len = 0;
+ {
+ FileHeader header;
+ header.putTag(FileHeader::Tag("foo", 6.9));
+ header.putTag(FileHeader::Tag("bar", 6699));
+ header.putTag(FileHeader::Tag("baz", "666999"));
+
+ FastOS_File file;
+ ASSERT_TRUE(file.OpenWriteOnlyTruncate("fileheader.tmp"));
+ len = header.writeFile(file);
+ EXPECT_EQUAL(len, header.getSize());
+ file.Close();
+ }
+ {
+ FastOS_File file;
+ ASSERT_TRUE(file.OpenReadWrite("fileheader.tmp"));
+
+ FileHeader header;
+ EXPECT_EQUAL(len, header.readFile(file));
+ EXPECT_EQUAL(len, header.getSize());
+
+ EXPECT_TRUE(header.hasTag("foo"));
+ EXPECT_EQUAL(6.9, header.getTag("foo").asFloat());
+ EXPECT_TRUE(header.hasTag("bar"));
+ EXPECT_EQUAL(6699, header.getTag("bar").asInteger());
+ EXPECT_TRUE(header.hasTag("baz"));
+ EXPECT_EQUAL("666999", header.getTag("baz").asString());
+
+ header.putTag(FileHeader::Tag("foo", 9.6));
+ header.putTag(FileHeader::Tag("bar", 9966));
+ header.putTag(FileHeader::Tag("baz", "999666"));
+ EXPECT_EQUAL(len, header.getSize());
+ EXPECT_EQUAL(len, header.rewriteFile(file));
+
+ file.Close();
+ }
+ {
+ FileHeader header;
+
+ FastOS_File file;
+ ASSERT_TRUE(file.OpenReadOnly("fileheader.tmp"));
+ EXPECT_EQUAL(len, header.readFile(file));
+ EXPECT_EQUAL(len, header.getSize());
+ file.Close();
+ file.Delete();
+
+ EXPECT_TRUE(header.hasTag("foo"));
+ EXPECT_EQUAL(9.6, header.getTag("foo").asFloat());
+ EXPECT_TRUE(header.hasTag("bar"));
+ EXPECT_EQUAL(9966, header.getTag("bar").asInteger());
+ EXPECT_TRUE(header.hasTag("baz"));
+ EXPECT_EQUAL("999666", header.getTag("baz").asString());
+ }
+}
+
+void
+Test::testFileAlign()
+{
+ for (uint32_t alignTo = 1; alignTo < 16; ++alignTo) {
+ FileHeader header(alignTo);
+ header.putTag(FileHeader::Tag("foo", "bar"));
+ EXPECT_EQUAL(0u, header.getSize() % alignTo);
+ }
+}
+
+void
+Test::testFileSize()
+{
+ for (uint32_t minSize = 0; minSize < 512; ++minSize) {
+ FileHeader header(1u, minSize);
+ header.putTag(FileHeader::Tag("foo", "bar"));
+ EXPECT_TRUE(header.getSize() >= minSize);
+ }
+}
+
+void
+Test::testReadErrors()
+{
+ {
+ DataBuffer buf;
+ EXPECT_TRUE(testReadError(buf, "Failed to read header info."));
+ }
+ {
+ DataBuffer buf;
+ buf.writeInt32(0xDEADBEAF);
+ buf.writeInt32(8);
+ EXPECT_TRUE(testReadError(buf, "Failed to verify magic bits."));
+ }
+ {
+ DataBuffer buf;
+ buf.writeInt32(GenericHeader::MAGIC);
+ buf.writeInt32(8);
+ EXPECT_TRUE(testReadError(buf, "Failed to verify header size."));
+ }
+ {
+ DataBuffer buf;
+ buf.writeInt32(GenericHeader::MAGIC);
+ buf.writeInt32(16);
+ buf.writeInt32(-1);
+ buf.writeInt32(0);
+ EXPECT_TRUE(testReadError(buf, "Failed to verify header version."));
+ }
+ {
+ DataBuffer buf;
+ buf.writeInt32(GenericHeader::MAGIC);
+ buf.writeInt32(21);
+ buf.writeInt32(GenericHeader::VERSION);
+ buf.writeInt32(1);
+ buf.writeBytes("foo", 3);
+ buf.writeInt8(0);
+ buf.writeInt8((uint8_t)GenericHeader::Tag::TYPE_EMPTY);
+ EXPECT_TRUE(testReadError(buf, "Can not deserialize empty tag."));
+ }
+}
+
+bool
+Test::testReadError(DataBuffer &buf, const std::string &expected)
+{
+ GenericHeader header;
+ header.putTag(GenericHeader::Tag("foo", "bar"));
+ try {
+ GenericHeader::BufferReader reader(buf);
+ header.read(reader);
+ EXPECT_TRUE(false);
+ return false;
+ } catch (IllegalHeaderException &e) {
+ if (!EXPECT_EQUAL(expected, e.getMessage())) {
+ return false;
+ }
+ }
+ if (!EXPECT_EQUAL(1u, header.getNumTags())) {
+ return false;
+ }
+ if (!EXPECT_EQUAL("bar", header.getTag("foo").asString())) {
+ return false;
+ }
+ return true;
+}
+
+void
+Test::testWriteErrors()
+{
+ GenericHeader header;
+ header.putTag(GenericHeader::Tag("foo", 69));
+
+ DataBuffer buf;
+ buf.ensureFree(4);
+ buf.moveFreeToData(buf.getFreeLen() - 4);
+ EXPECT_TRUE(header.getSize() > buf.getFreeLen());
+ try {
+ GenericHeader::BufferWriter writer(buf);
+ header.write(writer);
+ EXPECT_TRUE(false);
+ } catch (IllegalHeaderException &e) {
+ EXPECT_EQUAL("Failed to write header.", e.getMessage());
+ }
+
+ EXPECT_TRUE(header.hasTag("foo"));
+ EXPECT_EQUAL(69, header.getTag("foo").asInteger());
+}
+
+void
+Test::testRewriteErrors()
+{
+ FileHeader header;
+ header.putTag(FileHeader::Tag("foo", "bar"));
+ uint32_t len = header.getSize();
+
+ FastOS_File file;
+ ASSERT_TRUE(file.OpenWriteOnlyTruncate("fileheader.tmp"));
+ EXPECT_EQUAL(len, header.writeFile(file));
+ file.Close();
+
+ ASSERT_TRUE(file.OpenReadWrite("fileheader.tmp"));
+ header.putTag(FileHeader::Tag("baz", "cox"));
+ EXPECT_TRUE(len != header.getSize());
+ try {
+ header.rewriteFile(file);
+ EXPECT_TRUE(false);
+ } catch (IllegalHeaderException &e) {
+ EXPECT_EQUAL("Failed to rewrite resized header.", e.getMessage());
+ }
+ file.Close();
+}
+
+void
+Test::testLayout()
+{
+ FastOS_File file;
+ ASSERT_TRUE(file.OpenReadOnly("fileheader.dat"));
+
+ FileHeader header;
+ uint32_t len = header.readFile(file);
+ EXPECT_EQUAL(len, header.getSize());
+ file.Close();
+
+ EXPECT_TRUE(header.hasTag("foo"));
+ EXPECT_EQUAL(6.9, header.getTag("foo").asFloat());
+ EXPECT_TRUE(header.hasTag("bar"));
+ EXPECT_EQUAL(6699, header.getTag("bar").asInteger());
+ EXPECT_TRUE(header.hasTag("baz"));
+ EXPECT_EQUAL("666999", header.getTag("baz").asString());
+}
+
+
+void
+Test::testReadSize(bool mapped)
+{
+ DataBuffer buf;
+ buf.writeInt32(GenericHeader::MAGIC);
+ buf.writeInt32(21);
+ buf.writeInt32(GenericHeader::VERSION);
+ buf.writeInt32(1);
+ uint32_t headerLen = 0u;
+ if (mapped) {
+ GenericHeader::MMapReader reader(buf.getData(), buf.getDataLen());
+ headerLen = FileHeader::readSize(reader);
+ } else {
+ GenericHeader::BufferReader reader(buf);
+ headerLen = FileHeader::readSize(reader);
+ }
+ EXPECT_EQUAL(21u, headerLen);
+}
+
+
+void
+Test::testReadSizeErrors(bool mapped)
+{
+ {
+ DataBuffer buf;
+ EXPECT_TRUE(testReadSizeError(buf, "Failed to read header info.",
+ mapped));
+ }
+ {
+ DataBuffer buf;
+ buf.writeInt32(0xDEADBEAF);
+ buf.writeInt32(8);
+ buf.writeInt32(0);
+ buf.writeInt32(0);
+ EXPECT_TRUE(testReadSizeError(buf, "Failed to verify magic bits.",
+ mapped));
+ }
+ {
+ DataBuffer buf;
+ buf.writeInt32(GenericHeader::MAGIC);
+ buf.writeInt32(8);
+ buf.writeInt32(GenericHeader::VERSION);
+ buf.writeInt32(0);
+ EXPECT_TRUE(testReadSizeError(buf, "Failed to verify header size.",
+ mapped));
+ }
+ {
+ DataBuffer buf;
+ buf.writeInt32(GenericHeader::MAGIC);
+ buf.writeInt32(16);
+ buf.writeInt32(-1);
+ buf.writeInt32(0);
+ EXPECT_TRUE(testReadSizeError(buf,
+ "Failed to verify header version.",
+ mapped));
+ }
+}
+
+
+bool
+Test::testReadSizeError(DataBuffer &buf, const std::string &expected,
+ bool mapped)
+{
+ uint32_t headerLen = 0u;
+ try {
+ if (mapped) {
+ GenericHeader::MMapReader reader(buf.getData(), buf.getDataLen());
+ headerLen = FileHeader::readSize(reader);
+ } else {
+ GenericHeader::BufferReader reader(buf);
+ headerLen = FileHeader::readSize(reader);
+ }
+ EXPECT_TRUE(false);
+ return false;
+ } catch (IllegalHeaderException &e) {
+ if (!EXPECT_EQUAL(expected, e.getMessage())) {
+ return false;
+ }
+ }
+ EXPECT_EQUAL(headerLen, 0u);
+ return true;
+}
+
diff --git a/staging_vespalib/src/tests/floatingpointtype/.gitignore b/staging_vespalib/src/tests/floatingpointtype/.gitignore
new file mode 100644
index 00000000000..f99dd0fd707
--- /dev/null
+++ b/staging_vespalib/src/tests/floatingpointtype/.gitignore
@@ -0,0 +1,4 @@
+.depend
+Makefile
+floatingpointtype_test
+staging_vespalib_floatingpointtype_test_app
diff --git a/staging_vespalib/src/tests/floatingpointtype/CMakeLists.txt b/staging_vespalib/src/tests/floatingpointtype/CMakeLists.txt
new file mode 100644
index 00000000000..88c73073ed4
--- /dev/null
+++ b/staging_vespalib/src/tests/floatingpointtype/CMakeLists.txt
@@ -0,0 +1,8 @@
+# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(staging_vespalib_floatingpointtype_test_app
+ SOURCES
+ floatingpointtypetest.cpp
+ DEPENDS
+ staging_vespalib
+)
+vespa_add_test(NAME staging_vespalib_floatingpointtype_test_app COMMAND staging_vespalib_floatingpointtype_test_app)
diff --git a/staging_vespalib/src/tests/floatingpointtype/DESC b/staging_vespalib/src/tests/floatingpointtype/DESC
new file mode 100644
index 00000000000..4bdf790ff44
--- /dev/null
+++ b/staging_vespalib/src/tests/floatingpointtype/DESC
@@ -0,0 +1 @@
+Floating point wrapper test.
diff --git a/staging_vespalib/src/tests/floatingpointtype/FILES b/staging_vespalib/src/tests/floatingpointtype/FILES
new file mode 100644
index 00000000000..dd496cb1e12
--- /dev/null
+++ b/staging_vespalib/src/tests/floatingpointtype/FILES
@@ -0,0 +1 @@
+floatingpointtypetest.cpp
diff --git a/staging_vespalib/src/tests/floatingpointtype/floatingpointtypetest.cpp b/staging_vespalib/src/tests/floatingpointtype/floatingpointtypetest.cpp
new file mode 100644
index 00000000000..41eed2f7dc9
--- /dev/null
+++ b/staging_vespalib/src/tests/floatingpointtype/floatingpointtypetest.cpp
@@ -0,0 +1,75 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+ // Include first to make sure it includes all it need.
+#include <vespa/fastos/fastos.h>
+#include <vespa/vespalib/objects/floatingpointtype.h>
+
+#include <vespa/vespalib/testkit/testapp.h>
+
+class Test : public vespalib::TestApp
+{
+public:
+ void testFloatingPoint();
+ int Main();
+};
+
+void
+Test::testFloatingPoint()
+{
+ vespalib::Double d1(1.0);
+ vespalib::Double d2(1.000000000000001);
+ vespalib::Double d3(-1.00000000000001);
+ vespalib::Double d4(4.0);
+
+ EXPECT_TRUE(d1.getValue() != d2.getValue());
+
+ EXPECT_EQUAL(d1, d2);
+ EXPECT_EQUAL(d2, d1);
+
+ EXPECT_NOT_EQUAL(d1, d3);
+ EXPECT_NOT_EQUAL(d1, d4);
+
+ EXPECT_TRUE(d1 - d2 == 0);
+ EXPECT_TRUE(d2 - d1 == 0);
+
+ EXPECT_TRUE(d1 - 1 == 0);
+ EXPECT_TRUE(d1 + 1 != 0);
+
+ EXPECT_TRUE(d2 * d4 == 4.0);
+ EXPECT_TRUE(d2 / d4 == 0.25);
+
+ EXPECT_TRUE(d1 >= 1);
+ EXPECT_TRUE(d1 <= 1);
+ EXPECT_TRUE(!(d1 < 1));
+ EXPECT_TRUE(!(d1 > 1));
+
+ EXPECT_EQUAL(d2 * 4, d4);
+
+ EXPECT_EQUAL(++d4, 5.0);
+ EXPECT_EQUAL(d4++, 5.0);
+ EXPECT_EQUAL(d4, 6.0);
+
+ d4 /= 3;
+ EXPECT_EQUAL(d4, 2.00000000001);
+ d4 *= 2;
+ EXPECT_EQUAL(d4, 4.000000000001);
+
+ EXPECT_EQUAL(--d4, 3.0);
+ EXPECT_EQUAL(d4--, 3.0);
+ EXPECT_EQUAL(d4, 2.0);
+ d4 /= 0.50000000001;
+
+ EXPECT_EQUAL(d4, 4.0);
+
+ EXPECT_TRUE(!(d3 + 1 > 0));
+ EXPECT_TRUE(!(d3 + 1 < 0));
+}
+
+int
+Test::Main()
+{
+ TEST_INIT("floatingpointtype_test");
+ testFloatingPoint();
+ TEST_DONE();
+}
+
+TEST_APPHOOK(Test)
diff --git a/staging_vespalib/src/tests/growablebytebuffer/.gitignore b/staging_vespalib/src/tests/growablebytebuffer/.gitignore
new file mode 100644
index 00000000000..8df98f682b8
--- /dev/null
+++ b/staging_vespalib/src/tests/growablebytebuffer/.gitignore
@@ -0,0 +1,4 @@
+.depend
+Makefile
+growablebytebuffer_test
+staging_vespalib_growablebytebuffer_test_app
diff --git a/staging_vespalib/src/tests/growablebytebuffer/CMakeLists.txt b/staging_vespalib/src/tests/growablebytebuffer/CMakeLists.txt
new file mode 100644
index 00000000000..cd19f0f1256
--- /dev/null
+++ b/staging_vespalib/src/tests/growablebytebuffer/CMakeLists.txt
@@ -0,0 +1,8 @@
+# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(staging_vespalib_growablebytebuffer_test_app
+ SOURCES
+ growablebytebuffer_test.cpp
+ DEPENDS
+ staging_vespalib
+)
+vespa_add_test(NAME staging_vespalib_growablebytebuffer_test_app COMMAND staging_vespalib_growablebytebuffer_test_app)
diff --git a/staging_vespalib/src/tests/growablebytebuffer/growablebytebuffer_test.cpp b/staging_vespalib/src/tests/growablebytebuffer/growablebytebuffer_test.cpp
new file mode 100644
index 00000000000..121f8d2e011
--- /dev/null
+++ b/staging_vespalib/src/tests/growablebytebuffer/growablebytebuffer_test.cpp
@@ -0,0 +1,39 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/fastos/fastos.h>
+#include <vespa/log/log.h>
+LOG_SETUP("guard_test");
+#include <vespa/vespalib/testkit/testapp.h>
+#include <vespa/vespalib/util/growablebytebuffer.h>
+
+using namespace vespalib;
+
+class Test : public TestApp
+{
+public:
+ void testGrowing();
+ int Main();
+};
+
+void
+Test::testGrowing()
+{
+ GrowableByteBuffer buf(10);
+
+ buf.putInt(3);
+ buf.putInt(7);
+ buf.putLong(1234);
+ buf.putDouble(1234);
+ buf.putString("hei der");
+
+ EXPECT_EQUAL(35u, buf.position());
+}
+
+int
+Test::Main()
+{
+ TEST_INIT("guard_test");
+ testGrowing();
+ TEST_DONE();
+}
+
+TEST_APPHOOK(Test)
diff --git a/staging_vespalib/src/tests/health_server/.gitignore b/staging_vespalib/src/tests/health_server/.gitignore
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/staging_vespalib/src/tests/health_server/.gitignore
diff --git a/staging_vespalib/src/tests/json/.gitignore b/staging_vespalib/src/tests/json/.gitignore
new file mode 100644
index 00000000000..963bafed038
--- /dev/null
+++ b/staging_vespalib/src/tests/json/.gitignore
@@ -0,0 +1 @@
+staging_vespalib_json_test_app
diff --git a/staging_vespalib/src/tests/json/CMakeLists.txt b/staging_vespalib/src/tests/json/CMakeLists.txt
new file mode 100644
index 00000000000..284e858e033
--- /dev/null
+++ b/staging_vespalib/src/tests/json/CMakeLists.txt
@@ -0,0 +1,8 @@
+# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(staging_vespalib_json_test_app
+ SOURCES
+ json.cpp
+ DEPENDS
+ staging_vespalib
+)
+vespa_add_test(NAME staging_vespalib_json_test_app COMMAND staging_vespalib_json_test_app boost)
diff --git a/staging_vespalib/src/tests/json/json.cpp b/staging_vespalib/src/tests/json/json.cpp
new file mode 100644
index 00000000000..16d27643983
--- /dev/null
+++ b/staging_vespalib/src/tests/json/json.cpp
@@ -0,0 +1,473 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/fastos/fastos.h>
+#include <vespa/log/log.h>
+LOG_SETUP("json_test");
+#include <vespa/vespalib/testkit/testapp.h>
+
+#include <vespa/vespalib/util/exception.h>
+#include <vespa/vespalib/util/jsonstream.h>
+#include <cmath>
+
+using namespace vespalib;
+
+class JSONTest : public vespalib::TestApp
+{
+private:
+ void testJSONWriterValues();
+ void testJSONWriterObject();
+ void testJSONWriterArray();
+ void testJSONWriterComplex();
+ void testJsonStream();
+ void testJsonStreamErrors();
+ void testJsonStreamStateReporting();
+
+public:
+ int Main();
+};
+
+void
+JSONTest::testJSONWriterValues()
+{
+ JSONStringer js;
+
+ { // bool
+ js.appendBool(true);
+ EXPECT_EQUAL(js.toString(), "true");
+ js.clear().appendBool(false);
+ EXPECT_EQUAL(js.toString(), "false");
+ }
+ { // double
+ js.clear().appendDouble(1234.5678);
+ EXPECT_EQUAL(js.toString(), "1234.5678");
+ js.clear().appendDouble(-1234.5678);
+ EXPECT_EQUAL(js.toString(), "-1234.5678");
+ js.clear().appendDouble(0.0);
+ EXPECT_EQUAL(js.toString(), "0.0");
+ js.clear().appendDouble(0.00000000012345678912356789123456789);
+ EXPECT_EQUAL(js.toString(), "1.234567891235679e-10");
+ js.clear().appendDouble(std::numeric_limits<double>::max());
+ EXPECT_EQUAL(js.toString(), "1.797693134862316e+308");
+ js.clear().appendDouble(std::numeric_limits<double>::min());
+ EXPECT_EQUAL(js.toString(), "2.225073858507201e-308");
+ js.clear().appendDouble(1.0 * (uint64_t(1) << 53));
+ EXPECT_EQUAL(js.toString(), "9007199254740992.0");
+ js.clear().appendDouble(1000);
+ EXPECT_EQUAL(js.toString(), "1000.0");
+ }
+ { // float
+ js.clear().appendFloat(1234.5678f);
+ EXPECT_EQUAL(js.toString(), "1234.5677");
+ js.clear().appendFloat(-1234.5678f);
+ EXPECT_EQUAL(js.toString(), "-1234.5677");
+ js.clear().appendFloat(0.0f);
+ EXPECT_EQUAL(js.toString(), "0.0");
+ js.clear().appendFloat(0.00000000012345678912356789123456789f);
+ EXPECT_EQUAL(js.toString(), "1.2345679e-10");
+ js.clear().appendFloat(std::numeric_limits<float>::max());
+ EXPECT_EQUAL(js.toString(), "3.4028235e+38");
+ js.clear().appendFloat(std::numeric_limits<float>::min());
+ EXPECT_EQUAL(js.toString(), "1.1754944e-38");
+ js.clear().appendFloat(1.0 * (uint64_t(1) << 24));
+ EXPECT_EQUAL(js.toString(), "16777216.0");
+ js.clear().appendFloat(1000);
+ EXPECT_EQUAL(js.toString(), "1000.0");
+ }
+ { // long
+ js.clear().appendInt64(4294967296ll);
+ EXPECT_EQUAL(js.toString(), "4294967296");
+ js.clear().appendInt64(-4294967296ll);
+ EXPECT_EQUAL(js.toString(), "-4294967296");
+ }
+ { // string
+ js.clear().appendString("string");
+ EXPECT_EQUAL(js.toString(), "\"string\"");
+ }
+ { // NULL
+ js.clear().appendNull();
+ EXPECT_EQUAL(js.toString(), "null");
+ }
+ { // quote
+ js.clear().appendString("x\"y");
+ EXPECT_EQUAL(js.toString(), "\"x\\\"y\"");
+ js.clear().appendString("x\\y");
+ EXPECT_EQUAL(js.toString(), "\"x\\\\y\"");
+ js.clear().appendString("x/y");
+ EXPECT_EQUAL(js.toString(), "\"x/y\"");
+ js.clear().appendString("x\by");
+ EXPECT_EQUAL(js.toString(), "\"x\\by\"");
+ js.clear().appendString("x\fy");
+ EXPECT_EQUAL(js.toString(), "\"x\\fy\"");
+ js.clear().appendString("x\ny");
+ EXPECT_EQUAL(js.toString(), "\"x\\ny\"");
+ js.clear().appendString("x\ry");
+ EXPECT_EQUAL(js.toString(), "\"x\\ry\"");
+ js.clear().appendString("x\ty");
+ EXPECT_EQUAL(js.toString(), "\"x\\ty\"");
+ }
+}
+
+void
+JSONTest::testJSONWriterObject()
+{
+ JSONStringer js;
+
+ { // single pair
+ js.beginObject().appendKey("k1").appendInt64(1l).endObject();
+ EXPECT_EQUAL(js.toString(), "{\"k1\":1}");
+ }
+ { // multiple pairs
+ js.clear().beginObject().appendKey("k1").appendInt64(1l).appendKey("k2").appendInt64(2l).endObject();
+ EXPECT_EQUAL(js.toString(), "{\"k1\":1,\"k2\":2}");
+ }
+ { // object in object
+ js.clear().beginObject().appendKey("k1").beginObject().appendKey("k1.1").appendInt64(11l).endObject().endObject();
+ EXPECT_EQUAL(js.toString(), "{\"k1\":{\"k1.1\":11}}");
+ }
+ { // object in object (multiple pairs)
+ js.clear().beginObject().
+ appendKey("k1").
+ beginObject().
+ appendKey("k1.1").appendInt64(11l).
+ appendKey("k1.2").appendInt64(12l).
+ endObject().
+ appendKey("k2").
+ beginObject().
+ appendKey("k2.1").appendInt64(21l).
+ appendKey("k2.2").appendInt64(22l).
+ endObject().
+ endObject();
+ EXPECT_EQUAL(js.toString(), "{\"k1\":{\"k1.1\":11,\"k1.2\":12},\"k2\":{\"k2.1\":21,\"k2.2\":22}}");
+ }
+ { // array in object
+ js.clear().beginObject().appendKey("k1").
+ beginArray().appendInt64(1l).appendInt64(2l).endArray().endObject();
+ EXPECT_EQUAL(js.toString(), "{\"k1\":[1,2]}");
+ }
+ { // array in object (multiple pairs)
+ js.clear().beginObject().
+ appendKey("k1").beginArray().appendInt64(1l).appendInt64(2l).endArray().
+ appendKey("k2").beginArray().appendInt64(3l).appendInt64(4l).endArray().
+ endObject();
+ EXPECT_EQUAL(js.toString(), "{\"k1\":[1,2],\"k2\":[3,4]}");
+ }
+}
+
+
+void
+JSONTest::testJSONWriterArray()
+{
+ JSONStringer js;
+
+ { // single element
+ js.beginArray().appendInt64(1l).endArray();
+ EXPECT_EQUAL(js.toString(), "[1]");
+ }
+ { // multiple elements
+ js.clear().beginArray().appendInt64(1l).appendInt64(2l).endArray();
+ EXPECT_EQUAL(js.toString(), "[1,2]");
+ }
+ { // array in array
+ js.clear().beginArray().beginArray().appendInt64(1l).endArray().endArray();
+ EXPECT_EQUAL(js.toString(), "[[1]]");
+ }
+ { // array in array (multiple elements)
+ js.clear().beginArray().
+ beginArray().appendInt64(1l).appendInt64(2l).endArray().
+ beginArray().appendInt64(3l).appendInt64(4l).endArray().
+ endArray();
+ EXPECT_EQUAL(js.toString(), "[[1,2],[3,4]]");
+ }
+ { // object in array
+ js.clear().beginArray().
+ beginObject().appendKey("k1").appendInt64(1l).endObject().
+ endArray();
+ EXPECT_EQUAL(js.toString(), "[{\"k1\":1}]");
+ }
+ { // object in array (multiple elements)
+ js.clear().beginArray().
+ beginObject().appendKey("k1").appendInt64(1l).appendKey("k2").appendInt64(2l).endObject().
+ beginObject().appendKey("k3").appendInt64(3l).appendKey("k4").appendInt64(4l).endObject().
+ endArray();
+ EXPECT_EQUAL(js.toString(), "[{\"k1\":1,\"k2\":2},{\"k3\":3,\"k4\":4}]");
+ }
+}
+
+
+void
+JSONTest::testJSONWriterComplex()
+{
+ JSONStringer js;
+
+ js.beginObject();
+ { // object
+ js.appendKey("k1");
+ js.beginObject();
+ {
+ js.appendKey("k1.1");
+ js.appendInt64(1l);
+ }
+ {
+ js.appendKey("k1.2");
+ js.beginArray();
+ js.appendInt64(2l);
+ js.appendInt64(3l);
+ js.endArray();
+ }
+ js.endObject();
+ }
+ { // object of object
+ js.appendKey("k2");
+ js.beginObject();
+ {
+ js.appendKey("k2.1");
+ js.beginObject();
+ {
+ js.appendKey("k2.1.1");
+ js.appendInt64(4l);
+ }
+ {
+ js.appendKey("k2.1.2");
+ js.beginArray();
+ js.appendInt64(5l);
+ js.appendInt64(6l);
+ js.endArray();
+ }
+ js.endObject();
+ }
+ js.endObject();
+ }
+ { // array of object
+ js.appendKey("k3");
+ js.beginArray();
+ {
+ js.beginObject();
+ {
+ js.appendKey("k3.1");
+ js.appendInt64(7l);
+ }
+ {
+ js.appendKey("k3.2");
+ js.beginArray();
+ js.appendInt64(8l);
+ js.appendInt64(9l);
+ js.endArray();
+ }
+ js.endObject();
+ }
+ {
+ js.beginObject();
+ {
+ js.appendKey("k3.1");
+ js.appendInt64(10l);
+ }
+ {
+ js.appendKey("k3.2");
+ js.beginArray();
+ js.appendInt64(11l);
+ js.appendInt64(12l);
+ js.endArray();
+ }
+ js.endObject();
+ }
+ js.endArray();
+ }
+ js.endObject();
+ EXPECT_EQUAL(js.toString(), "{\"k1\":{\"k1.1\":1,\"k1.2\":[2,3]},\"k2\":{\"k2.1\":{\"k2.1.1\":4,\"k2.1.2\":[5,6]}},\"k3\":[{\"k3.1\":7,\"k3.2\":[8,9]},{\"k3.1\":10,\"k3.2\":[11,12]}]}");
+}
+
+namespace {
+ struct Builder : public vespalib::JsonStreamTypes {
+ void build(JsonStream& s) {
+ s << Object() << "k1" << Object()
+ << "k1.1" << 1l
+ << "k1.2" << Array()
+ << 2l << 3l << End()
+ << End()
+ << "k2" << Object()
+ << "k2.1" << Object()
+ << "k2.1.1" << 4l
+ << "k2.1.2" << Array()
+ << 5l << 6l << End()
+ << End()
+ << End()
+ << "k3" << Array()
+ << Object()
+ << "k3.1" << 7l
+ << "k3.2" << Array()
+ << 8l << 9l << End()
+ << End()
+ << Object()
+ << "k3.1" << 10l
+ << "k3.2" << Array()
+ << 11l << 12l << End()
+ << End()
+ << End()
+ << End();
+ }
+ };
+}
+
+void
+JSONTest::testJsonStream()
+{
+ vespalib::asciistream as;
+ vespalib::JsonStream stream(as);
+ Builder b;
+ b.build(stream);
+ stream.finalize();
+ EXPECT_EQUAL(as.str(), "{\"k1\":{\"k1.1\":1,\"k1.2\":[2,3]},\"k2\":{\"k2.1\":{\"k2.1.1\":4,\"k2.1.2\":[5,6]}},\"k3\":[{\"k3.1\":7,\"k3.2\":[8,9]},{\"k3.1\":10,\"k3.2\":[11,12]}]}");
+}
+
+void
+JSONTest::testJsonStreamErrors()
+{
+ using namespace vespalib::jsonstream;
+ // Unsupported object keys
+ try{
+ vespalib::asciistream as;
+ vespalib::JsonStream stream(as);
+ stream << Object() << Object();
+ } catch (vespalib::JsonStreamException& e) {
+ EXPECT_EQUAL("Invalid state on call: An object value cannot be an object key ({}(ObjectExpectingKey))", e.getReason());
+ }
+ try{
+ vespalib::asciistream as;
+ vespalib::JsonStream stream(as);
+ stream << Object() << true;
+ } catch (vespalib::JsonStreamException& e) {
+ EXPECT_EQUAL("Invalid state on call: A bool value cannot be an object key ({}(ObjectExpectingKey))", e.getReason());
+ }
+ try{
+ vespalib::asciistream as;
+ vespalib::JsonStream stream(as);
+ stream << Object() << 13;
+ } catch (vespalib::JsonStreamException& e) {
+ EXPECT_EQUAL("Invalid state on call: An int64_t value cannot be an object key ({}(ObjectExpectingKey))", e.getReason());
+ }
+ try{
+ vespalib::asciistream as;
+ vespalib::JsonStream stream(as);
+ stream << Object() << uint64_t(13);
+ } catch (vespalib::JsonStreamException& e) {
+ EXPECT_EQUAL("Invalid state on call: A uint64_t value cannot be an object key ({}(ObjectExpectingKey))", e.getReason());
+ }
+ try{
+ vespalib::asciistream as;
+ vespalib::JsonStream stream(as);
+ stream << Object() << 0.5;
+ } catch (vespalib::JsonStreamException& e) {
+ EXPECT_EQUAL("Invalid state on call: A double value cannot be an object key ({}(ObjectExpectingKey))", e.getReason());
+ }
+ try{
+ vespalib::asciistream as;
+ vespalib::JsonStream stream(as);
+ stream << Object() << Array();
+ } catch (vespalib::JsonStreamException& e) {
+ EXPECT_EQUAL("Invalid state on call: An array value cannot be an object key ({}(ObjectExpectingKey))", e.getReason());
+ }
+ // Invalid points to add End()
+ try{
+ vespalib::asciistream as;
+ vespalib::JsonStream stream(as);
+ stream << Object() << "foo" << End();
+ } catch (vespalib::JsonStreamException& e) {
+ EXPECT_EQUAL("Invalid state on call: Object got key but not value. Cannot end it now ({foo}(ObjectExpectingValue))", e.getReason());
+ }
+ try{
+ vespalib::asciistream as;
+ vespalib::JsonStream stream(as);
+ stream << End();
+ } catch (vespalib::JsonStreamException& e) {
+ EXPECT_EQUAL("Invalid state on call: No tag to end. At root ((RootExpectingArrayOrObjectStart))", e.getReason());
+ }
+ // Adding to finalized stream
+ try{
+ vespalib::asciistream as;
+ vespalib::JsonStream stream(as);
+ stream << Object() << End() << "foo";
+ } catch (vespalib::JsonStreamException& e) {
+ EXPECT_EQUAL("Invalid state on call: Stream already finalized. Can't add a string value. (Finalized)", e.getReason());
+ }
+ try{
+ vespalib::asciistream as;
+ vespalib::JsonStream stream(as);
+ stream << Object() << End() << false;
+ } catch (vespalib::JsonStreamException& e) {
+ EXPECT_EQUAL("Invalid state on call: Stream already finalized. Can't add a bool value. (Finalized)", e.getReason());
+ }
+ try{
+ vespalib::asciistream as;
+ vespalib::JsonStream stream(as);
+ stream << Object() << End() << 13;
+ } catch (vespalib::JsonStreamException& e) {
+ EXPECT_EQUAL("Invalid state on call: Stream already finalized. Can't add an int64_t value. (Finalized)", e.getReason());
+ }
+ try{
+ vespalib::asciistream as;
+ vespalib::JsonStream stream(as);
+ stream << Object() << End() << uint64_t(13);
+ } catch (vespalib::JsonStreamException& e) {
+ EXPECT_EQUAL("Invalid state on call: Stream already finalized. Can't add a uint64_t value. (Finalized)", e.getReason());
+ }
+ try{
+ vespalib::asciistream as;
+ vespalib::JsonStream stream(as);
+ stream << Object() << End() << 0.2;
+ } catch (vespalib::JsonStreamException& e) {
+ EXPECT_EQUAL("Invalid state on call: Stream already finalized. Can't add a double value. (Finalized)", e.getReason());
+ }
+ try{
+ vespalib::asciistream as;
+ vespalib::JsonStream stream(as);
+ stream << Object() << End() << Object();
+ } catch (vespalib::JsonStreamException& e) {
+ EXPECT_EQUAL("Invalid state on call: Stream already finalized. Can't start a new object. (Finalized)", e.getReason());
+ }
+ try{
+ vespalib::asciistream as;
+ vespalib::JsonStream stream(as);
+ stream << Object() << End() << Array();
+ } catch (vespalib::JsonStreamException& e) {
+ EXPECT_EQUAL("Invalid state on call: Stream already finalized. Can't start a new array. (Finalized)", e.getReason());
+ }
+ try{
+ vespalib::asciistream as;
+ vespalib::JsonStream stream(as);
+ stream << Object() << End() << End();
+ } catch (vespalib::JsonStreamException& e) {
+ EXPECT_EQUAL("Invalid state on call: Stream already finalized. Can't end it. (Finalized)", e.getReason());
+ }
+}
+
+void
+JSONTest::testJsonStreamStateReporting()
+{
+ using namespace vespalib::jsonstream;
+ vespalib::asciistream as;
+ vespalib::JsonStream stream(as);
+ stream << Array() << 13
+ << "foo"
+ << Object() << "key" << "value" << End()
+ << false
+ << End();
+ EXPECT_EQUAL("Current: Finalized", stream.getJsonStreamState());
+}
+
+int
+JSONTest::Main()
+{
+ TEST_INIT("json_test");
+
+ testJSONWriterValues();
+ testJSONWriterObject();
+ testJSONWriterArray();
+ testJSONWriterComplex();
+ testJsonStream();
+ testJsonStreamErrors();
+ testJsonStreamStateReporting();
+
+ TEST_DONE();
+}
+
+TEST_APPHOOK(JSONTest);
+
diff --git a/staging_vespalib/src/tests/librarypool/.gitignore b/staging_vespalib/src/tests/librarypool/.gitignore
new file mode 100644
index 00000000000..1a1aea2fda0
--- /dev/null
+++ b/staging_vespalib/src/tests/librarypool/.gitignore
@@ -0,0 +1 @@
+staging_vespalib_librarypool_test_app
diff --git a/staging_vespalib/src/tests/librarypool/CMakeLists.txt b/staging_vespalib/src/tests/librarypool/CMakeLists.txt
new file mode 100644
index 00000000000..0ef8d03ccda
--- /dev/null
+++ b/staging_vespalib/src/tests/librarypool/CMakeLists.txt
@@ -0,0 +1,8 @@
+# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(staging_vespalib_librarypool_test_app
+ SOURCES
+ librarypool_test.cpp
+ DEPENDS
+ staging_vespalib
+)
+vespa_add_test(NAME staging_vespalib_librarypool_test_app COMMAND staging_vespalib_librarypool_test_app)
diff --git a/staging_vespalib/src/tests/librarypool/DESC b/staging_vespalib/src/tests/librarypool/DESC
new file mode 100644
index 00000000000..2330c52fae7
--- /dev/null
+++ b/staging_vespalib/src/tests/librarypool/DESC
@@ -0,0 +1 @@
+Library pool test. Take a look at librarypool_test.cpp for details.
diff --git a/staging_vespalib/src/tests/librarypool/FILES b/staging_vespalib/src/tests/librarypool/FILES
new file mode 100644
index 00000000000..c8bb90cf093
--- /dev/null
+++ b/staging_vespalib/src/tests/librarypool/FILES
@@ -0,0 +1 @@
+librarypool_test.cpp
diff --git a/staging_vespalib/src/tests/librarypool/librarypool_test.cpp b/staging_vespalib/src/tests/librarypool/librarypool_test.cpp
new file mode 100644
index 00000000000..5808d1c91e5
--- /dev/null
+++ b/staging_vespalib/src/tests/librarypool/librarypool_test.cpp
@@ -0,0 +1,41 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/fastos/fastos.h>
+#include <vespa/vespalib/testkit/testapp.h>
+#include <vespa/vespalib/util/librarypool.h>
+#include <vespa/vespalib/util/exceptions.h>
+#include <vespa/log/log.h>
+LOG_SETUP("librarypool_test");
+
+using namespace vespalib;
+
+class Test : public TestApp
+{
+public:
+ int Main();
+};
+
+int
+Test::Main()
+{
+ TEST_INIT("librarypool_test");
+ LibraryPool p;
+ ASSERT_TRUE(p.get("z") == NULL);
+ p.loadLibrary("z");
+ ASSERT_TRUE(p.get("z") != NULL);
+ ASSERT_TRUE(p.get("z")->GetSymbol("some_symbol_that_is_not_there") == NULL);
+ ASSERT_TRUE(p.get("z")->GetSymbol("compress") != NULL);
+ try {
+ p.loadLibrary("not_found");
+ ASSERT_TRUE(false);
+ } catch (const IllegalArgumentException & e) {
+ ASSERT_TRUE(p.get("not_found") == NULL);
+ }
+ {
+ const LibraryPool & c(p);
+ ASSERT_TRUE(c.get("z") != NULL);
+ ASSERT_TRUE(c.get("not_found") == NULL);
+ }
+ TEST_DONE();
+}
+
+TEST_APPHOOK(Test)
diff --git a/staging_vespalib/src/tests/memorydatastore/.gitignore b/staging_vespalib/src/tests/memorydatastore/.gitignore
new file mode 100644
index 00000000000..634cea1ae88
--- /dev/null
+++ b/staging_vespalib/src/tests/memorydatastore/.gitignore
@@ -0,0 +1 @@
+staging_vespalib_memorydatastore_test_app
diff --git a/staging_vespalib/src/tests/memorydatastore/CMakeLists.txt b/staging_vespalib/src/tests/memorydatastore/CMakeLists.txt
new file mode 100644
index 00000000000..386cf7d6865
--- /dev/null
+++ b/staging_vespalib/src/tests/memorydatastore/CMakeLists.txt
@@ -0,0 +1,8 @@
+# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(staging_vespalib_memorydatastore_test_app
+ SOURCES
+ memorydatastore.cpp
+ DEPENDS
+ staging_vespalib
+)
+vespa_add_test(NAME staging_vespalib_memorydatastore_test_app COMMAND staging_vespalib_memorydatastore_test_app)
diff --git a/staging_vespalib/src/tests/memorydatastore/memorydatastore.cpp b/staging_vespalib/src/tests/memorydatastore/memorydatastore.cpp
new file mode 100644
index 00000000000..2bb5a272783
--- /dev/null
+++ b/staging_vespalib/src/tests/memorydatastore/memorydatastore.cpp
@@ -0,0 +1,75 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/fastos/fastos.h>
+#include <vespa/log/log.h>
+LOG_SETUP("data_test");
+#include <vespa/vespalib/testkit/testapp.h>
+#include <vespa/vespalib/data/memorydatastore.h>
+#include <vespa/vespalib/stllike/asciistream.h>
+#include <vector>
+
+using namespace vespalib;
+
+class MemoryDataStoreTest : public vespalib::TestApp
+{
+private:
+ void testMemoryDataStore();
+ void testVariableSizeVector();
+public:
+ int Main();
+};
+
+void
+MemoryDataStoreTest::testMemoryDataStore()
+{
+ MemoryDataStore s(256);
+ std::vector<MemoryDataStore::Reference> v;
+ v.push_back(s.push_back("mumbo", 5));
+ for (size_t i(0); i < 50; i++) {
+ v.push_back(s.push_back("mumbo", 5));
+ EXPECT_EQUAL(static_cast<const char *>(v[i].data()) + 5, v[i+1].data());
+ }
+ v.push_back(s.push_back("mumbo", 5));
+ EXPECT_EQUAL(52ul, v.size());
+ EXPECT_NOT_EQUAL(static_cast<const char *>(v[50].data()) + 5, v[51].data());
+ for (size_t i(0); i < v.size(); i++) {
+ EXPECT_EQUAL(0, memcmp("mumbo", v[i].data(), 5));
+ }
+}
+
+void
+MemoryDataStoreTest::testVariableSizeVector()
+{
+ VariableSizeVector v(256);
+ for (size_t i(0); i < 10000; i++) {
+ asciistream os;
+ os << i;
+ v.push_back(os.str().c_str(), os.str().size());
+ }
+ for (size_t i(0); i < v.size(); i++) {
+ asciistream os;
+ os << i;
+ EXPECT_EQUAL(os.str().size(), v[i].size());
+ EXPECT_EQUAL(0, memcmp(os.str().c_str(), v[i].data(), os.str().size()));
+ }
+ size_t i(0);
+ for (auto it(v.begin()), mt(v.end()); it != mt; it++, i++) {
+ asciistream os;
+ os << i;
+ EXPECT_EQUAL(os.str().size(), it->size());
+ EXPECT_EQUAL(0, memcmp(os.str().c_str(), (*it).data(), os.str().size()));
+ }
+
+}
+
+int
+MemoryDataStoreTest::Main()
+{
+ TEST_INIT("data_test");
+ testMemoryDataStore();
+ testVariableSizeVector();
+
+ TEST_DONE();
+}
+
+TEST_APPHOOK(MemoryDataStoreTest);
+
diff --git a/staging_vespalib/src/tests/objectdump/.gitignore b/staging_vespalib/src/tests/objectdump/.gitignore
new file mode 100644
index 00000000000..d243567aea6
--- /dev/null
+++ b/staging_vespalib/src/tests/objectdump/.gitignore
@@ -0,0 +1,4 @@
+.depend
+Makefile
+objectdump_test
+staging_vespalib_objectdump_test_app
diff --git a/staging_vespalib/src/tests/objectdump/CMakeLists.txt b/staging_vespalib/src/tests/objectdump/CMakeLists.txt
new file mode 100644
index 00000000000..e8b5f76b934
--- /dev/null
+++ b/staging_vespalib/src/tests/objectdump/CMakeLists.txt
@@ -0,0 +1,8 @@
+# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(staging_vespalib_objectdump_test_app
+ SOURCES
+ objectdump.cpp
+ DEPENDS
+ staging_vespalib
+)
+vespa_add_test(NAME staging_vespalib_objectdump_test_app COMMAND staging_vespalib_objectdump_test_app)
diff --git a/staging_vespalib/src/tests/objectdump/DESC b/staging_vespalib/src/tests/objectdump/DESC
new file mode 100644
index 00000000000..747ea8bb015
--- /dev/null
+++ b/staging_vespalib/src/tests/objectdump/DESC
@@ -0,0 +1 @@
+Test dumping of identifiable objects to human-readable form.
diff --git a/staging_vespalib/src/tests/objectdump/FILES b/staging_vespalib/src/tests/objectdump/FILES
new file mode 100644
index 00000000000..f44f8ce9c4c
--- /dev/null
+++ b/staging_vespalib/src/tests/objectdump/FILES
@@ -0,0 +1 @@
+objectdump.cpp
diff --git a/staging_vespalib/src/tests/objectdump/objectdump.cpp b/staging_vespalib/src/tests/objectdump/objectdump.cpp
new file mode 100644
index 00000000000..3427bbbff3b
--- /dev/null
+++ b/staging_vespalib/src/tests/objectdump/objectdump.cpp
@@ -0,0 +1,107 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/fastos/fastos.h>
+#include <vespa/log/log.h>
+LOG_SETUP("objectdump_test");
+#include <vespa/vespalib/testkit/testapp.h>
+#include <vespa/vespalib/objects/identifiable.h>
+#include <vespa/vespalib/objects/visit.h>
+
+using namespace vespalib;
+
+#define CID_Base 10000000
+#define CID_Foo 10000001
+#define CID_Bar 10000002
+#define CID_Baz 10000003
+
+struct Base : public vespalib::Identifiable
+{
+ DECLARE_IDENTIFIABLE(Base);
+ virtual Base *clone() const { return new Base(*this); }
+};
+IMPLEMENT_IDENTIFIABLE(Base, vespalib::Identifiable);
+
+struct Baz : public Base
+{
+ DECLARE_IDENTIFIABLE(Baz);
+ virtual Baz *clone() const { return new Baz(*this); }
+};
+IMPLEMENT_IDENTIFIABLE(Baz, Base);
+
+struct Bar : public Base
+{
+ DECLARE_IDENTIFIABLE(Bar);
+ bool _bool;
+ int8_t _int8;
+ uint8_t _uint8;
+ int16_t _int16;
+ uint16_t _uint16;
+ int32_t _int32;
+ uint32_t _uint32;
+ int64_t _int64;
+ uint64_t _uint64;
+ float _float;
+ double _double;
+ std::string _string;
+ Bar() : _bool(true), _int8(-1), _uint8(1), _int16(-2), _uint16(2),
+ _int32(-4), _uint32(4), _int64(-8), _uint64(8),
+ _float(2.5), _double(2.75), _string("bla bla") {}
+
+ virtual Bar *clone() const { return new Bar(*this); }
+
+ virtual void visitMembers(ObjectVisitor &v) const {
+ visit(v, "_bool", _bool);
+ visit(v, "_int8", _int8);
+ visit(v, "_uint8", _uint8);
+ visit(v, "_int16", _int16);
+ visit(v, "_uint16", _uint16);
+ visit(v, "_int32", _int32);
+ visit(v, "_uint32", _uint32);
+ visit(v, "_int64", _int64);
+ visit(v, "_uint64", _uint64);
+ visit(v, "_float", _float);
+ visit(v, "_double", _double);
+ visit(v, "_string", _string);
+ visit(v, "info", "a dummy string");
+ visit(v, "(const char*)0", (const char*)0);
+ }
+};
+IMPLEMENT_IDENTIFIABLE(Bar, Base);
+
+struct Foo : public Base
+{
+ DECLARE_IDENTIFIABLE(Foo);
+ Bar _objMember;
+ Baz _objMember2;
+ Baz *_objPtr;
+ std::vector<Bar> _list;
+ std::vector<IdentifiablePtr<Base> > _list2;
+
+ Foo() : _objMember(), _objMember2(), _objPtr(0), _list(), _list2() {
+ _list.push_back(Bar());
+ _list.push_back(Bar());
+ _list.push_back(Bar());
+ _list2.push_back(Bar());
+ _list2.push_back(Baz());
+ }
+ virtual Foo *clone() const { return new Foo(*this); }
+
+ virtual void visitMembers(ObjectVisitor &v) const {
+ visit(v, "_objMember", _objMember);
+ visit(v, "_objMember2", _objMember2);
+ visit(v, "_objPtr", _objPtr);
+ visit(v, "_list", _list);
+ visit(v, "_list2", _list2);
+ }
+};
+IMPLEMENT_IDENTIFIABLE(Foo, Base);
+
+TEST_SETUP(Test);
+
+int
+Test::Main()
+{
+ TEST_INIT("objectdump_test");
+ Foo foo;
+ fprintf(stderr, "%s", foo.asString().c_str());
+ TEST_DONE();
+}
diff --git a/staging_vespalib/src/tests/objects/.gitignore b/staging_vespalib/src/tests/objects/.gitignore
new file mode 100644
index 00000000000..2b10aff029c
--- /dev/null
+++ b/staging_vespalib/src/tests/objects/.gitignore
@@ -0,0 +1,5 @@
+.depend
+Makefile
+asciistream_test
+identifiable_test
+staging_vespalib_identifiable_test_app
diff --git a/staging_vespalib/src/tests/objects/CMakeLists.txt b/staging_vespalib/src/tests/objects/CMakeLists.txt
new file mode 100644
index 00000000000..1ef21d0aaa5
--- /dev/null
+++ b/staging_vespalib/src/tests/objects/CMakeLists.txt
@@ -0,0 +1,8 @@
+# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(staging_vespalib_identifiable_test_app
+ SOURCES
+ identifiable_test.cpp
+ DEPENDS
+ staging_vespalib
+)
+vespa_add_test(NAME staging_vespalib_identifiable_test_app COMMAND staging_vespalib_identifiable_test_app)
diff --git a/staging_vespalib/src/tests/objects/DESC b/staging_vespalib/src/tests/objects/DESC
new file mode 100644
index 00000000000..fe2ee1fa6f4
--- /dev/null
+++ b/staging_vespalib/src/tests/objects/DESC
@@ -0,0 +1,2 @@
+identifiable test. Take a look at identifiable.cpp for details.
+asciistream test. Take a look at asciistream.cpp for details.
diff --git a/staging_vespalib/src/tests/objects/FILES b/staging_vespalib/src/tests/objects/FILES
new file mode 100644
index 00000000000..f50b9f9ca5a
--- /dev/null
+++ b/staging_vespalib/src/tests/objects/FILES
@@ -0,0 +1,2 @@
+identifiable.cpp
+asciistream.cpp
diff --git a/staging_vespalib/src/tests/objects/identifiable_test.cpp b/staging_vespalib/src/tests/objects/identifiable_test.cpp
new file mode 100644
index 00000000000..2fe793dae10
--- /dev/null
+++ b/staging_vespalib/src/tests/objects/identifiable_test.cpp
@@ -0,0 +1,339 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/fastos/fastos.h>
+#include <vespa/log/log.h>
+LOG_SETUP("identifiable_test");
+#include <vespa/vespalib/testkit/testapp.h>
+#include <vespa/vespalib/objects/identifiable.h>
+#include <vespa/vespalib/objects/namedobject.h>
+#include <vespa/vespalib/util/exceptions.h>
+
+using namespace vespalib;
+
+class IdentifiableTest : public TestApp {
+ void requireThatIdentifiableCastCanCastPointers();
+ void requireThatIdentifiableCastCanCastReferences();
+ void testNamedObject();
+ void testNboStream();
+ template <typename T>
+ void testStream(const T & a);
+ void testNboSerializer();
+ template <typename T>
+ void testSerializer(const T & a);
+public:
+ int Main();
+};
+
+#define CID_Abstract 0x700000
+#define CID_A 0x700001
+#define CID_B 0x700002
+#define CID_C 0x700003
+
+class Abstract : public Identifiable
+{
+public:
+ DECLARE_IDENTIFIABLE_ABSTRACT(Abstract);
+ virtual ~Abstract() { }
+ virtual void someAbstractVirtualMethod() = 0;
+};
+
+class A : public Abstract
+{
+public:
+ DECLARE_IDENTIFIABLE(A);
+ A() { }
+ virtual void someAbstractVirtualMethod() { };
+};
+
+class B : public A
+{
+public:
+ DECLARE_IDENTIFIABLE(B);
+ B() { }
+};
+
+class C : public Identifiable
+{
+private:
+ int _value;
+
+public:
+ DECLARE_IDENTIFIABLE(C);
+ C() : _value(0) {}
+ C(int value) : _value(value) {}
+ C *clone() const { return new C(*this); }
+ virtual int cmp(const Identifiable &rhs) const {
+ int result(cmpClassId(rhs));
+ if (result == 0) {
+ result = _value - static_cast<const C &>(rhs)._value;
+ }
+ return result;
+ }
+};
+
+IMPLEMENT_IDENTIFIABLE_ABSTRACT(Abstract, Identifiable);
+IMPLEMENT_IDENTIFIABLE(A, Abstract);
+IMPLEMENT_IDENTIFIABLE(B, A);
+IMPLEMENT_IDENTIFIABLE(C, Identifiable);
+
+void
+IdentifiableTest::testNamedObject()
+{
+ NamedObject a("first"), b("second");;
+ nbostream os;
+ NBOSerializer nos(os);
+ nos << a << b;
+ EXPECT_EQUAL(27u,os.size());
+ Identifiable::UP o1;
+ o1 = Identifiable::create(nos);
+ EXPECT_EQUAL(14u, os.size());
+ ASSERT_TRUE(o1->inherits(NamedObject::classId));
+ ASSERT_TRUE(o1->getClass().id() == NamedObject::classId);
+ EXPECT_TRUE(static_cast<const NamedObject &>(*o1).getName() == "first");
+ o1 = Identifiable::create(nos);
+ EXPECT_EQUAL(0u, os.size());
+ ASSERT_TRUE(o1->inherits(NamedObject::classId));
+ ASSERT_TRUE(o1->getClass().id() == NamedObject::classId);
+ EXPECT_TRUE(static_cast<const NamedObject &>(*o1).getName() == "second");
+}
+
+template <typename T>
+void IdentifiableTest::testStream(const T & a)
+{
+ nbostream s;
+ s << a;
+ T b;
+ s >> b;
+ EXPECT_TRUE(s.empty());
+ EXPECT_EQUAL(a, b);
+ EXPECT_EQUAL(nbostream::ok, s.state());
+ EXPECT_TRUE(s.good());
+}
+
+template <typename T>
+void IdentifiableTest::testSerializer(const T & a)
+{
+ nbostream t;
+ NBOSerializer s(t);
+ s << a;
+ T b;
+ s >> b;
+ EXPECT_TRUE(s.getStream().empty());
+ EXPECT_EQUAL(a, b);
+ EXPECT_EQUAL(nbostream::ok, s.getStream().state());
+}
+
+void IdentifiableTest::testNboSerializer()
+{
+ testSerializer(true);
+ testSerializer(false);
+ testSerializer(static_cast<int8_t>('a'));
+ testSerializer(static_cast<uint8_t>(156));
+ testSerializer(static_cast<int16_t>(156));
+ testSerializer(static_cast<int32_t>(156));
+ testSerializer(static_cast<int64_t>(156));
+ testSerializer(static_cast<uint16_t>(156));
+ testSerializer(static_cast<uint32_t>(156));
+ testSerializer(static_cast<uint64_t>(156));
+ testSerializer(static_cast<float>(156));
+ testSerializer(static_cast<double>(156));
+ testSerializer(vespalib::string("abcdefgh"));
+}
+
+void IdentifiableTest::testNboStream()
+{
+ testStream(true);
+ testStream(false);
+ testStream('a');
+ testStream(static_cast<unsigned char>(156));
+ testStream(static_cast<int16_t>(156));
+ testStream(static_cast<int32_t>(156));
+ testStream(static_cast<int64_t>(156));
+ testStream(static_cast<uint16_t>(156));
+ testStream(static_cast<uint32_t>(156));
+ testStream(static_cast<uint64_t>(156));
+ testStream(static_cast<float>(156));
+ testStream(static_cast<double>(156));
+ testStream(std::string("abcdefgh"));
+ testStream(vespalib::string("abcdefgh"));
+ {
+ nbostream s(4);
+ EXPECT_EQUAL(4u, s.capacity());
+ s << "abcdef";
+ EXPECT_EQUAL(nbostream::ok, s.state());
+ EXPECT_EQUAL(10u, s.size());
+ EXPECT_EQUAL(16u, s.capacity());
+ EXPECT_EQUAL(0, strncmp(s.c_str()+4, "abcdef", 6));
+ }
+ {
+ nbostream s(8);
+ EXPECT_EQUAL(0u, s.size());
+ EXPECT_EQUAL(8u, s.capacity());
+ const char * prev = s.c_str();
+ s << "ABCD";
+ EXPECT_EQUAL(8u, s.size());
+ EXPECT_EQUAL(8u, s.capacity());
+ EXPECT_EQUAL(prev, s.c_str());
+ s << "A long string that will cause resizing";
+ EXPECT_EQUAL(50u, s.size());
+ EXPECT_EQUAL(64u, s.capacity());
+ EXPECT_NOT_EQUAL(prev, s.c_str());
+ }
+ {
+ nbostream s(8);
+ EXPECT_EQUAL(0u, s.size());
+ EXPECT_EQUAL(8u, s.capacity());
+ const char * prev = s.c_str();
+ s << "ABCD";
+ EXPECT_EQUAL(8u, s.size());
+ EXPECT_EQUAL(8u, s.capacity());
+ EXPECT_EQUAL(prev, s.c_str());
+ s.reserve(50);
+ EXPECT_NOT_EQUAL(prev, s.c_str());
+ EXPECT_EQUAL(8u, s.size());
+ EXPECT_EQUAL(64u, s.capacity());
+ prev = s.c_str();
+ s << "A long string that will cause resizing";
+ EXPECT_EQUAL(50u, s.size());
+ EXPECT_EQUAL(64u, s.capacity());
+ EXPECT_EQUAL(prev, s.c_str());
+ }
+ {
+ nbostream s;
+ s << long(9);
+ EXPECT_EQUAL(8u, s.size());
+ EXPECT_EQUAL(0u, s.rp());
+ long a(7), b(1);
+ s >> a;
+ EXPECT_EQUAL(0u, s.size());
+ EXPECT_EQUAL(8u, s.rp());
+ EXPECT_TRUE(s.empty());
+ EXPECT_TRUE(s.good());
+ EXPECT_EQUAL(9, a);
+ try {
+ s >> b;
+ EXPECT_TRUE(false);
+ } catch (const IllegalStateException & e) {
+ EXPECT_EQUAL("Stream failed bufsize(1024), readp(8), writep(8)", e.getMessage());
+ }
+ EXPECT_EQUAL(0u, s.size());
+ EXPECT_EQUAL(8u, s.rp());
+ EXPECT_TRUE(s.empty());
+ EXPECT_FALSE(s.good());
+ EXPECT_EQUAL(1, b);
+ EXPECT_EQUAL(nbostream::eof, s.state());
+ }
+}
+
+int
+IdentifiableTest::Main()
+{
+ TEST_INIT("identifiable_test");
+
+ TEST_DO(requireThatIdentifiableCastCanCastPointers());
+ TEST_DO(requireThatIdentifiableCastCanCastReferences());
+ testNamedObject();
+ testNboStream();
+ testNboSerializer();
+
+ A a;
+ B b;
+
+ const Identifiable::RuntimeClass & rtcA = a.getClass();
+ EXPECT_EQUAL(rtcA.id(), static_cast<unsigned int>(A::classId));
+ EXPECT_EQUAL(strcmp(rtcA.name(), "A"), 0);
+
+ const Identifiable::RuntimeClass & rtcB = b.getClass();
+ EXPECT_EQUAL(rtcB.id(), static_cast<unsigned int>(B::classId));
+ EXPECT_EQUAL(strcmp(rtcB.name(), "B"), 0);
+
+ const Identifiable::RuntimeClass * rt(Identifiable::classFromId(0x1ab76245));
+ ASSERT_TRUE(rt == NULL);
+ rt = Identifiable::classFromId(Abstract::classId);
+ ASSERT_TRUE(rt != NULL);
+ Identifiable * u = rt->create();
+ ASSERT_TRUE(u == NULL);
+ rt = Identifiable::classFromId(A::classId);
+ ASSERT_TRUE(rt != NULL);
+ rt = Identifiable::classFromId(B::classId);
+ ASSERT_TRUE(rt != NULL);
+
+ Identifiable * o = rt->create();
+ ASSERT_TRUE(o != NULL);
+
+ const Identifiable::RuntimeClass & rtc = o->getClass();
+ ASSERT_TRUE(rtc.id() == B::classId);
+ ASSERT_TRUE(strcmp(rtc.name(), "B") == 0);
+ ASSERT_TRUE(o->inherits(B::classId));
+ ASSERT_TRUE(o->inherits(A::classId));
+ ASSERT_TRUE(o->inherits(Abstract::classId));
+ ASSERT_TRUE(o->inherits(Identifiable::classId));
+ ASSERT_TRUE(o->getClass().id() == B::classId);
+ nbostream os;
+ NBOSerializer nos(os);
+ nos << *o;
+ EXPECT_EQUAL(os.size(), 4u);
+ Identifiable::UP o2 = Identifiable::create(nos);
+ EXPECT_TRUE(os.empty());
+ ASSERT_TRUE(o->inherits(B::classId));
+ ASSERT_TRUE(o->getClass().id() == B::classId);
+ delete o;
+
+ rt = Identifiable::classFromName("NotBNorA");
+ ASSERT_TRUE(rt == NULL);
+ rt = Identifiable::classFromName("B");
+ ASSERT_TRUE(rt != NULL);
+ o = rt->create();
+ ASSERT_TRUE(o != NULL);
+ const Identifiable::RuntimeClass & rtc2 = o->getClass();
+ ASSERT_TRUE(rtc2.id() == B::classId);
+ ASSERT_TRUE(strcmp(rtc2.name(), "B") == 0);
+ ASSERT_TRUE(o->inherits(B::classId));
+ ASSERT_TRUE(o->inherits(A::classId));
+ ASSERT_TRUE(o->inherits(Abstract::classId));
+ ASSERT_TRUE(o->inherits(Identifiable::classId));
+ ASSERT_TRUE(o->getClass().id() == B::classId);
+ delete o;
+
+ IdentifiablePtr<C> c0(NULL);
+ IdentifiablePtr<C> c1(new C(10));
+ IdentifiablePtr<C> c2(new C(20));
+
+ EXPECT_LESS(c0.cmp(c1), 0);
+ EXPECT_EQUAL(c0.cmp(c0), 0);
+ EXPECT_GREATER(c1.cmp(c0), 0);
+
+ EXPECT_LESS(c1.cmp(c2), 0);
+ EXPECT_EQUAL(c1.cmp(c1), 0);
+ EXPECT_GREATER(c2.cmp(c1), 0);
+
+ TEST_DONE();
+}
+
+void IdentifiableTest::requireThatIdentifiableCastCanCastPointers() {
+ A a;
+ B b;
+ EXPECT_TRUE(Identifiable::cast<A *>(&a));
+ EXPECT_TRUE(Identifiable::cast<A *>(&b));
+ EXPECT_TRUE(!Identifiable::cast<B *>(&a));
+ EXPECT_TRUE(Identifiable::cast<B *>(&b));
+ EXPECT_TRUE(Identifiable::cast<Abstract *>(&a));
+ EXPECT_TRUE(Identifiable::cast<Abstract *>(&b));
+}
+
+void IdentifiableTest::requireThatIdentifiableCastCanCastReferences() {
+ A a;
+ B b;
+ try {
+ // These should not throw.
+ Identifiable::cast<A &>(a);
+ Identifiable::cast<A &>(b);
+ Identifiable::cast<B &>(b);
+ Identifiable::cast<Abstract &>(a);
+ Identifiable::cast<Abstract &>(b);
+ } catch (std::bad_cast &e) {
+ TEST_FATAL(e.what());
+ }
+ EXPECT_EXCEPTION(Identifiable::cast<B &>(a), std::bad_cast, "bad_cast");
+}
+
+TEST_APPHOOK(IdentifiableTest)
diff --git a/staging_vespalib/src/tests/objectselection/.gitignore b/staging_vespalib/src/tests/objectselection/.gitignore
new file mode 100644
index 00000000000..3dece3fbbfe
--- /dev/null
+++ b/staging_vespalib/src/tests/objectselection/.gitignore
@@ -0,0 +1,4 @@
+.depend
+Makefile
+objectselection_test
+staging_vespalib_objectselection_test_app
diff --git a/staging_vespalib/src/tests/objectselection/CMakeLists.txt b/staging_vespalib/src/tests/objectselection/CMakeLists.txt
new file mode 100644
index 00000000000..53453035267
--- /dev/null
+++ b/staging_vespalib/src/tests/objectselection/CMakeLists.txt
@@ -0,0 +1,8 @@
+# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(staging_vespalib_objectselection_test_app
+ SOURCES
+ objectselection.cpp
+ DEPENDS
+ staging_vespalib
+)
+vespa_add_test(NAME staging_vespalib_objectselection_test_app COMMAND staging_vespalib_objectselection_test_app)
diff --git a/staging_vespalib/src/tests/objectselection/DESC b/staging_vespalib/src/tests/objectselection/DESC
new file mode 100644
index 00000000000..929fb82d99a
--- /dev/null
+++ b/staging_vespalib/src/tests/objectselection/DESC
@@ -0,0 +1 @@
+objectselection test. Take a look at objectselection.cpp for details.
diff --git a/staging_vespalib/src/tests/objectselection/FILES b/staging_vespalib/src/tests/objectselection/FILES
new file mode 100644
index 00000000000..ebc80a4c647
--- /dev/null
+++ b/staging_vespalib/src/tests/objectselection/FILES
@@ -0,0 +1 @@
+objectselection.cpp
diff --git a/staging_vespalib/src/tests/objectselection/objectselection.cpp b/staging_vespalib/src/tests/objectselection/objectselection.cpp
new file mode 100644
index 00000000000..bc09d17fce5
--- /dev/null
+++ b/staging_vespalib/src/tests/objectselection/objectselection.cpp
@@ -0,0 +1,93 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/fastos/fastos.h>
+#include <vespa/log/log.h>
+LOG_SETUP("objectselection_test");
+#include <vespa/vespalib/testkit/testapp.h>
+#include <vespa/vespalib/objects/identifiable.h>
+#include <vespa/vespalib/objects/objectpredicate.h>
+#include <vespa/vespalib/objects/objectoperation.h>
+
+using namespace vespalib;
+
+#define CID_Foo 60000005
+#define CID_Bar 60000010
+
+struct Foo : public Identifiable
+{
+ typedef IdentifiablePtr<Foo> CP;
+ std::vector<CP> nodes;
+
+ DECLARE_IDENTIFIABLE(Foo);
+ virtual Foo *clone() const { return new Foo(*this); }
+ virtual void selectMembers(const ObjectPredicate &p, ObjectOperation &o) {
+ for (uint32_t i = 0; i < nodes.size(); ++i) {
+ nodes[i]->select(p, o);
+ }
+ }
+};
+IMPLEMENT_IDENTIFIABLE(Foo, Identifiable);
+
+struct Bar : public Foo
+{
+ int value;
+
+ DECLARE_IDENTIFIABLE(Bar);
+ Bar() : value(0) {}
+ Bar(int v) { value = v; }
+ virtual Bar *clone() const { return new Bar(*this); }
+};
+IMPLEMENT_IDENTIFIABLE(Bar, Identifiable);
+
+struct ObjectType : public ObjectPredicate
+{
+ uint32_t cid;
+ ObjectType(uint32_t id) : cid(id) {}
+ virtual bool check(const Identifiable &obj) const {
+ return (obj.getClass().id() == cid);
+ }
+};
+
+struct ObjectCollect : public ObjectOperation
+{
+ std::vector<Identifiable*> nodes;
+ virtual void execute(Identifiable &obj) {
+ nodes.push_back(&obj);
+ }
+};
+
+TEST_SETUP(Test);
+
+int
+Test::Main()
+{
+ TEST_INIT("objectselection_test");
+ {
+ Foo f1;
+ Foo f2;
+ Foo f3;
+ Bar b1(1);
+ Bar b2(2);
+ Bar b3(3);
+ Bar b4(4);
+ f2.nodes.push_back(b1);
+ f2.nodes.push_back(b2);
+ f3.nodes.push_back(b3);
+ f3.nodes.push_back(b4);
+ f1.nodes.push_back(f2);
+ f1.nodes.push_back(f3);
+
+ ObjectType predicate(Bar::classId);
+ ObjectCollect operation;
+ f1.select(predicate, operation);
+ ASSERT_TRUE(operation.nodes.size() == 4);
+ ASSERT_TRUE(operation.nodes[0]->getClass().id() == Bar::classId);
+ ASSERT_TRUE(operation.nodes[1]->getClass().id() == Bar::classId);
+ ASSERT_TRUE(operation.nodes[2]->getClass().id() == Bar::classId);
+ ASSERT_TRUE(operation.nodes[3]->getClass().id() == Bar::classId);
+ ASSERT_TRUE(((Bar*)operation.nodes[0])->value == 1);
+ ASSERT_TRUE(((Bar*)operation.nodes[1])->value == 2);
+ ASSERT_TRUE(((Bar*)operation.nodes[2])->value == 3);
+ ASSERT_TRUE(((Bar*)operation.nodes[3])->value == 4);
+ }
+ TEST_DONE();
+}
diff --git a/staging_vespalib/src/tests/polymorphicarray/.gitignore b/staging_vespalib/src/tests/polymorphicarray/.gitignore
new file mode 100644
index 00000000000..b3a74390312
--- /dev/null
+++ b/staging_vespalib/src/tests/polymorphicarray/.gitignore
@@ -0,0 +1 @@
+staging_vespalib_polymorphicarray_test_app
diff --git a/staging_vespalib/src/tests/polymorphicarray/CMakeLists.txt b/staging_vespalib/src/tests/polymorphicarray/CMakeLists.txt
new file mode 100644
index 00000000000..929dd258cfe
--- /dev/null
+++ b/staging_vespalib/src/tests/polymorphicarray/CMakeLists.txt
@@ -0,0 +1,8 @@
+# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(staging_vespalib_polymorphicarray_test_app
+ SOURCES
+ polymorphicarray_test.cpp
+ DEPENDS
+ staging_vespalib
+)
+vespa_add_test(NAME staging_vespalib_polymorphicarray_test_app COMMAND staging_vespalib_polymorphicarray_test_app)
diff --git a/staging_vespalib/src/tests/polymorphicarray/DESC b/staging_vespalib/src/tests/polymorphicarray/DESC
new file mode 100644
index 00000000000..dd68c799d64
--- /dev/null
+++ b/staging_vespalib/src/tests/polymorphicarray/DESC
@@ -0,0 +1 @@
+Array for polymorphic types test. Take a look at polymorphicarray_test.cpp for details.
diff --git a/staging_vespalib/src/tests/polymorphicarray/FILES b/staging_vespalib/src/tests/polymorphicarray/FILES
new file mode 100644
index 00000000000..d61af365757
--- /dev/null
+++ b/staging_vespalib/src/tests/polymorphicarray/FILES
@@ -0,0 +1 @@
+polymorphicarray_test.cpp
diff --git a/staging_vespalib/src/tests/polymorphicarray/polymorphicarray_test.cpp b/staging_vespalib/src/tests/polymorphicarray/polymorphicarray_test.cpp
new file mode 100644
index 00000000000..9d549d3cc34
--- /dev/null
+++ b/staging_vespalib/src/tests/polymorphicarray/polymorphicarray_test.cpp
@@ -0,0 +1,123 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/fastos/fastos.h>
+#include <vespa/vespalib/testkit/test_kit.h>
+#include <vespa/vespalib/util/polymorphicarrays.h>
+
+using namespace vespalib;
+
+class A {
+public:
+ virtual ~A() { }
+ virtual void assign(const A & rhs) { (void) rhs; assert(false); } // Required by the primitive array.
+ virtual A * clone() const { assert(false); return nullptr; } // Required for the complex array.
+
+ // For testing
+ virtual bool operator == (const A & rhs) const = 0;
+ virtual void print(std::ostream & os) const = 0;
+};
+
+class Primitive : public A
+{
+public:
+ Primitive(size_t v=11) : _v(v) { }
+ size_t value() const { return _v; }
+ bool operator == (const A & rhs) const override {
+ return dynamic_cast<const Primitive &>(rhs).value() == value();
+ }
+ void assign(const A & rhs) override {
+ _v = dynamic_cast<const Primitive &>(rhs).value();
+ }
+ void print(std::ostream & os) const override {
+ os << _v;
+ }
+private:
+ size_t _v;
+};
+
+
+class Complex : public A
+{
+public:
+ Complex(size_t v=11) : _v(v) { }
+ size_t value() const { return _v; }
+ bool operator == (const A & rhs) const override {
+ return dynamic_cast<const Complex &>(rhs).value() == value();
+ }
+ Complex * clone() const override {
+ return new Complex(_v);
+ }
+ void print(std::ostream & os) const override {
+ os << _v;
+ }
+private:
+ size_t _v;
+};
+
+std::ostream & operator << (std::ostream & os, const A & v) {
+ v.print(os);
+ return os;
+}
+
+
+template <typename T>
+void
+verifyArray(IArrayT<A> & array)
+{
+ EXPECT_EQUAL(0u, array.size());
+ for (size_t i(0); i < 10; i++) {
+ array.push_back(T(i));
+ }
+ EXPECT_EQUAL(10u, array.size());
+ for (size_t i(0); i < 10; i++) {
+ EXPECT_EQUAL(T(i), array[i]);
+ }
+ IArrayT<A>::UP copy(array.clone());
+ array.clear();
+ EXPECT_EQUAL(0u, array.size());
+
+ for (size_t i(0); i < copy->size(); i++) {
+ array.push_back((*copy)[i]);
+ }
+
+ array.resize(19);
+ EXPECT_EQUAL(19u, array.size());
+ for (size_t i(0); i < 10; i++) {
+ EXPECT_EQUAL(T(i), array[i]);
+ }
+ for (size_t i(10); i < array.size(); i++) {
+ EXPECT_EQUAL(T(11), array[i]);
+ }
+ array.resize(13);
+ EXPECT_EQUAL(13u, array.size());
+ for (size_t i(0); i < 10; i++) {
+ EXPECT_EQUAL(T(i), array[i]);
+ }
+ for (size_t i(10); i < array.size(); i++) {
+ EXPECT_EQUAL(T(11), array[i]);
+ }
+ dynamic_cast<T &>(array[1]) = T(17);
+ EXPECT_EQUAL(T(0), array[0]);
+ EXPECT_EQUAL(T(17), array[1]);
+ EXPECT_EQUAL(T(2), array[2]);
+}
+
+
+TEST("require that primitive arrays conforms") {
+ PrimitiveArrayT<Primitive, A> a;
+ verifyArray<Primitive>(a);
+ EXPECT_EQUAL(7u, a[7].value());
+}
+
+class Factory : public ComplexArrayT<A>::Factory
+{
+public:
+ A * create() { return new Complex(); }
+ virtual Factory * clone() const { return new Factory(*this); }
+};
+
+TEST("require that complex arrays conforms") {
+ ComplexArrayT<A> a(Factory::UP(new Factory()));
+ verifyArray<Complex>(a);
+}
+
+TEST_MAIN() { TEST_RUN_ALL(); }
diff --git a/staging_vespalib/src/tests/programoptions/.gitignore b/staging_vespalib/src/tests/programoptions/.gitignore
new file mode 100644
index 00000000000..31f3aa61556
--- /dev/null
+++ b/staging_vespalib/src/tests/programoptions/.gitignore
@@ -0,0 +1,4 @@
+.depend
+Makefile
+programoptions_test
+staging_vespalib_programoptions_test_app
diff --git a/staging_vespalib/src/tests/programoptions/CMakeLists.txt b/staging_vespalib/src/tests/programoptions/CMakeLists.txt
new file mode 100644
index 00000000000..7e436e7cee7
--- /dev/null
+++ b/staging_vespalib/src/tests/programoptions/CMakeLists.txt
@@ -0,0 +1,8 @@
+# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(staging_vespalib_programoptions_test_app
+ SOURCES
+ programoptions_test.cpp
+ DEPENDS
+ staging_vespalib
+)
+vespa_add_test(NAME staging_vespalib_programoptions_test_app COMMAND staging_vespalib_programoptions_test_app)
diff --git a/staging_vespalib/src/tests/programoptions/DESC b/staging_vespalib/src/tests/programoptions/DESC
new file mode 100644
index 00000000000..6ec9a059c7d
--- /dev/null
+++ b/staging_vespalib/src/tests/programoptions/DESC
@@ -0,0 +1 @@
+programoptions test. Take a look at programoptions.cpp for details.
diff --git a/staging_vespalib/src/tests/programoptions/FILES b/staging_vespalib/src/tests/programoptions/FILES
new file mode 100644
index 00000000000..468a6bfb10a
--- /dev/null
+++ b/staging_vespalib/src/tests/programoptions/FILES
@@ -0,0 +1 @@
+programoptions.cpp
diff --git a/staging_vespalib/src/tests/programoptions/programoptions_test.cpp b/staging_vespalib/src/tests/programoptions/programoptions_test.cpp
new file mode 100644
index 00000000000..5dd27c1ce38
--- /dev/null
+++ b/staging_vespalib/src/tests/programoptions/programoptions_test.cpp
@@ -0,0 +1,362 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#include <vespa/fastos/fastos.h>
+#include <vespa/vespalib/util/programoptions.h>
+#include <vespa/vespalib/util/programoptions_testutils.h>
+
+#include <iostream>
+#include <vespa/log/log.h>
+#include <vespa/vespalib/testkit/testapp.h>
+
+LOG_SETUP("programoptions_test");
+
+namespace vespalib {
+
+class Test : public vespalib::TestApp
+{
+public:
+ void testSyntaxPage();
+ void testNormalUsage();
+ void testFailures();
+ void testVectorArgument();
+ void testAllHiddenOption();
+ void testOptionsAfterArguments();
+ int Main();
+};
+
+int
+Test::Main()
+{
+ TEST_INIT("programoptions_test");
+ srandom(1);
+ testSyntaxPage();
+ testNormalUsage();
+ testFailures();
+ testVectorArgument();
+ testAllHiddenOption();
+ // Currently not supported
+ // testOptionsAfterArguments();
+ TEST_DONE();
+}
+
+struct MyOptions : public ProgramOptions {
+ bool boolOpt;
+ bool boolWithDefOpt;
+ int intOpt;
+ uint32_t uintOpt;
+ float floatOpt;
+ std::string stringOpt;
+ std::string argString;
+ int argInt;
+ std::string argOptionalString;
+ std::map<std::string, std::string> properties;
+ int anotherOptionalArg;
+
+ MyOptions(int argc, const char* const* argv)
+ : ProgramOptions(argc, argv)
+ {
+ // Required options
+ addOption("uintopt u", uintOpt, "Sets an unsigned int");
+ // Optional options
+ addOption("b bool", boolOpt, "Enables a flag");
+ addOption("boolwithdef", boolWithDefOpt, true, "If set turns to false");
+
+ addOption("intopt i", intOpt, 5, "Sets a signed int");
+ addOption("floatopt", floatOpt, 4.0f, "Sets a float\nMultiline baby");
+ addOption("string s", stringOpt, std::string("ballalaika"),
+ "Sets a string value. This is a very long description that "
+ "should be broken down into multiple lines in some sensible "
+ "way.");
+ addOptionHeader("Advanced options");
+ addOption("p properties", properties, "Property map");
+ addHiddenIdentifiers("prop");
+ setArgumentTypeName("key");
+ setArgumentTypeName("value", 1);
+
+ addArgument("argString", argString, "Required string argument.");
+ addArgument("argInt", argInt, "Required int argument.");
+ addArgument("argOptionalString", argOptionalString, std::string("foo"),
+ "Optional string argument with a long description so we "
+ "can see that it will be broken correctly.");
+ addArgument("argSecondOptional", anotherOptionalArg, 3,
+ "Yet another optional argument");
+
+ setSyntaxMessage("A test program to see if this utility works.");
+ setSyntaxPageMaxLeftColumnSize(25);
+ }
+
+};
+
+void Test::testSyntaxPage() {
+ AppOptions opts("myapp");
+ MyOptions options(opts.getArgCount(), opts.getArguments());
+ std::ostringstream actual;
+ options.writeSyntaxPage(actual);
+
+ std::string expected(
+"\nA test program to see if this utility works.\n\n"
+"Usage: myapp [options] <argString> <argInt> [argOptionalString] [argSecondOptional]\n\n"
+"Arguments:\n"
+" argString (string) : Required string argument.\n"
+" argInt (int) : Required int argument.\n"
+" argOptionalString (string)\n"
+" : Optional string argument with a long description so\n"
+" we can see that it will be broken correctly.\n"
+" (optional)\n"
+" argSecondOptional (int) : Yet another optional argument (optional)\n\n"
+"Options:\n"
+" --uintopt -u <uint> : Sets an unsigned int (required)\n"
+" -b --bool : Enables a flag\n"
+" --boolwithdef : If set turns to false\n"
+" --intopt -i <int> : Sets a signed int (default 5)\n"
+" --floatopt <float> : Sets a float\n"
+" Multiline baby (default 4)\n"
+" --string -s <string> : Sets a string value. This is a very long description\n"
+" that should be broken down into multiple lines in some\n"
+" sensible way. (default \"ballalaika\")\n\n"
+"Advanced options:\n"
+" -p --properties <key> <value> : Property map (default empty)\n"
+ );
+ EXPECT_EQUAL(expected, actual.str());
+}
+
+void Test::testNormalUsage() {
+ {
+ AppOptions opts("myapp -b --uintopt 4 -s foo tit 1 tei 6");
+ MyOptions options(opts.getArgCount(), opts.getArguments());
+ options.parse();
+ EXPECT_EQUAL(true, options.boolOpt);
+ EXPECT_EQUAL(true, options.boolWithDefOpt);
+ EXPECT_EQUAL(5, options.intOpt);
+ EXPECT_EQUAL(4u, options.uintOpt);
+ EXPECT_APPROX(4, options.floatOpt, 0.00001);
+ EXPECT_EQUAL("foo", options.stringOpt);
+ EXPECT_EQUAL("tit", options.argString);
+ EXPECT_EQUAL(1, options.argInt);
+ EXPECT_EQUAL("tei", options.argOptionalString);
+ EXPECT_EQUAL(0u, options.properties.size());
+ EXPECT_EQUAL(6, options.anotherOptionalArg);
+ }
+ {
+ AppOptions opts("myapp --uintopt 6 tit 1");
+ MyOptions options(opts.getArgCount(), opts.getArguments());
+ options.parse();
+ EXPECT_EQUAL(false, options.boolOpt);
+ EXPECT_EQUAL(true, options.boolWithDefOpt);
+ EXPECT_EQUAL(5, options.intOpt);
+ EXPECT_EQUAL(6u, options.uintOpt);
+ EXPECT_APPROX(4, options.floatOpt, 0.00001);
+ EXPECT_EQUAL("ballalaika", options.stringOpt);
+ EXPECT_EQUAL("tit", options.argString);
+ EXPECT_EQUAL(1, options.argInt);
+ EXPECT_EQUAL("foo", options.argOptionalString);
+ EXPECT_EQUAL(0u, options.properties.size());
+ EXPECT_EQUAL(3, options.anotherOptionalArg);
+ }
+ // Arguments coming after options.
+ // (Required for nesting of short options)
+ {
+ AppOptions opts("myapp --uintopt --intopt 6 -8 tit 1 tei");
+ MyOptions options(opts.getArgCount(), opts.getArguments());
+ options.parse();
+ EXPECT_EQUAL(false, options.boolOpt);
+ EXPECT_EQUAL(true, options.boolWithDefOpt);
+ EXPECT_EQUAL(-8, options.intOpt);
+ EXPECT_EQUAL(6u, options.uintOpt);
+ EXPECT_APPROX(4, options.floatOpt, 0.00001);
+ EXPECT_EQUAL("ballalaika", options.stringOpt);
+ EXPECT_EQUAL("tit", options.argString);
+ EXPECT_EQUAL(1, options.argInt);
+ EXPECT_EQUAL("tei", options.argOptionalString);
+ EXPECT_EQUAL(0u, options.properties.size());
+ }
+ {
+ AppOptions opts( "myapp -uib 6 -8 --boolwithdef tit 1 tei");
+ MyOptions options(opts.getArgCount(), opts.getArguments());
+ options.parse();
+ EXPECT_EQUAL(true, options.boolOpt);
+ EXPECT_EQUAL(false, options.boolWithDefOpt);
+ EXPECT_EQUAL(-8, options.intOpt);
+ EXPECT_EQUAL(6u, options.uintOpt);
+ EXPECT_APPROX(4, options.floatOpt, 0.00001);
+ EXPECT_EQUAL("ballalaika", options.stringOpt);
+ EXPECT_EQUAL("tit", options.argString);
+ EXPECT_EQUAL(1, options.argInt);
+ EXPECT_EQUAL("tei", options.argOptionalString);
+ EXPECT_EQUAL(0u, options.properties.size());
+ }
+ // Properties
+ {
+ AppOptions opts("myapp -u 6 -p foo bar --prop hmm brr tit 1 tei");
+ MyOptions options(opts.getArgCount(), opts.getArguments());
+ options.parse();
+ EXPECT_EQUAL(false, options.boolOpt);
+ EXPECT_EQUAL(true, options.boolWithDefOpt);
+ EXPECT_EQUAL(5, options.intOpt);
+ EXPECT_EQUAL(6u, options.uintOpt);
+ EXPECT_APPROX(4, options.floatOpt, 0.00001);
+ EXPECT_EQUAL("ballalaika", options.stringOpt);
+ EXPECT_EQUAL("tit", options.argString);
+ EXPECT_EQUAL(1, options.argInt);
+ EXPECT_EQUAL("tei", options.argOptionalString);
+ EXPECT_EQUAL(2u, options.properties.size());
+ EXPECT_EQUAL("bar", options.properties["foo"]);
+ EXPECT_EQUAL("brr", options.properties["hmm"]);
+ }
+}
+
+void Test::testFailures() {
+ // Non-existing long option
+ {
+ AppOptions opts("myapp -b --uintopt 4 -s foo --none");
+ MyOptions options(opts.getArgCount(), opts.getArguments());
+ try{
+ options.parse();
+ TEST_FATAL("Expected exception");
+ } catch (InvalidCommandLineArgumentsException& e) {
+ EXPECT_EQUAL("Invalid option 'none'.", e.getMessage());
+ }
+ }
+ // Non-existing short option
+ {
+ AppOptions opts("myapp -b --uintopt 4 -s foo -q");
+ MyOptions options(opts.getArgCount(), opts.getArguments());
+ try{
+ options.parse();
+ TEST_FATAL("Expected exception");
+ } catch (InvalidCommandLineArgumentsException& e) {
+ EXPECT_EQUAL("Invalid option 'q'.", e.getMessage());
+ }
+ }
+ // Lacking option argument
+ {
+ AppOptions opts("myapp -b --uintopt 4 -s");
+ MyOptions options(opts.getArgCount(), opts.getArguments());
+ try{
+ options.parse();
+ TEST_FATAL("Expected exception");
+ } catch (InvalidCommandLineArgumentsException& e) {
+ EXPECT_EQUAL("Option 's' needs 1 arguments. Only 0 available.",
+ e.getMessage());
+ }
+ }
+ // Out of signed ranged
+ {
+ AppOptions opts("myapp -b --uintopt 4 -intopt 3000000000");
+ MyOptions options(opts.getArgCount(), opts.getArguments());
+ try{
+ options.parse();
+ TEST_FATAL("Expected exception");
+ } catch (InvalidCommandLineArgumentsException& e) {
+ EXPECT_EQUAL("The argument '3000000000' can not be interpreted as a "
+ "number of type int.", e.getMessage());
+ }
+ }
+ // Negative value to unsigned var (Currently doesnt fail)
+/*
+ {
+ AppOptions opts("myapp -b --uintopt -1 foo 0");
+ MyOptions options(opts.getArgCount(), opts.getArguments());
+ try{
+ options.parse();
+ TEST_FATAL("Expected exception");
+ } catch (InvalidCommandLineArgumentsException& e) {
+ EXPECT_EQUAL("The argument '-1' can not be interpreted as a "
+ "number of type uint.", e.getMessage());
+ }
+ }
+ */
+ // Lacking required option
+ {
+ AppOptions opts("myapp -b");
+ MyOptions options(opts.getArgCount(), opts.getArguments());
+ try{
+ options.parse();
+ TEST_FATAL("Expected exception");
+ } catch (InvalidCommandLineArgumentsException& e) {
+ EXPECT_EQUAL("Option 'uintopt' has no default and must be set.",
+ e.getMessage());
+ }
+ }
+ // Lacking required argument
+ {
+ AppOptions opts("myapp --uintopt 1 tit");
+ MyOptions options(opts.getArgCount(), opts.getArguments());
+ try{
+ options.parse();
+ TEST_FATAL("Expected exception");
+ } catch (InvalidCommandLineArgumentsException& e) {
+ EXPECT_EQUAL("Insufficient data is given to set required argument "
+ "'argInt'.",
+ e.getMessage());
+ }
+ }
+ // Argument of wrong type
+ {
+ AppOptions opts("myapp --uintopt 1 tit en");
+ MyOptions options(opts.getArgCount(), opts.getArguments());
+ try{
+ options.parse();
+ TEST_FATAL("Expected exception");
+ } catch (InvalidCommandLineArgumentsException& e) {
+ EXPECT_EQUAL("The argument 'en' can not be interpreted as a number "
+ "of type int.",
+ e.getMessage());
+ }
+ }
+}
+
+void Test::testVectorArgument()
+{
+ AppOptions opts("myapp foo bar baz");
+ std::vector<std::string> args;
+ ProgramOptions options(opts.getArgCount(), opts.getArguments());
+ options.addListArgument("ids", args, "Vector element");
+ std::ostringstream actual;
+ options.writeSyntaxPage(actual);
+ std::string expected(
+"\nUsage: myapp [ids...]\n\n"
+"Arguments:\n"
+" ids (string[]) : Vector element\n"
+ );
+ EXPECT_EQUAL(expected, actual.str());
+
+ options.parse();
+ EXPECT_EQUAL(3u, args.size());
+ EXPECT_EQUAL("foo", args[0]);
+ EXPECT_EQUAL("bar", args[1]);
+ EXPECT_EQUAL("baz", args[2]);
+}
+
+void Test::testAllHiddenOption()
+{
+ AppOptions opts("myapp --foo bar");
+ std::string option;
+ ProgramOptions options(opts.getArgCount(), opts.getArguments());
+ options.addOption("", option, "Description");
+ options.addHiddenIdentifiers("foo");
+ std::ostringstream actual;
+ options.writeSyntaxPage(actual);
+ std::string expected("\nUsage: myapp\n");
+ EXPECT_EQUAL(expected, actual.str());
+
+ options.parse();
+ EXPECT_EQUAL("bar", option);
+}
+
+void Test::testOptionsAfterArguments()
+{
+ AppOptions opts("myapp bar --foo baz");
+ std::string option;
+ std::string argument;
+ ProgramOptions options(opts.getArgCount(), opts.getArguments());
+ options.addOption("foo", option, "Description");
+ options.addArgument("arg", argument, "Description");
+ options.parse();
+ EXPECT_EQUAL("baz", option);
+ EXPECT_EQUAL("bar", argument);
+}
+
+} // vespalib
+
+TEST_APPHOOK(vespalib::Test)
diff --git a/staging_vespalib/src/tests/rusage/.gitignore b/staging_vespalib/src/tests/rusage/.gitignore
new file mode 100644
index 00000000000..195922a9ced
--- /dev/null
+++ b/staging_vespalib/src/tests/rusage/.gitignore
@@ -0,0 +1 @@
+staging_vespalib_rusage_test_app
diff --git a/staging_vespalib/src/tests/rusage/CMakeLists.txt b/staging_vespalib/src/tests/rusage/CMakeLists.txt
new file mode 100644
index 00000000000..b927110179e
--- /dev/null
+++ b/staging_vespalib/src/tests/rusage/CMakeLists.txt
@@ -0,0 +1,8 @@
+# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(staging_vespalib_rusage_test_app
+ SOURCES
+ rusage_test.cpp
+ DEPENDS
+ staging_vespalib
+)
+vespa_add_test(NAME staging_vespalib_rusage_test_app COMMAND staging_vespalib_rusage_test_app)
diff --git a/staging_vespalib/src/tests/rusage/DESC b/staging_vespalib/src/tests/rusage/DESC
new file mode 100644
index 00000000000..957ed92a119
--- /dev/null
+++ b/staging_vespalib/src/tests/rusage/DESC
@@ -0,0 +1 @@
+rusage test. Take a look at rusage_test.cpp for details.
diff --git a/staging_vespalib/src/tests/rusage/FILES b/staging_vespalib/src/tests/rusage/FILES
new file mode 100644
index 00000000000..bea76c6f532
--- /dev/null
+++ b/staging_vespalib/src/tests/rusage/FILES
@@ -0,0 +1 @@
+rusage_test.cpp
diff --git a/staging_vespalib/src/tests/rusage/rusage_test.cpp b/staging_vespalib/src/tests/rusage/rusage_test.cpp
new file mode 100644
index 00000000000..3da7f1d0b54
--- /dev/null
+++ b/staging_vespalib/src/tests/rusage/rusage_test.cpp
@@ -0,0 +1,76 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/fastos/fastos.h>
+#include <stddef.h>
+#include <vespa/log/log.h>
+LOG_SETUP("alloc_test");
+#include <vespa/vespalib/testkit/testapp.h>
+#include <vespa/vespalib/util/rusage.h>
+
+using namespace vespalib;
+
+class Test : public TestApp
+{
+public:
+ int Main();
+ void testRUsage();
+};
+
+int
+Test::Main()
+{
+ TEST_INIT("rusage_test");
+ testRUsage();
+ TEST_DONE();
+}
+
+void
+Test::testRUsage()
+{
+ RUsage r1;
+ EXPECT_EQUAL("", r1.toString());
+ RUsage r2;
+ EXPECT_EQUAL(r2.toString(), r1.toString());
+ RUsage diff = r2-r1;
+ EXPECT_EQUAL(diff.toString(), r2.toString());
+ {
+ RUsage then = RUsage::createSelf(17765895674);
+ RUsage now = RUsage::createSelf();
+ EXPECT_NOT_EQUAL(now.toString(), then.toString());
+ }
+ {
+ RUsage then = RUsage::createChildren(1337583);
+ RUsage now = RUsage::createChildren();
+ EXPECT_NOT_EQUAL(now.toString(), then.toString());
+ }
+ {
+ timeval a, b, c, d, r;
+ a.tv_usec = 7;
+ a.tv_sec = 7;
+ b.tv_usec = 7;
+ b.tv_sec = 7;
+ c.tv_usec = 1;
+ c.tv_sec = 8;
+ d.tv_usec = 9;
+ d.tv_sec = 4;
+ r = a - b;
+ EXPECT_EQUAL(0, r.tv_sec);
+ EXPECT_EQUAL(0, r.tv_usec);
+ r = b - a;
+ EXPECT_EQUAL(0, r.tv_sec);
+ EXPECT_EQUAL(0, r.tv_usec);
+ r = a - c;
+ EXPECT_EQUAL(-1, r.tv_sec);
+ EXPECT_EQUAL( 6, r.tv_usec);
+ r = c - a;
+ EXPECT_EQUAL(0, r.tv_sec);
+ EXPECT_EQUAL(999994, r.tv_usec);
+ r = a - d;
+ EXPECT_EQUAL(2, r.tv_sec);
+ EXPECT_EQUAL(999998, r.tv_usec);
+ r = d - a;
+ EXPECT_EQUAL(-3, r.tv_sec);
+ EXPECT_EQUAL( 2, r.tv_usec);
+ }
+}
+
+TEST_APPHOOK(Test)
diff --git a/staging_vespalib/src/tests/shutdownguard/.gitignore b/staging_vespalib/src/tests/shutdownguard/.gitignore
new file mode 100644
index 00000000000..a596164ac7b
--- /dev/null
+++ b/staging_vespalib/src/tests/shutdownguard/.gitignore
@@ -0,0 +1 @@
+staging_vespalib_shutdownguard_test_app
diff --git a/staging_vespalib/src/tests/shutdownguard/CMakeLists.txt b/staging_vespalib/src/tests/shutdownguard/CMakeLists.txt
new file mode 100644
index 00000000000..75093312cd3
--- /dev/null
+++ b/staging_vespalib/src/tests/shutdownguard/CMakeLists.txt
@@ -0,0 +1,8 @@
+# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(staging_vespalib_shutdownguard_test_app
+ SOURCES
+ shutdownguard_test.cpp
+ DEPENDS
+ staging_vespalib
+)
+vespa_add_test(NAME staging_vespalib_shutdownguard_test_app NO_VALGRIND COMMAND staging_vespalib_shutdownguard_test_app)
diff --git a/staging_vespalib/src/tests/shutdownguard/DESC b/staging_vespalib/src/tests/shutdownguard/DESC
new file mode 100644
index 00000000000..869fc61d80f
--- /dev/null
+++ b/staging_vespalib/src/tests/shutdownguard/DESC
@@ -0,0 +1 @@
+shutdown guard test. Take a look at shutdownguard_test.cpp for details.
diff --git a/staging_vespalib/src/tests/shutdownguard/FILES b/staging_vespalib/src/tests/shutdownguard/FILES
new file mode 100644
index 00000000000..0c040a71f20
--- /dev/null
+++ b/staging_vespalib/src/tests/shutdownguard/FILES
@@ -0,0 +1 @@
+suicide_test.cpp
diff --git a/staging_vespalib/src/tests/shutdownguard/shutdownguard_test.cpp b/staging_vespalib/src/tests/shutdownguard/shutdownguard_test.cpp
new file mode 100644
index 00000000000..c31e34afe76
--- /dev/null
+++ b/staging_vespalib/src/tests/shutdownguard/shutdownguard_test.cpp
@@ -0,0 +1,40 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/fastos/fastos.h>
+#include <vespa/log/log.h>
+LOG_SETUP("shutdownguard_test");
+#include <vespa/vespalib/testkit/testapp.h>
+#include <vespa/vespalib/util/shutdownguard.h>
+
+using namespace vespalib;
+
+TEST_SETUP(Test);
+
+int
+Test::Main()
+{
+ TEST_INIT("shutdownguard_test");
+ {
+ ShutdownGuard farFuture(123456789);
+ FastOS_Thread::Sleep(20);
+ }
+ EXPECT_TRUE(true);
+ pid_t child = fork();
+ if (child == 0) {
+ ShutdownGuard soon(30);
+ for (int i = 0; i < 1000; ++i) {
+ FastOS_Thread::Sleep(20);
+ }
+ exit(0);
+ }
+ for (int i = 0; i < 1000; ++i) {
+ FastOS_Thread::Sleep(20);
+ int stat = 0;
+ if (waitpid(child, &stat, WNOHANG) == child) {
+ EXPECT_TRUE(WIFEXITED(stat));
+ EXPECT_EQUAL(1, WEXITSTATUS(stat));
+ break;
+ }
+ EXPECT_TRUE(i < 800);
+ }
+ TEST_DONE();
+}
diff --git a/staging_vespalib/src/tests/state_server/.gitignore b/staging_vespalib/src/tests/state_server/.gitignore
new file mode 100644
index 00000000000..b1884d4e060
--- /dev/null
+++ b/staging_vespalib/src/tests/state_server/.gitignore
@@ -0,0 +1 @@
+staging_vespalib_state_server_test_app
diff --git a/staging_vespalib/src/tests/state_server/CMakeLists.txt b/staging_vespalib/src/tests/state_server/CMakeLists.txt
new file mode 100644
index 00000000000..a62549a563b
--- /dev/null
+++ b/staging_vespalib/src/tests/state_server/CMakeLists.txt
@@ -0,0 +1,8 @@
+# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(staging_vespalib_state_server_test_app
+ SOURCES
+ state_server_test.cpp
+ DEPENDS
+ staging_vespalib
+)
+vespa_add_test(NAME staging_vespalib_state_server_test_app NO_VALGRIND NO_VALGRIND COMMAND staging_vespalib_state_server_test_app)
diff --git a/staging_vespalib/src/tests/state_server/FILES b/staging_vespalib/src/tests/state_server/FILES
new file mode 100644
index 00000000000..2328b597e56
--- /dev/null
+++ b/staging_vespalib/src/tests/state_server/FILES
@@ -0,0 +1 @@
+state_server_test.cpp
diff --git a/staging_vespalib/src/tests/state_server/state_server_test.cpp b/staging_vespalib/src/tests/state_server/state_server_test.cpp
new file mode 100644
index 00000000000..79236523694
--- /dev/null
+++ b/staging_vespalib/src/tests/state_server/state_server_test.cpp
@@ -0,0 +1,444 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/fastos/fastos.h>
+#include <vespa/vespalib/testkit/test_kit.h>
+#include <vespa/vespalib/net/state_server.h>
+#include <vespa/vespalib/net/simple_health_producer.h>
+#include <vespa/vespalib/net/simple_metrics_producer.h>
+#include <vespa/vespalib/net/simple_component_config_producer.h>
+#include <vespa/vespalib/util/stringfmt.h>
+#include <vespa/vespalib/util/slaveproc.h>
+#include <vespa/vespalib/net/state_explorer.h>
+#include <vespa/vespalib/net/slime_explorer.h>
+#include <vespa/vespalib/net/generic_state_handler.h>
+
+using namespace vespalib;
+
+//-----------------------------------------------------------------------------
+
+vespalib::string root_path = "/state/v1/";
+vespalib::string short_root_path = "/state/v1";
+vespalib::string metrics_path = "/state/v1/metrics";
+vespalib::string health_path = "/state/v1/health";
+vespalib::string config_path = "/state/v1/config";
+
+vespalib::string total_metrics_path = "/metrics/total";
+
+vespalib::string unknown_path = "/this/path/is/not/known";
+vespalib::string unknown_state_path = "/state/v1/this/path/is/not/known";
+vespalib::string my_path = "/my/path";
+
+vespalib::string host_tag = "HOST";
+std::map<vespalib::string,vespalib::string> empty_params;
+
+//-----------------------------------------------------------------------------
+
+vespalib::string run_cmd(const vespalib::string &cmd) {
+ std::string out;
+ ASSERT_TRUE(SlaveProc::run(cmd.c_str(), out));
+ return out;
+}
+
+vespalib::string getPage(int port, const vespalib::string &path, const vespalib::string &extra_params = "") {
+ vespalib::string result = run_cmd(make_string("curl -s %s http://localhost:%d%s", extra_params.c_str(), port, path.c_str()));
+ vespalib::string chunked_result = run_cmd(make_string("curl -H transfer-encoding:chunked -s %s http://localhost:%d%s", extra_params.c_str(), port, path.c_str()));
+ ASSERT_EQUAL(result, chunked_result);
+ return result;
+}
+
+vespalib::string getFull(int port, const vespalib::string &path) { return getPage(port, path, "-D -"); }
+
+//-----------------------------------------------------------------------------
+
+struct DummyHandler : JsonGetHandler {
+ vespalib::string result;
+ DummyHandler(const vespalib::string &result_in) : result(result_in) {}
+ virtual vespalib::string get(const vespalib::string &,
+ const vespalib::string &,
+ const std::map<vespalib::string,vespalib::string> &) const
+ {
+ return result;
+ }
+};
+
+//-----------------------------------------------------------------------------
+
+TEST_F("require that unknown url returns 404 response", HttpServer(0)) {
+ f1.start();
+ std::string expect("HTTP/1.1 404 Not Found\r\n"
+ "Connection: close\r\n"
+ "\r\n");
+ std::string actual = getFull(f1.port(), unknown_path);
+ EXPECT_EQUAL(expect, actual);
+}
+
+TEST_FF("require that empty known url returns 404 response", DummyHandler(""), HttpServer(0)) {
+ auto token = f2.repo().bind(my_path, f1);
+ f2.start();
+ std::string expect("HTTP/1.1 404 Not Found\r\n"
+ "Connection: close\r\n"
+ "\r\n");
+ std::string actual = getFull(f2.port(), my_path);
+ EXPECT_EQUAL(expect, actual);
+}
+
+TEST_FF("require that non-empty known url returns expected headers", DummyHandler("[123]"), HttpServer(0)) {
+ auto token = f2.repo().bind(my_path, f1);
+ f2.start();
+ vespalib::string expect("HTTP/1.1 200 OK\r\n"
+ "Connection: close\r\n"
+ "Content-Type: application/json\r\n"
+ "\r\n"
+ "[123]");
+ std::string actual = getFull(f2.port(), my_path);
+ EXPECT_EQUAL(expect, actual);
+}
+
+TEST_FFFF("require that handler is selected based on longest matching url prefix",
+ DummyHandler("[1]"), DummyHandler("[2]"), DummyHandler("[3]"),
+ HttpServer(0))
+{
+ auto token2 = f4.repo().bind("/foo/bar", f2);
+ auto token1 = f4.repo().bind("/foo", f1);
+ auto token3 = f4.repo().bind("/foo/bar/baz", f3);
+ f4.start();
+ int port = f4.port();
+ EXPECT_EQUAL("", getPage(port, "/fox"));
+ EXPECT_EQUAL("[1]", getPage(port, "/foo"));
+ EXPECT_EQUAL("[1]", getPage(port, "/foo/fox"));
+ EXPECT_EQUAL("[2]", getPage(port, "/foo/bar"));
+ EXPECT_EQUAL("[2]", getPage(port, "/foo/bar/fox"));
+ EXPECT_EQUAL("[3]", getPage(port, "/foo/bar/baz"));
+ EXPECT_EQUAL("[3]", getPage(port, "/foo/bar/baz/fox"));
+}
+
+struct EchoHost : JsonGetHandler {
+ virtual vespalib::string get(const vespalib::string &host,
+ const vespalib::string &,
+ const std::map<vespalib::string,vespalib::string> &) const
+ {
+ return "[\"" + host + "\"]";
+ }
+};
+
+TEST_FF("require that host is passed correctly", EchoHost(), HttpServer(0)) {
+ auto token = f2.repo().bind(my_path, f1);
+ f2.start();
+ EXPECT_EQUAL(make_string("%s:%d", run_cmd("hostname").c_str(), f2.port()), f2.host());
+ vespalib::string default_result = make_string("[\"%s\"]", f2.host().c_str());
+ vespalib::string localhost_result = make_string("[\"%s:%d\"]", "localhost", f2.port());
+ vespalib::string silly_result = "[\"sillyserver\"]";
+ EXPECT_EQUAL(localhost_result, run_cmd(make_string("curl -s http://localhost:%d/my/path", f2.port())));
+ EXPECT_EQUAL(silly_result, run_cmd(make_string("curl -s http://localhost:%d/my/path -H \"Host: sillyserver\"", f2.port())));
+ EXPECT_EQUAL(default_result, run_cmd(make_string("curl -s http://localhost:%d/my/path -H \"Host:\"", f2.port())));
+}
+
+//-----------------------------------------------------------------------------
+
+TEST_FFFF("require that the state server wires the appropriate url prefixes",
+ SimpleHealthProducer(), SimpleMetricsProducer(), SimpleComponentConfigProducer(),
+ StateServer(0, f1, f2, f3))
+{
+ f2.setTotalMetrics("{}"); // avoid empty result
+ int port = f4.getListenPort();
+ EXPECT_TRUE(getFull(port, short_root_path).find("HTTP/1.1 200 OK") == 0);
+ EXPECT_TRUE(getFull(port, total_metrics_path).find("HTTP/1.1 200 OK") == 0);
+ EXPECT_TRUE(getFull(port, unknown_path).find("HTTP/1.1 404 Not Found") == 0);
+}
+
+TEST_FFFF("require that the state server exposes the state api handler repo",
+ SimpleHealthProducer(), SimpleMetricsProducer(), SimpleComponentConfigProducer(),
+ StateServer(0, f1, f2, f3))
+{
+ int port = f4.getListenPort();
+ vespalib::string page1 = getPage(port, root_path);
+ auto token = f4.repo().add_root_resource("state/v1/custom");
+ vespalib::string page2 = getPage(port, root_path);
+ EXPECT_NOT_EQUAL(page1, page2);
+ token.reset();
+ vespalib::string page3 = getPage(port, root_path);
+ EXPECT_EQUAL(page3, page1);
+}
+
+//-----------------------------------------------------------------------------
+
+TEST_FFFF("require that json handlers can be removed from repo",
+ DummyHandler("[1]"), DummyHandler("[2]"), DummyHandler("[3]"),
+ JsonHandlerRepo())
+{
+ auto token1 = f4.bind("/foo", f1);
+ auto token2 = f4.bind("/foo/bar", f2);
+ auto token3 = f4.bind("/foo/bar/baz", f3);
+ std::map<vespalib::string,vespalib::string> params;
+ EXPECT_EQUAL("[1]", f4.get("", "/foo", params));
+ EXPECT_EQUAL("[2]", f4.get("", "/foo/bar", params));
+ EXPECT_EQUAL("[3]", f4.get("", "/foo/bar/baz", params));
+ token2.reset();
+ EXPECT_EQUAL("[1]", f4.get("", "/foo", params));
+ EXPECT_EQUAL("[1]", f4.get("", "/foo/bar", params));
+ EXPECT_EQUAL("[3]", f4.get("", "/foo/bar/baz", params));
+}
+
+TEST_FFFF("require that json handlers can be shadowed",
+ DummyHandler("[1]"), DummyHandler("[2]"), DummyHandler("[3]"),
+ JsonHandlerRepo())
+{
+ auto token1 = f4.bind("/foo", f1);
+ auto token2 = f4.bind("/foo/bar", f2);
+ std::map<vespalib::string,vespalib::string> params;
+ EXPECT_EQUAL("[1]", f4.get("", "/foo", params));
+ EXPECT_EQUAL("[2]", f4.get("", "/foo/bar", params));
+ auto token3 = f4.bind("/foo/bar", f3);
+ EXPECT_EQUAL("[3]", f4.get("", "/foo/bar", params));
+ token3.reset();
+ EXPECT_EQUAL("[2]", f4.get("", "/foo/bar", params));
+}
+
+TEST_F("require that root resources can be tracked", JsonHandlerRepo())
+{
+ EXPECT_TRUE(std::vector<vespalib::string>({}) == f1.get_root_resources());
+ auto token1 = f1.add_root_resource("/health");
+ EXPECT_TRUE(std::vector<vespalib::string>({"/health"}) == f1.get_root_resources());
+ auto token2 = f1.add_root_resource("/config");
+ EXPECT_TRUE(std::vector<vespalib::string>({"/health", "/config"}) == f1.get_root_resources());
+ auto token3 = f1.add_root_resource("/custom/foo");
+ EXPECT_TRUE(std::vector<vespalib::string>({"/health", "/config", "/custom/foo"}) == f1.get_root_resources());
+ token2.reset();
+ EXPECT_TRUE(std::vector<vespalib::string>({"/health", "/custom/foo"}) == f1.get_root_resources());
+}
+
+//-----------------------------------------------------------------------------
+
+TEST_FFFF("require that state api responds to the expected paths",
+ SimpleHealthProducer(), SimpleMetricsProducer(), SimpleComponentConfigProducer(),
+ StateApi(f1, f2, f3))
+{
+ f2.setTotalMetrics("{}"); // avoid empty result
+ EXPECT_TRUE(!f4.get(host_tag, short_root_path, empty_params).empty());
+ EXPECT_TRUE(!f4.get(host_tag, root_path, empty_params).empty());
+ EXPECT_TRUE(!f4.get(host_tag, health_path, empty_params).empty());
+ EXPECT_TRUE(!f4.get(host_tag, metrics_path, empty_params).empty());
+ EXPECT_TRUE(!f4.get(host_tag, config_path, empty_params).empty());
+ EXPECT_TRUE(!f4.get(host_tag, total_metrics_path, empty_params).empty());
+ EXPECT_TRUE(f4.get(host_tag, unknown_path, empty_params).empty());
+ EXPECT_TRUE(f4.get(host_tag, unknown_state_path, empty_params).empty());
+}
+
+TEST_FFFF("require that top-level urls are generated correctly",
+ SimpleHealthProducer(), SimpleMetricsProducer(), SimpleComponentConfigProducer(),
+ StateApi(f1, f2, f3))
+{
+ EXPECT_EQUAL("{\"resources\":["
+ "{\"url\":\"http://HOST/state/v1/health\"},"
+ "{\"url\":\"http://HOST/state/v1/metrics\"},"
+ "{\"url\":\"http://HOST/state/v1/config\"}]}",
+ f4.get(host_tag, root_path, empty_params));
+ EXPECT_EQUAL(f4.get(host_tag, root_path, empty_params),
+ f4.get(host_tag, short_root_path, empty_params));
+}
+
+TEST_FFFF("require that top-level resource list can be extended",
+ SimpleHealthProducer(), SimpleMetricsProducer(), SimpleComponentConfigProducer(),
+ StateApi(f1, f2, f3))
+{
+ auto token = f4.repo().add_root_resource("/state/v1/custom");
+ EXPECT_EQUAL("{\"resources\":["
+ "{\"url\":\"http://HOST/state/v1/health\"},"
+ "{\"url\":\"http://HOST/state/v1/metrics\"},"
+ "{\"url\":\"http://HOST/state/v1/config\"},"
+ "{\"url\":\"http://HOST/state/v1/custom\"}]}",
+ f4.get(host_tag, root_path, empty_params));
+}
+
+TEST_FFFF("require that health resource works as expected",
+ SimpleHealthProducer(), SimpleMetricsProducer(), SimpleComponentConfigProducer(),
+ StateApi(f1, f2, f3))
+{
+ EXPECT_EQUAL("{\"status\":{\"code\":\"up\"}}",
+ f4.get(host_tag, health_path, empty_params));
+ f1.setFailed("FAIL MSG");
+ EXPECT_EQUAL("{\"status\":{\"code\":\"down\",\"message\":\"FAIL MSG\"}}",
+ f4.get(host_tag, health_path, empty_params));
+}
+
+TEST_FFFF("require that metrics resource works as expected",
+ SimpleHealthProducer(), SimpleMetricsProducer(), SimpleComponentConfigProducer(),
+ StateApi(f1, f2, f3))
+{
+ EXPECT_EQUAL("{\"status\":{\"code\":\"up\"}}",
+ f4.get(host_tag, metrics_path, empty_params));
+ f1.setFailed("FAIL MSG");
+ EXPECT_EQUAL("{\"status\":{\"code\":\"down\",\"message\":\"FAIL MSG\"}}",
+ f4.get(host_tag, metrics_path, empty_params));
+ f1.setOk();
+ f2.setMetrics("{\"foo\":\"bar\"}");
+ EXPECT_EQUAL("{\"status\":{\"code\":\"up\"},\"metrics\":{\"foo\":\"bar\"}}",
+ f4.get(host_tag, metrics_path, empty_params));
+}
+
+TEST_FFFF("require that config resource works as expected",
+ SimpleHealthProducer(), SimpleMetricsProducer(), SimpleComponentConfigProducer(),
+ StateApi(f1, f2, f3))
+{
+ EXPECT_EQUAL("{\"config\":{}}",
+ f4.get(host_tag, config_path, empty_params));
+ f3.addConfig(SimpleComponentConfigProducer::Config("foo", 3));
+ EXPECT_EQUAL("{\"config\":{\"generation\":3,\"foo\":{\"generation\":3}}}",
+ f4.get(host_tag, config_path, empty_params));
+ f3.addConfig(SimpleComponentConfigProducer::Config("foo", 4));
+ f3.addConfig(SimpleComponentConfigProducer::Config("bar", 4, "error"));
+ EXPECT_EQUAL("{\"config\":{\"generation\":4,\"bar\":{\"generation\":4,\"message\":\"error\"},\"foo\":{\"generation\":4}}}",
+ f4.get(host_tag, config_path, empty_params));
+ f3.removeConfig("bar");
+ EXPECT_EQUAL("{\"config\":{\"generation\":4,\"foo\":{\"generation\":4}}}",
+ f4.get(host_tag, config_path, empty_params));
+}
+
+TEST_FFFF("require that state api also can return total metric",
+ SimpleHealthProducer(), SimpleMetricsProducer(), SimpleComponentConfigProducer(),
+ StateApi(f1, f2, f3))
+{
+ f2.setTotalMetrics("{\"foo\":\"bar\"}");
+ EXPECT_EQUAL("{\"foo\":\"bar\"}",
+ f4.get(host_tag, total_metrics_path, empty_params));
+}
+
+TEST_FFFFF("require that custom handlers can be added to the state server",
+ SimpleHealthProducer(), SimpleMetricsProducer(), SimpleComponentConfigProducer(),
+ StateApi(f1, f2, f3), DummyHandler("[123]"))
+{
+ EXPECT_EQUAL("", f4.get(host_tag, my_path, empty_params));
+ auto token = f4.repo().bind(my_path, f5);
+ EXPECT_EQUAL("[123]", f4.get(host_tag, my_path, empty_params));
+ token.reset();
+ EXPECT_EQUAL("", f4.get(host_tag, my_path, empty_params));
+}
+
+struct EchoConsumer : MetricsProducer {
+ virtual vespalib::string getMetrics(const vespalib::string &consumer) {
+ return "[\"" + consumer + "\"]";
+ }
+ virtual vespalib::string getTotalMetrics(const vespalib::string &consumer) {
+ return "[\"" + consumer + "\"]";
+ }
+};
+
+TEST_FFFF("require that metrics consumer is passed correctly",
+ SimpleHealthProducer(), EchoConsumer(), SimpleComponentConfigProducer(),
+ StateApi(f1, f2, f3))
+{
+ std::map<vespalib::string,vespalib::string> my_params;
+ my_params["consumer"] = "ME";
+ EXPECT_EQUAL("{\"status\":{\"code\":\"up\"},\"metrics\":[\"\"]}", f4.get(host_tag, metrics_path, empty_params));
+ EXPECT_EQUAL("{\"status\":{\"code\":\"up\"},\"metrics\":[\"ME\"]}", f4.get(host_tag, metrics_path, my_params));
+ EXPECT_EQUAL("[\"\"]", f4.get(host_tag, total_metrics_path, empty_params));
+ EXPECT_EQUAL("[\"ME\"]", f4.get(host_tag, total_metrics_path, my_params));
+}
+
+void check_json(const vespalib::string &expect_json, const vespalib::string &actual_json) {
+ Slime expect_slime;
+ Slime actual_slime;
+ EXPECT_TRUE(slime::JsonFormat::decode(expect_json, expect_slime) > 0);
+ EXPECT_TRUE(slime::JsonFormat::decode(actual_json, actual_slime) > 0);
+ EXPECT_EQUAL(expect_slime, actual_slime);
+}
+
+TEST("require that generic state can be explored") {
+ vespalib::string json_model =
+ "{"
+ " foo: 'bar',"
+ " cnt: 123,"
+ " engine: {"
+ " up: 'yes',"
+ " stats: {"
+ " latency: 5,"
+ " qps: 100"
+ " }"
+ " },"
+ " list: {"
+ " one: {"
+ " size: {"
+ " value: 1"
+ " }"
+ " },"
+ " two: {"
+ " size: 2"
+ " }"
+ " }"
+ "}";
+ vespalib::string json_root =
+ "{"
+ " full: true,"
+ " foo: 'bar',"
+ " cnt: 123,"
+ " engine: {"
+ " up: 'yes',"
+ " url: 'http://HOST/state/v1/engine'"
+ " },"
+ " list: {"
+ " one: {"
+ " size: {"
+ " value: 1,"
+ " url: 'http://HOST/state/v1/list/one/size'"
+ " }"
+ " },"
+ " two: {"
+ " size: 2,"
+ " url: 'http://HOST/state/v1/list/two'"
+ " }"
+ " }"
+ "}";
+ vespalib::string json_engine =
+ "{"
+ " full: true,"
+ " up: 'yes',"
+ " stats: {"
+ " latency: 5,"
+ " qps: 100,"
+ " url: 'http://HOST/state/v1/engine/stats'"
+ " }"
+ "}";
+ vespalib::string json_engine_stats =
+ "{"
+ " full: true,"
+ " latency: 5,"
+ " qps: 100"
+ "}";
+ vespalib::string json_list =
+ "{"
+ " one: {"
+ " size: {"
+ " value: 1,"
+ " url: 'http://HOST/state/v1/list/one/size'"
+ " }"
+ " },"
+ " two: {"
+ " size: 2,"
+ " url: 'http://HOST/state/v1/list/two'"
+ " }"
+ "}";
+ vespalib::string json_list_one =
+ "{"
+ " size: {"
+ " value: 1,"
+ " url: 'http://HOST/state/v1/list/one/size'"
+ " }"
+ "}";
+ vespalib::string json_list_one_size = "{ full: true, value: 1 }";
+ vespalib::string json_list_two = "{ full: true, size: 2 }";
+ //-------------------------------------------------------------------------
+ Slime slime_state;
+ EXPECT_TRUE(slime::JsonFormat::decode(json_model, slime_state) > 0);
+ SlimeExplorer slime_explorer(slime_state.get());
+ GenericStateHandler state_handler(short_root_path, slime_explorer);
+ EXPECT_EQUAL("", state_handler.get(host_tag, unknown_path, empty_params));
+ EXPECT_EQUAL("", state_handler.get(host_tag, unknown_state_path, empty_params));
+ check_json(json_root, state_handler.get(host_tag, root_path, empty_params));
+ check_json(json_engine, state_handler.get(host_tag, root_path + "engine", empty_params));
+ check_json(json_engine_stats, state_handler.get(host_tag, root_path + "engine/stats", empty_params));
+ check_json(json_list, state_handler.get(host_tag, root_path + "list", empty_params));
+ check_json(json_list_one, state_handler.get(host_tag, root_path + "list/one", empty_params));
+ check_json(json_list_one_size, state_handler.get(host_tag, root_path + "list/one/size", empty_params));
+ check_json(json_list_two, state_handler.get(host_tag, root_path + "list/two", empty_params));
+}
+
+TEST_MAIN_WITH_PROCESS_PROXY() { TEST_RUN_ALL(); }
diff --git a/staging_vespalib/src/tests/stllike/.gitignore b/staging_vespalib/src/tests/stllike/.gitignore
new file mode 100644
index 00000000000..268b9e88393
--- /dev/null
+++ b/staging_vespalib/src/tests/stllike/.gitignore
@@ -0,0 +1,6 @@
+.depend
+Makefile
+lrucache_test
+cache_test
+staging_vespalib_cache_test_app
+staging_vespalib_lrucache_test_app
diff --git a/staging_vespalib/src/tests/stllike/CMakeLists.txt b/staging_vespalib/src/tests/stllike/CMakeLists.txt
new file mode 100644
index 00000000000..690582676ad
--- /dev/null
+++ b/staging_vespalib/src/tests/stllike/CMakeLists.txt
@@ -0,0 +1,15 @@
+# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(staging_vespalib_lrucache_test_app
+ SOURCES
+ lrucache.cpp
+ DEPENDS
+ staging_vespalib
+)
+vespa_add_test(NAME staging_vespalib_lrucache_test_app COMMAND staging_vespalib_lrucache_test_app)
+vespa_add_executable(staging_vespalib_cache_test_app
+ SOURCES
+ cache_test.cpp
+ DEPENDS
+ staging_vespalib
+)
+vespa_add_test(NAME staging_vespalib_cache_test_app COMMAND staging_vespalib_cache_test_app)
diff --git a/staging_vespalib/src/tests/stllike/DESC b/staging_vespalib/src/tests/stllike/DESC
new file mode 100644
index 00000000000..ec13a79916b
--- /dev/null
+++ b/staging_vespalib/src/tests/stllike/DESC
@@ -0,0 +1 @@
+hash test. Take a look at hash.cpp for details.
diff --git a/staging_vespalib/src/tests/stllike/FILES b/staging_vespalib/src/tests/stllike/FILES
new file mode 100644
index 00000000000..eb3794b4a28
--- /dev/null
+++ b/staging_vespalib/src/tests/stllike/FILES
@@ -0,0 +1,3 @@
+hash.cpp
+uniq_by_sort_map_hash.cpp
+lrucache.cpp
diff --git a/staging_vespalib/src/tests/stllike/avl.cpp b/staging_vespalib/src/tests/stllike/avl.cpp
new file mode 100644
index 00000000000..53df03319d7
--- /dev/null
+++ b/staging_vespalib/src/tests/stllike/avl.cpp
@@ -0,0 +1,265 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/fastos/fastos.h>
+#include <vespa/log/log.h>
+LOG_SETUP("memory_test");
+#include <vespa/vespalib/testkit/testapp.h>
+#include <vespalib/stllike/avl_set.h>
+#include <vespa/vespalib/stllike/avl_map.h>
+
+using namespace vespalib;
+using std::make_pair;
+
+class Test : public TestApp
+{
+public:
+ int Main();
+ void testAvlTreeSet();
+ void testAvlTreeSet2();
+ void testAvlTreeMap();
+ void testAvlTreeFind();
+};
+
+int
+Test::Main()
+{
+ TEST_INIT("avl_test");
+ testAvlTreeSet();
+ testAvlTreeSet2();
+ testAvlTreeMap();
+ testAvlTreeFind();
+ TEST_DONE();
+}
+
+namespace {
+ struct Foo {
+ int i;
+
+ Foo() : i(0) {}
+ Foo(int i_) : i(i_) {}
+
+ bool operator<(const Foo& f) const
+ { return (i < f.i); }
+ friend std::ostream & operator << (std::ostream & os, const Foo & f) { return os << f.i; }
+ };
+}
+
+void Test::testAvlTreeSet2()
+{
+ const size_t testSize(2000);
+ avl_set<Foo> set(100);
+ // Verfify start conditions.
+ EXPECT_TRUE(set.size() == 0);
+ EXPECT_TRUE(set.begin() == set.end());
+ EXPECT_TRUE(set.find(7) == set.end());
+ // Insert one element
+ set.insert(Foo(7));
+ EXPECT_TRUE(set.size() == 1);
+ EXPECT_TRUE(set.begin() != set.end());
+ EXPECT_TRUE(set.find(Foo(7)) != set.end());
+ EXPECT_TRUE(*set.find(Foo(7)) == Foo(7));
+ EXPECT_TRUE(set.find(Foo(8)) == set.end());
+ // erase non existing
+ set.erase(Foo(8));
+ EXPECT_TRUE(set.size() == 1);
+ EXPECT_TRUE(set.begin() != set.end());
+ EXPECT_TRUE(set.find(Foo(7)) != set.end());
+ EXPECT_TRUE(*set.find(Foo(7)) == Foo(7));
+ EXPECT_TRUE(set.find(Foo(8)) == set.end());
+ // erase existing
+ set.erase(Foo(7));
+ EXPECT_TRUE(set.size() == 0);
+ EXPECT_TRUE(set.begin() == set.end());
+ EXPECT_TRUE(set.find(Foo(7)) == set.end());
+ for (size_t i(0); i < testSize; i++) {
+ set.insert(Foo(i));
+ avl_set<Foo, Foo::avl>::iterator it = set.find(Foo(i));
+ ASSERT_TRUE(it != set.end());
+ for (size_t j=0; j < i; j++) {
+ it = set.find(Foo(j));
+ ASSERT_TRUE(it != set.end());
+ }
+ }
+ EXPECT_TRUE(set.size() == testSize);
+ avl_set<Foo, Foo::avl>::iterator it = set.find(Foo((testSize/2)-1));
+ ASSERT_TRUE(it != set.end());
+ EXPECT_EQUAL(*it, Foo((testSize/2)-1));
+ for (size_t i(0); i < testSize/2; i++) {
+ set.erase(Foo(i*2));
+ }
+ ASSERT_TRUE(it != set.end());
+ EXPECT_EQUAL(*it, Foo((testSize/2)-1));
+ EXPECT_TRUE(set.find(Foo(testSize/2)) == set.end());
+ EXPECT_TRUE(set.size() == testSize/2);
+ for (size_t i(0); i < testSize; i++) {
+ set.insert(Foo(i));
+ }
+ EXPECT_EQUAL(set.size(), testSize);
+ EXPECT_TRUE(*set.find(Foo(7)) == Foo(7));
+ EXPECT_TRUE(*set.find(Foo(0)) == Foo(0));
+ EXPECT_TRUE(*set.find(Foo(1)) == Foo(1));
+ EXPECT_TRUE(*set.find(Foo(testSize-1)) == Foo(testSize-1));
+ EXPECT_TRUE(set.find(Foo(testSize)) == set.end());
+
+ set.clear();
+
+ EXPECT_EQUAL(set.size(), 0u);
+ EXPECT_TRUE(set.find(Foo(7)) == set.end());
+}
+
+void Test::testAvlTreeSet()
+{
+ avl_set<int> set(1000);
+ // Verfify start conditions.
+ EXPECT_TRUE(set.size() == 0);
+ EXPECT_TRUE(set.begin() == set.end());
+ EXPECT_TRUE(set.find(7) == set.end());
+ // Insert one element
+ set.insert(7);
+ EXPECT_TRUE(set.size() == 1);
+ EXPECT_TRUE(set.begin() != set.end());
+ EXPECT_TRUE(set.find(7) != set.end());
+ EXPECT_TRUE(*set.find(7) == 7);
+ EXPECT_TRUE(set.find(8) == set.end());
+ // erase non existing
+ set.erase(8);
+ EXPECT_TRUE(set.size() == 1);
+ EXPECT_TRUE(set.begin() != set.end());
+ EXPECT_TRUE(set.find(7) != set.end());
+ EXPECT_TRUE(*set.find(7) == 7);
+ EXPECT_TRUE(set.find(8) == set.end());
+ // erase existing
+ set.erase(7);
+ EXPECT_TRUE(set.size() == 0);
+ EXPECT_TRUE(set.begin() == set.end());
+ EXPECT_TRUE(set.find(7) == set.end());
+ for (size_t i(0); i < 10000; i++) {
+ set.insert(i);
+ }
+ EXPECT_TRUE(set.size() == 10000);
+ for (size_t i(0); i < 5000; i++) {
+ set.erase(i*2);
+ }
+ EXPECT_TRUE(*set.find(4999) == 4999);
+ EXPECT_TRUE(set.find(5000) == set.end());
+ EXPECT_TRUE(set.size() == 5000);
+ for (size_t i(0); i < 10000; i++) {
+ set.insert(i);
+ }
+ EXPECT_EQUAL(set.size(), 10000u);
+ EXPECT_TRUE(*set.find(7) == 7);
+ EXPECT_TRUE(*set.find(0) == 0);
+ EXPECT_TRUE(*set.find(1) == 1);
+ EXPECT_TRUE(*set.find(9999) == 9999);
+ EXPECT_TRUE(set.find(10000) == set.end());
+
+ set.clear();
+
+ EXPECT_EQUAL(set.size(), 0u);
+ EXPECT_TRUE(set.find(7) == set.end());
+}
+
+void Test::testAvlTreeMap()
+{
+ avl_map<int, int> set(1000);
+ // Verfify start conditions.
+ EXPECT_TRUE(set.size() == 0);
+ EXPECT_TRUE(set.begin() == set.end());
+ EXPECT_TRUE(set.find(7) == set.end());
+ // Insert one element
+ set.insert(make_pair(7, 70));
+ EXPECT_TRUE(set.size() == 1);
+ EXPECT_TRUE(set.begin() != set.end());
+ EXPECT_TRUE(set.find(7) != set.end());
+ EXPECT_TRUE(set.find(7)->first == 7);
+ EXPECT_TRUE(set.find(7)->second == 70);
+ EXPECT_TRUE(set.find(8) == set.end());
+ // erase non existing
+ set.erase(8);
+ EXPECT_TRUE(set.size() == 1);
+ EXPECT_TRUE(set.begin() != set.end());
+ EXPECT_TRUE(set.find(7) != set.end());
+ EXPECT_TRUE(set.find(7)->first == 7);
+ EXPECT_TRUE(set.find(7)->second == 70);
+ EXPECT_TRUE(set.find(8) == set.end());
+ // erase existing
+ set.erase(7);
+ EXPECT_TRUE(set.size() == 0);
+ EXPECT_TRUE(set.begin() == set.end());
+ EXPECT_TRUE(set.find(7) == set.end());
+ for (size_t i(0); i < 10000; i++) {
+ set.insert(make_pair(i,i*10));
+ }
+ EXPECT_TRUE(set.size() == 10000);
+ for (size_t i(0); i < 5000; i++) {
+ set.erase(i*2);
+ }
+ EXPECT_TRUE(set.find(4999)->first == 4999);
+ EXPECT_TRUE(set.find(4999)->second == 49990);
+ EXPECT_TRUE(set.find(5000) == set.end());
+ EXPECT_TRUE(set.size() == 5000);
+ for (size_t i(0); i < 10000; i++) {
+ set.insert(make_pair(i,i*10));
+ }
+ EXPECT_EQUAL(set.size(), 10000u);
+ EXPECT_TRUE(set.find(7)->first == 7);
+ EXPECT_TRUE(set.find(7)->second == 70);
+ EXPECT_TRUE(set.find(0)->first == 0);
+ EXPECT_TRUE(set.find(0)->second == 0);
+ EXPECT_TRUE(set.find(1)->first == 1);
+ EXPECT_TRUE(set.find(1)->second == 10);
+ EXPECT_TRUE(set.find(9999)->first == 9999);
+ EXPECT_TRUE(set.find(9999)->second == 99990);
+ EXPECT_TRUE(set.find(10000) == set.end());
+
+ avl_map<int, int> set2(7);
+ set.swap(set2);
+ EXPECT_EQUAL(set2.size(), 10000u);
+ EXPECT_TRUE(set2.find(7)->first == 7);
+ EXPECT_TRUE(set2.find(7)->second == 70);
+
+ EXPECT_EQUAL(set.size(), 0u);
+ EXPECT_TRUE(set.find(7) == set.end());
+ for (int i=0; i < 100; i++) {
+ set.insert(make_pair(i,i*10));
+ }
+ for (int i=0; i < 100; i++) {
+ EXPECT_TRUE(set.find(i)->second == i*10);
+ }
+
+ avl_map<int, int> set3;
+ set3.insert(set.begin(), set.end());
+ for (int i=0; i < 100; i++) {
+ EXPECT_EQUAL(i*10, set.find(i)->second);
+ }
+}
+
+class S {
+public:
+ explicit S(uint64_t l=0) : _a(l&0xfffffffful), _b(l>>32) { }
+ uint32_t avl() const { return _a; }
+ uint32_t a() const { return _a; }
+ friend bool operator == (const S & a, const S & b) { return a._a == b._a && a._b == b._b; }
+private:
+ uint32_t _a, _b;
+};
+
+struct myavl {
+ size_t operator() (const S & arg) const { return arg.avl(); }
+};
+
+struct myextract {
+ uint32_t operator() (const S & arg) const { return arg.a(); }
+};
+
+void Test::testAvlTreeFind()
+{
+ avl_set<S, myavl> set(1000);
+ for (size_t i(0); i < 10000; i++) {
+ set.insert(S(i));
+ }
+ EXPECT_TRUE(*set.find(S(1)) == S(1));
+ avl_set<S, myavl>::iterator cit = set.find<uint32_t, myextract, vespalib::avl<uint32_t>, std::equal_to<uint32_t> >(7);
+ EXPECT_TRUE(*cit == S(7));
+}
+
+TEST_APPHOOK(Test)
diff --git a/staging_vespalib/src/tests/stllike/cache_test.cpp b/staging_vespalib/src/tests/stllike/cache_test.cpp
new file mode 100644
index 00000000000..288ef367be4
--- /dev/null
+++ b/staging_vespalib/src/tests/stllike/cache_test.cpp
@@ -0,0 +1,165 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/fastos/fastos.h>
+#include <vespa/log/log.h>
+LOG_SETUP("cache_test");
+#include <vespa/vespalib/testkit/testapp.h>
+#include <vespa/vespalib/stllike/string.h>
+#include <vespa/vespalib/stllike/cache.h>
+#include <map>
+
+using namespace vespalib;
+
+template<typename K, typename V>
+class Map : public std::map<K, V> {
+ typedef typename std::map<K, V>::const_iterator const_iterator;
+ typedef std::map<K, V> M;
+public:
+ bool read(const K & k, V & v) const {
+ const_iterator found = M::find(k);
+ bool ok(found != this->end());
+ if (ok) {
+ v = found->second;
+ }
+ return ok;
+ }
+ void write(const K & k, const V & v) {
+ (*this)[k] = v;
+ }
+ void erase(const K & k) {
+ M::erase(k);
+ }
+};
+
+class Test : public TestApp
+{
+public:
+ int Main();
+private:
+ typedef LruParam<uint32_t, string> P;
+ typedef Map<uint32_t, string> B;
+ void testCache();
+ void testCacheSize();
+ void testCacheSizeDeep();
+ void testCacheEntriesHonoured();
+ void testCacheMaxSizeHonoured();
+ void testThatMultipleRemoveOnOverflowIsFine();
+};
+
+int
+Test::Main()
+{
+ TEST_INIT("cache_test");
+ testCache();
+ testCacheSize();
+ testCacheSizeDeep();
+ testCacheEntriesHonoured();
+ testCacheMaxSizeHonoured();
+ testThatMultipleRemoveOnOverflowIsFine();
+ TEST_DONE();
+}
+
+void Test::testCache()
+{
+ B m;
+ cache< CacheParam<P, B> > cache(m, -1);
+ // Verfify start conditions.
+ EXPECT_TRUE(cache.size() == 0);
+ EXPECT_TRUE( ! cache.hasKey(1) );
+ cache.write(1, "First inserted string");
+ EXPECT_TRUE( cache.hasKey(1) );
+ m[2] = "String inserted beneath";
+ EXPECT_TRUE( ! cache.hasKey(2) );
+ EXPECT_EQUAL( cache.read(2), "String inserted beneath");
+ EXPECT_TRUE( cache.hasKey(2) );
+ cache.erase(1);
+ EXPECT_TRUE( ! cache.hasKey(1) );
+ EXPECT_TRUE(cache.size() == 1);
+}
+
+void Test::testCacheSize()
+{
+ B m;
+ cache< CacheParam<P, B> > cache(m, -1);
+ cache.write(1, "10 bytes string");
+ EXPECT_EQUAL(80u, cache.sizeBytes());
+}
+
+void Test::testCacheSizeDeep()
+{
+ B m;
+ cache< CacheParam<P, B, zero<uint32_t>, size<string> > > cache(m, -1);
+ cache.write(1, "15 bytes string");
+ EXPECT_EQUAL(95u, cache.sizeBytes());
+}
+
+void Test::testCacheEntriesHonoured()
+{
+ B m;
+ cache< CacheParam<P, B, zero<uint32_t>, size<string> > > cache(m, -1);
+ cache.maxElements(1);
+ cache.write(1, "15 bytes string");
+ EXPECT_EQUAL(1u, cache.size());
+ EXPECT_EQUAL(95u, cache.sizeBytes());
+ cache.write(2, "16 bytes stringg");
+ EXPECT_EQUAL(1u, cache.size());
+ EXPECT_TRUE( cache.hasKey(2) );
+ EXPECT_FALSE( cache.hasKey(1) );
+ EXPECT_EQUAL(96u, cache.sizeBytes());
+}
+
+void Test::testCacheMaxSizeHonoured()
+{
+ B m;
+ cache< CacheParam<P, B, zero<uint32_t>, size<string> > > cache(m, 200);
+ cache.write(1, "15 bytes string");
+ EXPECT_EQUAL(1u, cache.size());
+ EXPECT_EQUAL(95u, cache.sizeBytes());
+ cache.write(2, "16 bytes stringg");
+ EXPECT_EQUAL(2u, cache.size());
+ EXPECT_EQUAL(191u, cache.sizeBytes());
+ cache.write(3, "17 bytes stringgg");
+ EXPECT_EQUAL(3u, cache.size());
+ EXPECT_EQUAL(288u, cache.sizeBytes());
+ cache.write(4, "18 bytes stringggg");
+ EXPECT_EQUAL(3u, cache.size());
+ EXPECT_EQUAL(291u, cache.sizeBytes());
+}
+
+void Test::testThatMultipleRemoveOnOverflowIsFine()
+{
+ B m;
+ cache< CacheParam<P, B, zero<uint32_t>, size<string> > > cache(m, 2000);
+
+ for (size_t j(0); j < 5; j++) {
+ for (size_t i(0); cache.size() == i; i++) {
+ cache.write(j*53+i, "a");
+ }
+ }
+ EXPECT_EQUAL(25u, cache.size());
+ EXPECT_EQUAL(2025u, cache.sizeBytes());
+ EXPECT_FALSE( cache.hasKey(0) );
+ string ls("long string aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
+ string vls=ls+ls+ls+ls+ls+ls;
+ cache.write(53+5, ls);
+ EXPECT_EQUAL(25u, cache.size());
+ EXPECT_EQUAL(2498u, cache.sizeBytes());
+ EXPECT_FALSE( cache.hasKey(1) );
+ cache.write(53*7+5, ls);
+ EXPECT_EQUAL(19u, cache.size());
+ EXPECT_EQUAL(2485u, cache.sizeBytes());
+ EXPECT_FALSE( cache.hasKey(2) );
+ cache.write(53*8+5, vls);
+ EXPECT_EQUAL(14u, cache.size());
+ EXPECT_EQUAL(4923u, cache.sizeBytes());
+ cache.write(53*9+6, vls);
+ EXPECT_EQUAL(1u, cache.size());
+ EXPECT_EQUAL(2924u, cache.sizeBytes());
+}
+
+
+TEST_APPHOOK(Test)
diff --git a/staging_vespalib/src/tests/stllike/lrucache.cpp b/staging_vespalib/src/tests/stllike/lrucache.cpp
new file mode 100644
index 00000000000..de5bcb8a365
--- /dev/null
+++ b/staging_vespalib/src/tests/stllike/lrucache.cpp
@@ -0,0 +1,192 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/fastos/fastos.h>
+#include <vespa/log/log.h>
+LOG_SETUP("lrucache_test");
+#include <vespa/vespalib/testkit/testapp.h>
+#include <vespa/vespalib/stllike/string.h>
+#include <vespa/vespalib/stllike/lrucache_map.h>
+
+using namespace vespalib;
+
+TEST("testCache") {
+ lrucache_map< LruParam<int, string> > cache(7);
+ // Verfify start conditions.
+ EXPECT_TRUE(cache.size() == 0);
+ cache.insert(1, "First inserted string");
+ EXPECT_TRUE(cache.verifyInternals());
+ EXPECT_TRUE(cache.size() == 1);
+ EXPECT_TRUE(cache.hasKey(1));
+ cache.insert(2, "Second inserted string");
+ EXPECT_TRUE(cache.verifyInternals());
+ EXPECT_TRUE(cache.size() == 2);
+ EXPECT_TRUE(cache.hasKey(1));
+ EXPECT_TRUE(cache.hasKey(2));
+ cache.insert(3, "Third inserted string");
+ EXPECT_TRUE(cache.verifyInternals());
+ EXPECT_TRUE(cache.size() == 3);
+ EXPECT_TRUE(cache.hasKey(1));
+ EXPECT_TRUE(cache.hasKey(2));
+ EXPECT_TRUE(cache.hasKey(3));
+ cache.insert(4, "Fourth inserted string");
+ EXPECT_TRUE(cache.verifyInternals());
+ EXPECT_TRUE(cache.size() == 4);
+ EXPECT_TRUE(cache.hasKey(1));
+ EXPECT_TRUE(cache.hasKey(2));
+ EXPECT_TRUE(cache.hasKey(3));
+ EXPECT_TRUE(cache.hasKey(4));
+ cache.insert(5, "Fifth inserted string");
+ EXPECT_TRUE(cache.verifyInternals());
+ EXPECT_TRUE(cache.size() == 5);
+ EXPECT_TRUE(cache.hasKey(1));
+ EXPECT_TRUE(cache.hasKey(2));
+ EXPECT_TRUE(cache.hasKey(3));
+ EXPECT_TRUE(cache.hasKey(4));
+ EXPECT_TRUE(cache.hasKey(5));
+ cache.insert(6, "Sixt inserted string");
+ EXPECT_TRUE(cache.verifyInternals());
+ EXPECT_TRUE(cache.size() == 6);
+ EXPECT_TRUE(cache.hasKey(1));
+ EXPECT_TRUE(cache.hasKey(2));
+ EXPECT_TRUE(cache.hasKey(3));
+ EXPECT_TRUE(cache.hasKey(4));
+ EXPECT_TRUE(cache.hasKey(5));
+ EXPECT_TRUE(cache.hasKey(6));
+ cache.insert(7, "Seventh inserted string");
+ EXPECT_TRUE(cache.verifyInternals());
+ EXPECT_EQUAL(cache.size(), 7u);
+ EXPECT_TRUE(cache.hasKey(1));
+ EXPECT_TRUE(cache.hasKey(2));
+ EXPECT_TRUE(cache.hasKey(3));
+ EXPECT_TRUE(cache.hasKey(4));
+ EXPECT_TRUE(cache.hasKey(5));
+ EXPECT_TRUE(cache.hasKey(6));
+ EXPECT_TRUE(cache.hasKey(7));
+ cache.insert(8, "Eighth inserted string");
+ EXPECT_TRUE(cache.verifyInternals());
+ EXPECT_EQUAL(cache.size(), 7u);
+ EXPECT_TRUE(cache.hasKey(2));
+ EXPECT_TRUE(cache.hasKey(3));
+ EXPECT_TRUE(cache.hasKey(4));
+ EXPECT_TRUE(cache.hasKey(5));
+ EXPECT_TRUE(cache.hasKey(6));
+ EXPECT_TRUE(cache.hasKey(7));
+ EXPECT_TRUE(cache.hasKey(8));
+ cache.insert(15, "Eighth inserted string");
+ EXPECT_TRUE(cache.verifyInternals());
+ EXPECT_EQUAL(cache.size(), 7u);
+ EXPECT_TRUE(cache.hasKey(3));
+ EXPECT_TRUE(cache.hasKey(4));
+ EXPECT_TRUE(cache.hasKey(5));
+ EXPECT_TRUE(cache.hasKey(6));
+ EXPECT_TRUE(cache.hasKey(7));
+ EXPECT_TRUE(cache.hasKey(8));
+ EXPECT_TRUE(cache.hasKey(15));
+ // Test get and erase
+ cache.get(3);
+ EXPECT_TRUE(cache.verifyInternals());
+ cache.erase(3);
+ EXPECT_TRUE(cache.verifyInternals());
+ EXPECT_TRUE(!cache.hasKey(3));
+}
+
+typedef std::shared_ptr<std::string> MyKey;
+typedef std::shared_ptr<std::string> MyData;
+
+struct SharedEqual : public std::binary_function<MyKey, MyKey, bool> {
+ bool operator()(const MyKey & a, const MyKey & b) {
+ return ((*a) == (*b));
+ }
+};
+
+struct SharedHash {
+ size_t operator() (const MyKey & arg) const { return arg->size(); }
+};
+
+
+TEST("testCacheInsertOverResize") {
+ typedef vespalib::LinkedPtr<std::string> LS;
+ typedef lrucache_map< LruParam<int, LS> > Cache;
+
+ Cache cache(100);
+ size_t sum(0);
+ for (size_t i(0); i < cache.capacity()*10; i++) {
+ LS s(new std::string("abc"));
+ cache[random()] = s;
+ sum += strlen(s->c_str());
+ EXPECT_EQUAL(strlen(s->c_str()), s->size());
+ }
+ EXPECT_EQUAL(sum, cache.capacity()*10*3);
+}
+
+TEST("testCacheErase") {
+ lrucache_map< LruParam<MyKey, MyData, SharedHash, SharedEqual> > cache(4);
+
+ MyData d(new std::string("foo"));
+ MyKey k(new std::string("barlol"));
+ // Verfify start conditions.
+ EXPECT_TRUE(cache.size() == 0);
+ EXPECT_TRUE(d.use_count() == 1);
+ EXPECT_TRUE(k.use_count() == 1);
+ cache.insert(k, d);
+ EXPECT_TRUE(d.use_count() == 2);
+ EXPECT_TRUE(k.use_count() == 2);
+ cache.erase(k);
+ EXPECT_TRUE(d.use_count() == 1);
+ EXPECT_TRUE(k.use_count() == 1);
+}
+
+TEST("testCacheIterator") {
+ typedef lrucache_map< LruParam<int, string> > Cache;
+ Cache cache(3);
+ cache.insert(1, "first");
+ cache.insert(2, "second");
+ cache.insert(3, "third");
+ Cache::iterator it(cache.begin());
+ Cache::iterator mt(cache.end());
+ ASSERT_TRUE(it != mt);
+ ASSERT_EQUAL("third", *it);
+ ASSERT_TRUE(it != mt);
+ ASSERT_EQUAL("second", *(++it));
+ ASSERT_TRUE(it != mt);
+ ASSERT_EQUAL("second", *it++);
+ ASSERT_TRUE(it != mt);
+ ASSERT_EQUAL("first", *it);
+ ASSERT_TRUE(it != mt);
+ it++;
+ ASSERT_TRUE(it == mt);
+ cache.insert(4, "fourth");
+ Cache::iterator it2(cache.begin());
+ Cache::iterator it3(cache.begin());
+ ASSERT_EQUAL("fourth", *it2);
+ ASSERT_TRUE(it2 == it3);
+ it2++;
+ ASSERT_TRUE(it2 != it3);
+ it2++;
+ it2++;
+ ASSERT_TRUE(it2 == mt);
+ Cache::iterator it4 = cache.erase(it3);
+ ASSERT_EQUAL("third", *it4);
+ ASSERT_EQUAL("third", *cache.begin());
+ Cache::iterator it5(cache.erase(cache.end()));
+ ASSERT_TRUE(it5 == cache.end());
+}
+
+TEST("testCacheIteratorErase") {
+ typedef lrucache_map< LruParam<int, string> > Cache;
+ Cache cache(3);
+ cache.insert(1, "first");
+ cache.insert(8, "second");
+ cache.insert(15, "third");
+ cache.insert(15, "third");
+ cache.insert(8, "second");
+ cache.insert(1, "first");
+ Cache::iterator it(cache.begin());
+ ASSERT_EQUAL("first", *it);
+ it++;
+ ASSERT_EQUAL("second", *it);
+ it = cache.erase(it);
+ ASSERT_EQUAL("third", *it);
+ cache.erase(it);
+}
+
+TEST_MAIN() { TEST_RUN_ALL(); }
diff --git a/staging_vespalib/src/tests/timer/.gitignore b/staging_vespalib/src/tests/timer/.gitignore
new file mode 100644
index 00000000000..9031e40152a
--- /dev/null
+++ b/staging_vespalib/src/tests/timer/.gitignore
@@ -0,0 +1 @@
+staging_vespalib_timer_test_app
diff --git a/staging_vespalib/src/tests/timer/CMakeLists.txt b/staging_vespalib/src/tests/timer/CMakeLists.txt
new file mode 100644
index 00000000000..ab16cc236c4
--- /dev/null
+++ b/staging_vespalib/src/tests/timer/CMakeLists.txt
@@ -0,0 +1,8 @@
+# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(staging_vespalib_timer_test_app
+ SOURCES
+ timer_test.cpp
+ DEPENDS
+ staging_vespalib
+)
+vespa_add_test(NAME staging_vespalib_timer_test_app COMMAND staging_vespalib_timer_test_app)
diff --git a/staging_vespalib/src/tests/timer/timer_test.cpp b/staging_vespalib/src/tests/timer/timer_test.cpp
new file mode 100644
index 00000000000..de2f081f48a
--- /dev/null
+++ b/staging_vespalib/src/tests/timer/timer_test.cpp
@@ -0,0 +1,60 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/fastos/fastos.h>
+#include <vespa/log/log.h>
+LOG_SETUP("timer_test");
+#include <vespa/vespalib/testkit/testapp.h>
+#include <vespa/vespalib/util/timer.h>
+#include <vespa/vespalib/util/executor.h>
+
+using namespace vespalib;
+using vespalib::Executor;
+typedef Executor::Task Task;
+
+class Test : public TestApp
+{
+public:
+ int Main();
+ void testScheduling();
+ void testReset();
+};
+
+class TestTask : public Task {
+private:
+ vespalib::CountDownLatch &_latch;
+public:
+ TestTask(vespalib::CountDownLatch & latch) : _latch(latch) { }
+ void run() { _latch.countDown(); }
+};
+
+int
+Test::Main()
+{
+ TEST_INIT("timer_test");
+ testScheduling();
+ testReset();
+ TEST_DONE();
+}
+
+void Test::testScheduling()
+{
+ vespalib::CountDownLatch latch1(3);
+ vespalib::CountDownLatch latch2(2);
+ Timer timer;
+ timer.scheduleAtFixedRate(Task::UP(new TestTask(latch1)), 0.1, 0.2);
+ timer.scheduleAtFixedRate(Task::UP(new TestTask(latch2)), 0.5, 0.5);
+ EXPECT_TRUE(latch1.await(60000));
+ EXPECT_TRUE(latch2.await(60000));
+}
+
+void Test::testReset()
+{
+ vespalib::CountDownLatch latch1(2);
+ Timer timer;
+ timer.scheduleAtFixedRate(Task::UP(new TestTask(latch1)), 2.0, 3.0);
+ timer.reset();
+ EXPECT_TRUE(!latch1.await(3000));
+ timer.scheduleAtFixedRate(Task::UP(new TestTask(latch1)), 0.2, 0.3);
+ EXPECT_TRUE(latch1.await(60000));
+}
+
+TEST_APPHOOK(Test)
diff --git a/staging_vespalib/src/tests/trace/.gitignore b/staging_vespalib/src/tests/trace/.gitignore
new file mode 100644
index 00000000000..14ed55a124e
--- /dev/null
+++ b/staging_vespalib/src/tests/trace/.gitignore
@@ -0,0 +1 @@
+staging_vespalib_trace_test_app
diff --git a/staging_vespalib/src/tests/trace/CMakeLists.txt b/staging_vespalib/src/tests/trace/CMakeLists.txt
new file mode 100644
index 00000000000..cb381733bff
--- /dev/null
+++ b/staging_vespalib/src/tests/trace/CMakeLists.txt
@@ -0,0 +1,8 @@
+# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(staging_vespalib_trace_test_app
+ SOURCES
+ trace.cpp
+ DEPENDS
+ staging_vespalib
+)
+vespa_add_test(NAME staging_vespalib_trace_test_app COMMAND staging_vespalib_trace_test_app)
diff --git a/staging_vespalib/src/tests/trace/trace.cpp b/staging_vespalib/src/tests/trace/trace.cpp
new file mode 100644
index 00000000000..a7896d43338
--- /dev/null
+++ b/staging_vespalib/src/tests/trace/trace.cpp
@@ -0,0 +1,110 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/fastos/fastos.h>
+#include <vespa/log/log.h>
+LOG_SETUP("trace_test");
+#include <vespa/vespalib/testkit/test_kit.h>
+#include <vespa/vespalib/trace/tracenode.h>
+#include <vespa/vespalib/trace/slime_trace_serializer.h>
+#include <vespa/vespalib/trace/slime_trace_deserializer.h>
+
+using namespace vespalib;
+using namespace vespalib::slime;
+
+TEST("that a single trace node is serialized") {
+ TraceNode node;
+ Slime slime;
+ SlimeTraceSerializer serializer(slime.setObject());
+ node.accept(serializer);
+ Inspector & i(slime.get());
+ EXPECT_TRUE(i["timestamp"].valid());
+ EXPECT_EQUAL(0l, i["timestamp"].asLong());
+ EXPECT_FALSE(i["payload"].valid());
+}
+
+TEST("that a trace node with children is serialized") {
+ TraceNode node;
+ node.addChild("foo", 1234);
+ node.addChild("bar", 1235);
+ Slime slime;
+ SlimeTraceSerializer serializer(slime.setObject());
+ node.accept(serializer);
+ Inspector & i(slime.get());
+ EXPECT_TRUE(i["timestamp"].valid());
+ EXPECT_EQUAL(0l, i["timestamp"].asLong());
+ EXPECT_TRUE(i["children"].valid());
+ Inspector & iBar(i["children"][0]);
+ Inspector & iFoo(i["children"][1]);
+ EXPECT_TRUE(iFoo.valid());
+ EXPECT_TRUE(iBar.valid());
+ EXPECT_EQUAL(1234, iFoo["timestamp"].asLong());
+ EXPECT_EQUAL("foo", iFoo["payload"].asString().make_string());
+ EXPECT_EQUAL(1235, iBar["timestamp"].asLong());
+ EXPECT_EQUAL("bar", iBar["payload"].asString().make_string());
+}
+
+TEST("that an empty root trace node can be deserialized") {
+ Slime slime;
+ Cursor & root(slime.setObject());
+ SlimeTraceDeserializer deserializer(root);
+ TraceNode node(deserializer.deserialize());
+ EXPECT_FALSE(node.hasNote());
+ EXPECT_EQUAL(0, node.getTimestamp());
+}
+
+
+TEST("that a single trace node can be deserialized") {
+ Slime slime;
+ Cursor & root(slime.setObject());
+ root.setLong("timestamp", 1234);
+ root.setString("payload", "hello");
+ SlimeTraceDeserializer deserializer(root);
+ TraceNode node(deserializer.deserialize());
+ EXPECT_EQUAL(1234, node.getTimestamp());
+ EXPECT_TRUE(node.hasNote());
+ EXPECT_EQUAL("hello", node.getNote());
+}
+
+TEST("that a trace node with children can be deserialized") {
+ Slime slime;
+ Cursor & root(slime.setObject());
+ Cursor & rootChildren(root.setArray("children"));
+ Cursor & foo(rootChildren.addObject());
+ foo.setLong("timestamp", 123);
+ Cursor &fooArray(foo.setArray("children"));
+ Cursor &foobar(fooArray.addObject());
+ foobar.setLong("timestamp", 45);
+ foobar.setString("payload", "world");
+ Cursor & bar(rootChildren.addObject());
+ bar.setLong("timestamp", 67);
+ bar.setString("payload", "!");
+
+ vespalib::slime::SimpleBuffer buf;
+ vespalib::slime::JsonFormat::encode(slime, buf, false);
+
+ SlimeTraceDeserializer deserializer(root);
+ TraceNode node(deserializer.deserialize());
+ EXPECT_FALSE(node.hasNote());
+ ASSERT_EQUAL(2u, node.getNumChildren());
+ TraceNode fooNode(node.getChild(0));
+ ASSERT_EQUAL(1u, fooNode.getNumChildren());
+ TraceNode fooBarNode(fooNode.getChild(0));
+ EXPECT_EQUAL("world", fooBarNode.getNote());
+ TraceNode barNode(node.getChild(1));
+ EXPECT_EQUAL("!", barNode.getNote());
+ ASSERT_EQUAL(0u, barNode.getNumChildren());
+}
+
+TEST("test serialization and deserialization") {
+ TraceNode root;
+ root.addChild("foo", 45);
+ root.addChild("bar");
+ root.addChild(TraceNode());
+ Slime slime;
+ SlimeTraceSerializer s(slime.setObject());
+ root.accept(s);
+ SlimeTraceDeserializer d(slime.get());
+ TraceNode root2(d.deserialize());
+ ASSERT_EQUAL(3u, root2.getNumChildren());
+}
+
+TEST_MAIN() { TEST_RUN_ALL(); }
diff --git a/staging_vespalib/src/tests/util/process_memory_stats/.gitignore b/staging_vespalib/src/tests/util/process_memory_stats/.gitignore
new file mode 100644
index 00000000000..e32e9f22dd3
--- /dev/null
+++ b/staging_vespalib/src/tests/util/process_memory_stats/.gitignore
@@ -0,0 +1,2 @@
+mapfile
+staging_vespalib_process_memory_stats_test_app
diff --git a/staging_vespalib/src/tests/util/process_memory_stats/CMakeLists.txt b/staging_vespalib/src/tests/util/process_memory_stats/CMakeLists.txt
new file mode 100644
index 00000000000..a9c23944575
--- /dev/null
+++ b/staging_vespalib/src/tests/util/process_memory_stats/CMakeLists.txt
@@ -0,0 +1,8 @@
+# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(staging_vespalib_process_memory_stats_test_app
+ SOURCES
+ process_memory_stats_test.cpp
+ DEPENDS
+ staging_vespalib
+)
+vespa_add_test(NAME staging_vespalib_process_memory_stats_test_app COMMAND sh process_memory_stats_test.sh)
diff --git a/staging_vespalib/src/tests/util/process_memory_stats/DESC b/staging_vespalib/src/tests/util/process_memory_stats/DESC
new file mode 100644
index 00000000000..3f2b5fb571e
--- /dev/null
+++ b/staging_vespalib/src/tests/util/process_memory_stats/DESC
@@ -0,0 +1 @@
+ProcessMemoryStats test. Take a look at process_memory_stats_test.cpp for details.
diff --git a/staging_vespalib/src/tests/util/process_memory_stats/FILES b/staging_vespalib/src/tests/util/process_memory_stats/FILES
new file mode 100644
index 00000000000..18ccce970a4
--- /dev/null
+++ b/staging_vespalib/src/tests/util/process_memory_stats/FILES
@@ -0,0 +1 @@
+process_memory_stats_test.cpp
diff --git a/staging_vespalib/src/tests/util/process_memory_stats/process_memory_stats_test.cpp b/staging_vespalib/src/tests/util/process_memory_stats/process_memory_stats_test.cpp
new file mode 100644
index 00000000000..43288d630cf
--- /dev/null
+++ b/staging_vespalib/src/tests/util/process_memory_stats/process_memory_stats_test.cpp
@@ -0,0 +1,79 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#include <vespa/fastos/fastos.h>
+#include <vespa/vespalib/testkit/test_kit.h>
+#include <vespa/vespalib/util/process_memory_stats.h>
+#include <iostream>
+#include <fstream>
+
+
+using namespace vespalib;
+
+namespace {
+
+std::string toString(const ProcessMemoryStats &stats)
+{
+ std::ostringstream os;
+ os << "Mapped("
+ << stats.getMappedVirt() << "," << stats.getMappedRss() <<
+ "), Anonymous("
+ << stats.getAnonymousVirt() << "," << stats.getAnonymousRss() << ")";
+ return os.str();
+}
+
+}
+
+TEST("Simple stats")
+{
+ ProcessMemoryStats stats(ProcessMemoryStats::create());
+ std::cout << toString(stats) << std::endl;
+ EXPECT_LESS(0u, stats.getMappedVirt());
+ EXPECT_LESS(0u, stats.getMappedRss());
+ EXPECT_LESS(0u, stats.getAnonymousVirt());
+ EXPECT_LESS(0u, stats.getAnonymousRss());
+}
+
+TEST("grow anonymous memory")
+{
+ ProcessMemoryStats stats1(ProcessMemoryStats::create());
+ std::cout << toString(stats1) << std::endl;
+ size_t mapLen = 64 * 1024;
+ void *mapAddr = mmap(nullptr, mapLen, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ EXPECT_NOT_EQUAL(reinterpret_cast<void *>(-1), mapAddr);
+ ProcessMemoryStats stats2(ProcessMemoryStats::create());
+ std::cout << toString(stats2) << std::endl;
+ EXPECT_LESS_EQUAL(stats1.getAnonymousVirt() + mapLen,
+ stats2.getAnonymousVirt());
+ memset(mapAddr, 1, mapLen);
+ ProcessMemoryStats stats3(ProcessMemoryStats::create());
+ std::cout << toString(stats3) << std::endl;
+ // Cannot check that resident grows if swap is enabled and system loaded
+ munmap(mapAddr, mapLen);
+}
+
+TEST("grow mapped memory")
+{
+ std::ofstream of("mapfile");
+ size_t mapLen = 64 * 1024;
+ std::vector<char> buf(mapLen, 4);
+ of.write(&buf[0], buf.size());
+ of.close();
+ int mapfileFileDescriptor = open("mapfile", O_RDONLY, 0666);
+ EXPECT_LESS_EQUAL(0, mapfileFileDescriptor);
+ ProcessMemoryStats stats1(ProcessMemoryStats::create());
+ std::cout << toString(stats1) << std::endl;
+ void *mapAddr = mmap(nullptr, mapLen, PROT_READ, MAP_SHARED,
+ mapfileFileDescriptor, 0);
+ EXPECT_NOT_EQUAL(reinterpret_cast<void *>(-1), mapAddr);
+ ProcessMemoryStats stats2(ProcessMemoryStats::create());
+ std::cout << toString(stats2) << std::endl;
+ EXPECT_LESS_EQUAL(stats1.getMappedVirt() + mapLen, stats2.getMappedVirt());
+ EXPECT_EQUAL(0, memcmp(mapAddr, &buf[0], mapLen));
+ ProcessMemoryStats stats3(ProcessMemoryStats::create());
+ std::cout << toString(stats3) << std::endl;
+ // Cannot check that resident grows if swap is enabled and system loaded
+ munmap(mapAddr, mapLen);
+}
+
+TEST_MAIN() { TEST_RUN_ALL(); }
diff --git a/staging_vespalib/src/tests/util/process_memory_stats/process_memory_stats_test.sh b/staging_vespalib/src/tests/util/process_memory_stats/process_memory_stats_test.sh
new file mode 100755
index 00000000000..57b6c8cb613
--- /dev/null
+++ b/staging_vespalib/src/tests/util/process_memory_stats/process_memory_stats_test.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+rm -f mapfile
+$VALGRIND ./staging_vespalib_process_memory_stats_test_app
+rm -f mapfile
diff --git a/staging_vespalib/src/tests/xmlserializable/.gitignore b/staging_vespalib/src/tests/xmlserializable/.gitignore
new file mode 100644
index 00000000000..d2910cb7407
--- /dev/null
+++ b/staging_vespalib/src/tests/xmlserializable/.gitignore
@@ -0,0 +1,4 @@
+*_test
+.depend
+Makefile
+staging_vespalib_xmlserializable_test_app
diff --git a/staging_vespalib/src/tests/xmlserializable/CMakeLists.txt b/staging_vespalib/src/tests/xmlserializable/CMakeLists.txt
new file mode 100644
index 00000000000..9d351cec4d9
--- /dev/null
+++ b/staging_vespalib/src/tests/xmlserializable/CMakeLists.txt
@@ -0,0 +1,8 @@
+# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(staging_vespalib_xmlserializable_test_app
+ SOURCES
+ xmlserializabletest.cpp
+ DEPENDS
+ staging_vespalib
+)
+vespa_add_test(NAME staging_vespalib_xmlserializable_test_app COMMAND staging_vespalib_xmlserializable_test_app)
diff --git a/staging_vespalib/src/tests/xmlserializable/DESC b/staging_vespalib/src/tests/xmlserializable/DESC
new file mode 100644
index 00000000000..7768b3e7b6d
--- /dev/null
+++ b/staging_vespalib/src/tests/xmlserializable/DESC
@@ -0,0 +1 @@
+xmlserializable test. Take a look at xmlserializabletest.cpp for details.
diff --git a/staging_vespalib/src/tests/xmlserializable/FILES b/staging_vespalib/src/tests/xmlserializable/FILES
new file mode 100644
index 00000000000..e7c7d2397b7
--- /dev/null
+++ b/staging_vespalib/src/tests/xmlserializable/FILES
@@ -0,0 +1 @@
+xmlserializabletest.cpp
diff --git a/staging_vespalib/src/tests/xmlserializable/xmlserializabletest.cpp b/staging_vespalib/src/tests/xmlserializable/xmlserializabletest.cpp
new file mode 100644
index 00000000000..a44802735eb
--- /dev/null
+++ b/staging_vespalib/src/tests/xmlserializable/xmlserializabletest.cpp
@@ -0,0 +1,165 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#include <vespa/fastos/fastos.h>
+#include <vespa/vespalib/util/xmlserializable.h>
+
+#include <vespa/vespalib/testkit/testapp.h>
+
+namespace vespalib {
+
+class Test : public vespalib::TestApp
+{
+public:
+ void testNormalUsage();
+ void testEscaping();
+ void testNesting();
+ void testIndent();
+
+ int Main();
+};
+
+int
+Test::Main()
+{
+ TEST_INIT("xmlserializables_test");
+ srandom(1);
+ testNormalUsage();
+ testEscaping();
+ testNesting();
+ testIndent();
+ TEST_DONE();
+}
+
+void
+Test::testNormalUsage()
+{
+ std::ostringstream ost;
+ XmlOutputStream xos(ost);
+ using namespace vespalib::xml;
+ xos << XmlTag("car")
+ << XmlTag("door")
+ << XmlAttribute("windowstate", "up")
+ << XmlEndTag()
+ << XmlTag("description")
+ << "This is a car description used to test"
+ << XmlEndTag()
+ << XmlEndTag();
+ std::string expected =
+ "\n<car>\n"
+ "<door windowstate=\"up\"/>\n"
+ "<description>This is a car description used to test</description>\n"
+ "</car>";
+ EXPECT_EQUAL(expected, "\n" + ost.str());
+}
+
+void
+Test::testEscaping()
+{
+ std::ostringstream ost;
+ XmlOutputStream xos(ost);
+ using namespace vespalib::xml;
+ xos << XmlTag("!#trash%-", CONVERT_ILLEGAL_CHARACTERS)
+ << XmlTag("foo")
+ << XmlAttribute("bar", "<100%\" &\n>")
+ << XmlEndTag()
+ << XmlTag("escaped")
+ << XmlEscapedContent()
+ << XmlContentWrapper("<>&\"'% \r\n\t\f\0", 12)
+ << XmlEndTag()
+ << XmlTag("encoded")
+ << XmlBase64Content()
+ << XmlContentWrapper("<>&\"'% \t\f\0", 10)
+ << XmlEndTag()
+ << XmlTag("auto1")
+ << XmlContentWrapper("<>&\t\f\r\nfoo", 10)
+ << XmlEndTag()
+ << XmlTag("auto2")
+ << XmlContentWrapper("<>&\t\0\r\nfoo", 10)
+ << XmlEndTag()
+ << XmlEndTag();
+ std::string expected =
+ "\n<__trash_->\n"
+ "<foo bar=\"&lt;100%&quot; &amp;&#10;&gt;\"/>\n"
+ "<escaped>&lt;&gt;&amp;\"'% &#13;\n&#9;&#12;&#0;</escaped>\n"
+ "<encoded binaryencoding=\"base64\">PD4mIiclIAkMAA==</encoded>\n"
+ "<auto1>&lt;&gt;&amp;&#9;&#12;&#13;\nfoo</auto1>\n"
+ "<auto2 binaryencoding=\"base64\">PD4mCQANCmZvbw==</auto2>\n"
+ "</__trash_->";
+ EXPECT_EQUAL(expected, "\n" + ost.str());
+}
+
+namespace {
+ struct LookAndFeel : public XmlSerializable {
+
+ LookAndFeel() {}
+
+ void printXml(XmlOutputStream& out) const {
+ using namespace vespalib::xml;
+ out << XmlAttribute("color", "blue")
+ << XmlTag("other")
+ << XmlAttribute("count", 5)
+ << XmlTag("something") << "foo" << XmlEndTag()
+ << XmlTag("else") << "bar" << XmlEndTag()
+ << XmlEndTag();
+ }
+ };
+}
+
+void
+Test::testNesting()
+{
+ std::ostringstream ost;
+ XmlOutputStream xos(ost);
+ using namespace vespalib::xml;
+ xos << XmlTag("car")
+ << XmlTag("door")
+ << LookAndFeel()
+ << XmlEndTag()
+ << XmlTag("description")
+ << "This is a car description used to test"
+ << XmlEndTag()
+ << XmlEndTag();
+ std::string expected =
+ "\n<car>\n"
+ "<door color=\"blue\">\n"
+ "<other count=\"5\">\n"
+ "<something>foo</something>\n"
+ "<else>bar</else>\n"
+ "</other>\n"
+ "</door>\n"
+ "<description>This is a car description used to test</description>\n"
+ "</car>";
+ EXPECT_EQUAL(expected, "\n" + ost.str());
+}
+
+void
+Test::testIndent()
+{
+ std::ostringstream ost;
+ XmlOutputStream xos(ost, " ");
+ using namespace vespalib::xml;
+ xos << XmlTag("foo")
+ << XmlTag("bar") << 2.14 << XmlEndTag()
+ << "Litt innhold"
+ << XmlTag("nytag")
+ << "Mer innhold"
+ << XmlTag("base")
+ << XmlBase64Content() << "foobar"
+ << XmlEndTag()
+ << XmlEndTag()
+ << XmlEndTag();
+ std::string expected = "\n"
+ "<foo>\n"
+ " <bar>2.14</bar>\n"
+ " Litt innhold\n"
+ " <nytag>\n"
+ " Mer innhold\n"
+ " <base binaryencoding=\"base64\">Zm9vYmFy</base>\n"
+ " </nytag>\n"
+ "</foo>";
+ EXPECT_EQUAL(expected, "\n" + ost.str());
+}
+
+} // vespalib
+
+TEST_APPHOOK(vespalib::Test)