From 3080bdd575f2c82674fbe14982caa6b77e1addc4 Mon Sep 17 00:00:00 2001 From: Roy Ben Moshe Date: Sun, 20 Nov 2022 14:16:17 +0200 Subject: [PATCH] QA tool to check artifacts (#120) --- tools/artifacts_check/.gitignore | 2 + tools/artifacts_check/Makefile | 29 +++++ tools/artifacts_check/README.md | 14 +++ tools/artifacts_check/check_artifacts.cc | 152 +++++++++++++++++++++++ 4 files changed, 197 insertions(+) create mode 100644 tools/artifacts_check/.gitignore create mode 100644 tools/artifacts_check/Makefile create mode 100644 tools/artifacts_check/README.md create mode 100644 tools/artifacts_check/check_artifacts.cc diff --git a/tools/artifacts_check/.gitignore b/tools/artifacts_check/.gitignore new file mode 100644 index 0000000000..1b660d640d --- /dev/null +++ b/tools/artifacts_check/.gitignore @@ -0,0 +1,2 @@ +check_static +check_shared \ No newline at end of file diff --git a/tools/artifacts_check/Makefile b/tools/artifacts_check/Makefile new file mode 100644 index 0000000000..582bb7dd3c --- /dev/null +++ b/tools/artifacts_check/Makefile @@ -0,0 +1,29 @@ +include ../../make_config.mk + +ifndef DISABLE_JEMALLOC + ifdef JEMALLOC + PLATFORM_CXXFLAGS += -DROCKSDB_JEMALLOC -DJEMALLOC_NO_DEMANGLE + endif + EXEC_LDFLAGS := $(JEMALLOC_LIB) $(EXEC_LDFLAGS) -lpthread + PLATFORM_CXXFLAGS += $(JEMALLOC_INCLUDE) +endif + +ifneq ($(USE_RTTI), 1) + CXXFLAGS += -fno-rtti +endif + +CFLAGS += -Wstrict-prototypes + +.PHONY: clean + +all: check_static check_shared + +check_static: check_artifacts.cc + $(CXX) $(CXXFLAGS) check_artifacts.cc -o$@ ../../libspeedb.a -I../../include -std=c++17 $(PLATFORM_LDFLAGS) $(PLATFORM_CXXFLAGS) $(EXEC_LDFLAGS) + +check_shared: check_artifacts.cc + $(CXX) $(CXXFLAGS) check_artifacts.cc -o$@ -L../.. -lspeedb -I../../include -std=c++17 $(PLATFORM_LDFLAGS) $(PLATFORM_CXXFLAGS) $(EXEC_LDFLAGS) + +clean: + rm -rf ./check_static ./check_shared + diff --git a/tools/artifacts_check/README.md b/tools/artifacts_check/README.md new file mode 100644 index 0000000000..f24706492f --- /dev/null +++ b/tools/artifacts_check/README.md @@ -0,0 +1,14 @@ +# Speedb Artifacts Checker + +## Motivation + +As part of our release process, we need to test the .a and .so artifacts. our QA tools (unit, stress, and fuzz tests) are all testing the source code and compiling it to be tested. Those tools are unable to test either static or dynamic artifacts. +We would like to create primary testing tools, able to import .a / .so artifact, verify compilation, and no corruption. + +## Overview + +Sanity check for .a / .so artifact. + +## Usage +make check_shared / make check_static while the artifact is in speedb folder. + diff --git a/tools/artifacts_check/check_artifacts.cc b/tools/artifacts_check/check_artifacts.cc new file mode 100644 index 0000000000..6b67243ab4 --- /dev/null +++ b/tools/artifacts_check/check_artifacts.cc @@ -0,0 +1,152 @@ +// Copyright (c) 2011-present, Facebook, Inc. All rights reserved. +// This source code is licensed under both the GPLv2 (found in the +// COPYING file in the root directory) and Apache 2.0 License +// (found in the LICENSE.Apache file in the root directory). + +#include +#include +#include + +#include "rocksdb/db.h" +#include "rocksdb/options.h" +#include "rocksdb/slice.h" + +using ROCKSDB_NAMESPACE::DB; +using ROCKSDB_NAMESPACE::Iterator; +using ROCKSDB_NAMESPACE::Options; +using ROCKSDB_NAMESPACE::PinnableSlice; +using ROCKSDB_NAMESPACE::ReadOptions; +using ROCKSDB_NAMESPACE::Status; +using ROCKSDB_NAMESPACE::WriteBatch; +using ROCKSDB_NAMESPACE::WriteOptions; + +#if defined(OS_WIN) +std::string kDBPath = "C:\\Windows\\TEMP\\check_artifacts"; +#else +std::string kDBPath = "/tmp/check_artifacts"; +#endif + +int main() { + DB* db; + Options options; + int counter; + + // Optimize RocksDB. This is the easiest way to get RocksDB to perform well + options.IncreaseParallelism(); + options.OptimizeLevelStyleCompaction(); + // create the DB if it's not already present + options.create_if_missing = true; + + ReadOptions ropts; + ropts.verify_checksums = true; + ropts.total_order_seek = true; + + // open DB + Status s = DB::Open(options, kDBPath, &db); + assert(s.ok()); + + Iterator* iter = db->NewIterator(ropts); + // verify db is empty + iter->SeekToFirst(); + if (iter->Valid()) { + delete iter; + delete db; + db = nullptr; + s = DB::Open(options, kDBPath, &db); + assert(s.ok()); + iter = db->NewIterator(ropts); + } + + // Put key-value + s = db->Put(WriteOptions(), "1", "value"); + assert(s.ok()); + std::string value; + // get value + s = db->Get(ReadOptions(), "1", &value); + assert(s.ok()); + assert(value == "value"); + + // atomically apply a set of updates + { + WriteBatch batch; + batch.Delete("1"); + batch.Put("2", value); + s = db->Write(WriteOptions(), &batch); + } + + s = db->Get(ReadOptions(), "1", &value); + assert(s.IsNotFound()); + + db->Get(ReadOptions(), "2", &value); + assert(value == "value"); + + s = db->Put(WriteOptions(), "4", "value3"); + assert(s.ok()); + + // Seek for key + iter->SeekToFirst(); + iter->Seek("3"); + counter = 0; + while (iter->Valid()) { + iter->Next(); + counter++; + } + assert(counter == 1); + + // value is bigger than the max value in db + iter->Seek("9"); + counter = 0; + while (iter->Valid()) { + iter->Next(); + counter++; + } + assert(counter == 0); + + // value is smaller than the min value in db + iter->Seek("1"); + counter = 0; + while (iter->Valid()) { + iter->Next(); + counter++; + } + assert(counter == 2); + + // seek for the last + iter->Seek("4"); + counter = 0; + while (iter->Valid()) { + iter->Next(); + counter++; + } + assert(counter == 1); + + { + PinnableSlice pinnable_val; + db->Get(ReadOptions(), db->DefaultColumnFamily(), "2", &pinnable_val); + assert(pinnable_val == "value"); + } + + { + std::string string_val; + // If it cannot pin the value, it copies the value to its internal buffer. + // The intenral buffer could be set during construction. + PinnableSlice pinnable_val(&string_val); + db->Get(ReadOptions(), db->DefaultColumnFamily(), "2", &pinnable_val); + assert(pinnable_val == "value"); + // If the value is not pinned, the internal buffer must have the value. + assert(pinnable_val.IsPinned() || string_val == "value"); + } + + PinnableSlice pinnable_val; + s = db->Get(ReadOptions(), db->DefaultColumnFamily(), "1", &pinnable_val); + assert(s.IsNotFound()); + // Reset PinnableSlice after each use and before each reuse + pinnable_val.Reset(); + db->Get(ReadOptions(), db->DefaultColumnFamily(), "2", &pinnable_val); + assert(pinnable_val == "value"); + pinnable_val.Reset(); + // The Slice pointed by pinnable_val is not valid after this point + delete iter; + delete db; + return 0; +}