%global group_name %{name}
%global state_path %{_localstatedir}/%{name}/
+%global tests_dir %{_datarootdir}/%{name}/tests
%global build_type %{?build_type:%build_type}%{!?build_type:RELEASE}
cp -a %{SOURCE1008} .
cp -a %{SOURCE1009} .
cp -a %{SOURCE1010} .
+cp -a test/db/db* .
%build
%if 0%{?sec_build_binary_debug_enable}
export CXXFLAGS="$CXXFLAGS -Wp,-U_FORTIFY_SOURCE"
%endif
-export CXXFLAGS="$CXXFLAGS -DCYNARA_STATE_PATH=\\\"%{state_path}\\\""
+export CXXFLAGS="$CXXFLAGS -DCYNARA_STATE_PATH=\\\"%{state_path}\\\" \
+ -DCYNARA_TESTS_DIR=\\\"%{tests_dir}\\\""
export LDFLAGS+="-Wl,--rpath=%{_libdir}"
%cmake . \
mkdir -p %{buildroot}/usr/lib/systemd/system/sockets.target.wants
mkdir -p %{buildroot}/%{state_path}
+mkdir -p %{buildroot}/%{tests_dir}
+cp -a db* %{buildroot}/%{tests_dir}
ln -s ../cynara.socket %{buildroot}/usr/lib/systemd/system/sockets.target.wants/cynara.socket
ln -s ../cynara-admin.socket %{buildroot}/usr/lib/systemd/system/sockets.target.wants/cynara-admin.socket
%files -n cynara-tests
%manifest cynara-tests.manifest
%attr(755,root,root) /usr/bin/cynara-tests
+%attr(755,root,root) %{tests_dir}/db*/*
%files -n libcynara-creds-commons
%manifest libcynara-creds-commons.manifest
#include <log/log.h>
#include <exceptions/BucketNotExistsException.h>
#include <exceptions/CannotCreateFileException.h>
+#include <exceptions/DatabaseException.h>
#include <exceptions/FileNotFoundException.h>
#include <exceptions/UnexpectedErrorException.h>
#include <types/PolicyBucket.h>
storageDeserializer.initBuckets(buckets());
storageDeserializer.loadBuckets(buckets());
- } catch (const FileNotFoundException &) {
- LOGE("Reading cynara database failed.");
+ } catch (const DatabaseException &) {
+ LOGC("Reading cynara database failed.");
+ buckets().clear();
+ // TODO: Implement emergency mode toggle
}
if (!hasBucket(defaultPolicyBucketId)) {
- LOGN("Creating defaultBucket.");
- this->buckets().insert({ defaultPolicyBucketId, PolicyBucket() });
+ LOGN("Creating defaultBucket.");
+ this->buckets().insert({ defaultPolicyBucketId, PolicyBucket() });
}
}
#define INMEMEORYSTORAGEBACKENDFIXTURE_H_
#include <gmock/gmock.h>
+#include <gtest/gtest.h>
#include <types/PolicyBucket.h>
#include <types/PolicyCollection.h>
}
}
+ static void ASSERT_DB_VIRGIN(Cynara::Buckets &buckets) {
+ using ::testing::IsEmpty;
+ ASSERT_EQ(1, buckets.size());
+ auto defaultBucketIter = buckets.find(Cynara::defaultPolicyBucketId);
+ ASSERT_NE(buckets.end(), defaultBucketIter);
+ auto &defaultBucket = defaultBucketIter->second;
+ ASSERT_THAT(defaultBucket, IsEmpty());
+ ASSERT_EQ(Cynara::PredefinedPolicyType::DENY, defaultBucket.defaultPolicy());
+ }
+
virtual ~InMemeoryStorageBackendFixture() {}
// TODO: consider defaulting accessor with ON_CALL
#include <gmock/gmock.h>
#include <gtest/gtest.h>
-#include "exceptions/DefaultBucketDeletionException.h"
#include "exceptions/BucketNotExistsException.h"
+#include "exceptions/BucketDeserializationException.h"
+#include "exceptions/DefaultBucketDeletionException.h"
+#include "exceptions/FileNotFoundException.h"
#include "storage/InMemoryStorageBackend.h"
#include "storage/StorageBackend.h"
#include "types/PolicyCollection.h"
EXPECT_THROW(backend.deletePolicy("non-existent", Helpers::generatePolicyKey()),
BucketNotExistsException);
}
+
+// Database dir is empty
+TEST_F(InMemeoryStorageBackendFixture, load_no_db) {
+ using ::testing::ReturnRef;
+ auto testDbPath = std::string(CYNARA_TESTS_DIR) + "/db1/";
+ FakeInMemoryStorageBackend backend(testDbPath);
+ EXPECT_CALL(backend, buckets()).WillRepeatedly(ReturnRef(m_buckets));
+ backend.load();
+ ASSERT_DB_VIRGIN(m_buckets);
+}
+
+// Database dir contains index with default bucket, but no file for this bucket
+TEST_F(InMemeoryStorageBackendFixture, load_no_default) {
+ using ::testing::ReturnRef;
+ auto testDbPath = std::string(CYNARA_TESTS_DIR) + "/db2/";
+ FakeInMemoryStorageBackend backend(testDbPath);
+ EXPECT_CALL(backend, buckets()).WillRepeatedly(ReturnRef(m_buckets));
+ backend.load();
+ ASSERT_DB_VIRGIN(m_buckets);
+}
+
+// Database contains index with default bucket and an empty bucket file
+TEST_F(InMemeoryStorageBackendFixture, load_default_only) {
+ using ::testing::ReturnRef;
+ auto testDbPath = std::string(CYNARA_TESTS_DIR) + "/db3/";
+ FakeInMemoryStorageBackend backend(testDbPath);
+ EXPECT_CALL(backend, buckets()).WillRepeatedly(ReturnRef(m_buckets));
+ backend.load();
+ ASSERT_DB_VIRGIN(m_buckets);
+}
+
+// Database contains index with default bucket and an additional bucket
+// There are files for both buckets present
+TEST_F(InMemeoryStorageBackendFixture, load_2_buckets) {
+ using ::testing::ReturnRef;
+ using ::testing::IsEmpty;
+
+ auto testDbPath = std::string(CYNARA_TESTS_DIR) + "/db4/";
+
+ FakeInMemoryStorageBackend backend(testDbPath);
+ EXPECT_CALL(backend, buckets()).WillRepeatedly(ReturnRef(m_buckets));
+ backend.load();
+
+ std::vector<std::string> bucketIds = { "", "additional" };
+
+ for(const auto &bucketId : bucketIds) {
+ SCOPED_TRACE(bucketId);
+ const auto bucketIter = m_buckets.find(bucketId);
+ ASSERT_NE(m_buckets.end(), bucketIter);
+
+ const auto &bucketPolicies = bucketIter->second;
+ ASSERT_THAT(bucketPolicies, IsEmpty());
+ }
+}
+
+// Database contains index with 2 buckets; 1st bucket is valid, but second is corrupted
+TEST_F(InMemeoryStorageBackendFixture, second_bucket_corrupted) {
+ using ::testing::ReturnRef;
+ auto testDbPath = std::string(CYNARA_TESTS_DIR) + "/db5/";
+ FakeInMemoryStorageBackend backend(testDbPath);
+ EXPECT_CALL(backend, buckets()).WillRepeatedly(ReturnRef(m_buckets));
+ backend.load();
+ ASSERT_DB_VIRGIN(m_buckets);
+}