aboutsummaryrefslogtreecommitdiffstats
path: root/SoftHSMv2/src/lib/object_store/test
diff options
context:
space:
mode:
authorNingSun <ning.sun@intel.com>2018-02-08 08:34:03 -0800
committerNingSun <ning.sun@intel.com>2018-02-08 09:14:52 -0800
commit0c89b3ccba7c9b7332ab67ae1936aff51ca62367 (patch)
tree70c1b1d160d4c6d0a83395ca9a87c1264d0d3439 /SoftHSMv2/src/lib/object_store/test
parent945613b4db4e07f75d2bc7463db580ddfaa700fd (diff)
Initial sshsm project structure
Issue-ID: AAF-94 Change-Id: I5e82fff418e7567b161acf9b98013a9b85ffc5b4 Signed-off-by: NingSun <ning.sun@intel.com>
Diffstat (limited to 'SoftHSMv2/src/lib/object_store/test')
-rw-r--r--SoftHSMv2/src/lib/object_store/test/DBObjectStoreTests.cpp159
-rw-r--r--SoftHSMv2/src/lib/object_store/test/DBObjectStoreTests.h79
-rw-r--r--SoftHSMv2/src/lib/object_store/test/DBObjectTests.cpp816
-rw-r--r--SoftHSMv2/src/lib/object_store/test/DBObjectTests.h93
-rw-r--r--SoftHSMv2/src/lib/object_store/test/DBTests.cpp648
-rw-r--r--SoftHSMv2/src/lib/object_store/test/DBTests.h134
-rw-r--r--SoftHSMv2/src/lib/object_store/test/DBTokenTests.cpp491
-rw-r--r--SoftHSMv2/src/lib/object_store/test/DBTokenTests.h66
-rw-r--r--SoftHSMv2/src/lib/object_store/test/DirectoryTests.cpp227
-rw-r--r--SoftHSMv2/src/lib/object_store/test/DirectoryTests.h54
-rw-r--r--SoftHSMv2/src/lib/object_store/test/FileTests.cpp340
-rw-r--r--SoftHSMv2/src/lib/object_store/test/FileTests.h63
-rw-r--r--SoftHSMv2/src/lib/object_store/test/Makefile.am39
-rw-r--r--SoftHSMv2/src/lib/object_store/test/OSTokenTests.cpp504
-rw-r--r--SoftHSMv2/src/lib/object_store/test/OSTokenTests.h60
-rw-r--r--SoftHSMv2/src/lib/object_store/test/ObjectFileTests.cpp911
-rw-r--r--SoftHSMv2/src/lib/object_store/test/ObjectFileTests.h72
-rw-r--r--SoftHSMv2/src/lib/object_store/test/ObjectStoreTests.cpp278
-rw-r--r--SoftHSMv2/src/lib/object_store/test/ObjectStoreTests.h58
-rw-r--r--SoftHSMv2/src/lib/object_store/test/SessionObjectStoreTests.cpp319
-rw-r--r--SoftHSMv2/src/lib/object_store/test/SessionObjectStoreTests.h56
-rw-r--r--SoftHSMv2/src/lib/object_store/test/SessionObjectTests.cpp436
-rw-r--r--SoftHSMv2/src/lib/object_store/test/SessionObjectTests.h68
-rw-r--r--SoftHSMv2/src/lib/object_store/test/UUIDTests.cpp61
-rw-r--r--SoftHSMv2/src/lib/object_store/test/UUIDTests.h54
-rw-r--r--SoftHSMv2/src/lib/object_store/test/objstoretest.cpp91
26 files changed, 6177 insertions, 0 deletions
diff --git a/SoftHSMv2/src/lib/object_store/test/DBObjectStoreTests.cpp b/SoftHSMv2/src/lib/object_store/test/DBObjectStoreTests.cpp
new file mode 100644
index 0000000..2cc8360
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/DBObjectStoreTests.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2013 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DBObjectStoreTests.cpp
+
+ Contains test cases to test the object store implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "DBObjectStoreTests.h"
+
+#include <cstdio>
+
+#ifndef HAVE_SQLITE3_H
+#error expected sqlite3 to be available
+#endif
+
+CPPUNIT_TEST_SUITE_REGISTRATION(test_a_newly_created_object_store);
+
+void test_a_newly_created_object_store::setUp()
+{
+ CPPUNIT_ASSERT(!system("mkdir testdir"));
+
+ ObjectStoreToken::selectBackend("db");
+
+ store = new ObjectStore("testdir");
+ nulltoken = NULL;
+}
+
+void test_a_newly_created_object_store::tearDown()
+{
+ delete store;
+
+ ObjectStoreToken::selectBackend("file");
+
+#ifndef _WIN32
+ CPPUNIT_ASSERT(!system("rm -rf testdir"));
+#else
+ CPPUNIT_ASSERT(!system("rmdir /s /q testdir 2> nul"));
+#endif
+}
+
+
+void test_a_newly_created_object_store::contains_no_items()
+{
+ CPPUNIT_ASSERT_EQUAL(store->getTokenCount(), (size_t)0);
+}
+
+void test_a_newly_created_object_store::can_create_a_new_token()
+{
+ ByteString label1 = "DEADC0FFEE";
+
+ ObjectStoreToken *token1 = store->newToken(label1);
+ CPPUNIT_ASSERT(token1 != nulltoken);
+ CPPUNIT_ASSERT_EQUAL(store->getTokenCount(), (size_t)1);
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(test_a_newly_created_object_store_containing_two_tokens);
+
+
+void test_a_newly_created_object_store_containing_two_tokens::setUp()
+{
+ test_a_newly_created_object_store::setUp();
+
+ ByteString label1 = "DEADC0FFEE";
+ ByteString label2 = "DEADBEEF";
+
+ ObjectStoreToken* token1 = store->newToken(label1);
+ CPPUNIT_ASSERT(token1 != nulltoken);
+ CPPUNIT_ASSERT_EQUAL(store->getTokenCount(), (size_t)1);
+
+ ObjectStoreToken* token2 = store->newToken(label2);
+ CPPUNIT_ASSERT(token2 != nulltoken);
+ CPPUNIT_ASSERT_EQUAL(store->getTokenCount(), (size_t)2);
+}
+
+void test_a_newly_created_object_store_containing_two_tokens::tearDown()
+{
+ ObjectStoreToken* token1 = store->getToken(0);
+ ObjectStoreToken* token2 = store->getToken(1);
+ CPPUNIT_ASSERT(store->destroyToken(token1));
+ CPPUNIT_ASSERT(store->destroyToken(token2));
+
+ test_a_newly_created_object_store::tearDown();
+}
+
+void test_a_newly_created_object_store_containing_two_tokens::has_two_tokens()
+{
+ CPPUNIT_ASSERT_EQUAL(store->getTokenCount(), (size_t)2);
+}
+
+void test_a_newly_created_object_store_containing_two_tokens::can_access_both_tokens()
+{
+ // Retrieve both tokens and check that both are present
+ ObjectStoreToken* token1 = store->getToken(0);
+ ObjectStoreToken* token2 = store->getToken(1);
+
+ CPPUNIT_ASSERT(token1 != nulltoken);
+ CPPUNIT_ASSERT(token2 != nulltoken);
+}
+
+void test_a_newly_created_object_store_containing_two_tokens::assigned_labels_correctly_to_tokens()
+{
+ ByteString label1 = "DEADC0FFEE";
+ ByteString label2 = "DEADBEEF";
+
+ // Retrieve both tokens and check that both are present
+ ObjectStoreToken* token1 = store->getToken(0);
+ ObjectStoreToken* token2 = store->getToken(1);
+
+ ByteString retrieveLabel1, retrieveLabel2;
+
+ CPPUNIT_ASSERT(token1->getTokenLabel(retrieveLabel1));
+ CPPUNIT_ASSERT(token2->getTokenLabel(retrieveLabel2));
+
+ CPPUNIT_ASSERT(label1 == retrieveLabel1 || label1 == retrieveLabel2);
+ CPPUNIT_ASSERT(label2 == retrieveLabel1 || label2 == retrieveLabel2);
+ CPPUNIT_ASSERT(label1 != label2);
+}
+
+void test_a_newly_created_object_store_containing_two_tokens::assigned_a_unique_serial_number_to_each_token()
+{
+ // Retrieve both tokens and check that both are present
+ ObjectStoreToken* token1 = store->getToken(0);
+ ObjectStoreToken* token2 = store->getToken(1);
+
+ ByteString retrieveSerial1, retrieveSerial2;
+
+ CPPUNIT_ASSERT(token1->getTokenSerial(retrieveSerial1));
+ CPPUNIT_ASSERT(token2->getTokenSerial(retrieveSerial2));
+
+ CPPUNIT_ASSERT(retrieveSerial1 != retrieveSerial2);
+}
diff --git a/SoftHSMv2/src/lib/object_store/test/DBObjectStoreTests.h b/SoftHSMv2/src/lib/object_store/test/DBObjectStoreTests.h
new file mode 100644
index 0000000..7d100c8
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/DBObjectStoreTests.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2013 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DBObjectStoreTests.h
+
+ Contains test cases to test the object store implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DBOBJECTSTORETESTS_H
+#define _SOFTHSM_V2_DBOBJECTSTORETESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "ObjectStore.h"
+#include "ObjectStoreToken.h"
+
+class test_a_newly_created_object_store : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(test_a_newly_created_object_store);
+ CPPUNIT_TEST(contains_no_items);
+ CPPUNIT_TEST(can_create_a_new_token);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void setUp();
+ void tearDown();
+
+ void contains_no_items();
+ void can_create_a_new_token();
+protected:
+ ObjectStore *store;
+ ObjectStoreToken *nulltoken;
+
+private:
+};
+
+class test_a_newly_created_object_store_containing_two_tokens : public test_a_newly_created_object_store
+{
+ CPPUNIT_TEST_SUITE(test_a_newly_created_object_store_containing_two_tokens);
+ CPPUNIT_TEST(has_two_tokens);
+ CPPUNIT_TEST(can_access_both_tokens);
+ CPPUNIT_TEST(assigned_labels_correctly_to_tokens);
+ CPPUNIT_TEST(assigned_a_unique_serial_number_to_each_token);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void setUp();
+ void tearDown();
+
+ void has_two_tokens();
+ void can_access_both_tokens();
+ void assigned_labels_correctly_to_tokens();
+ void assigned_a_unique_serial_number_to_each_token();
+};
+
+#endif // !_SOFTHSM_V2_DBOBJECTSTORETESTS_H
diff --git a/SoftHSMv2/src/lib/object_store/test/DBObjectTests.cpp b/SoftHSMv2/src/lib/object_store/test/DBObjectTests.cpp
new file mode 100644
index 0000000..d856b06
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/DBObjectTests.cpp
@@ -0,0 +1,816 @@
+/*
+ * Copyright (c) 2013 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DBObjectTests.cpp
+
+ Contains test cases to test the database token object implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "DBObjectTests.h"
+#include "DBObject.h"
+
+#include <cstdio>
+
+#ifndef HAVE_SQLITE3_H
+#error expected sqlite3 to be available
+#endif
+
+CPPUNIT_TEST_SUITE_REGISTRATION(test_a_dbobject);
+
+void test_a_dbobject::setUp()
+{
+ CPPUNIT_ASSERT(!system("mkdir testdir"));
+ connection = DB::Connection::Create("testdir","TestToken");
+ CPPUNIT_ASSERT(connection != NULL);
+ CPPUNIT_ASSERT(connection->connect("<1>"));
+ connection->setBusyTimeout(10);
+
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.startTransaction(DBObject::ReadWrite));
+ CPPUNIT_ASSERT(testObject.createTables());
+ CPPUNIT_ASSERT(testObject.commitTransaction());
+
+ connection2 = DB::Connection::Create("testdir","TestToken");
+ CPPUNIT_ASSERT(connection2 != NULL);
+ CPPUNIT_ASSERT(connection2->connect("<2>"));
+ connection2->setBusyTimeout(10);
+}
+
+void test_a_dbobject::tearDown()
+{
+ CPPUNIT_ASSERT(connection != NULL);
+ connection->close();
+ delete connection;
+
+ CPPUNIT_ASSERT(connection2 != NULL);
+ connection2->close();
+ delete connection2;
+
+#ifndef _WIN32
+ CPPUNIT_ASSERT(!system("rm -rf testdir"));
+#else
+ CPPUNIT_ASSERT(!system("rmdir /s /q testdir 2> nul"));
+#endif
+}
+
+void test_a_dbobject::should_be_insertable()
+{
+ DBObject tokenObject(connection);
+ CPPUNIT_ASSERT(!tokenObject.isValid());
+ CPPUNIT_ASSERT(tokenObject.insert());
+ CPPUNIT_ASSERT(tokenObject.isValid());
+ CPPUNIT_ASSERT_EQUAL(tokenObject.objectId(), (long long)1);
+}
+
+void test_a_dbobject::should_be_selectable()
+{
+ should_be_insertable();
+
+ DBObject tokenObject(connection);
+ CPPUNIT_ASSERT(tokenObject.find(1));
+ CPPUNIT_ASSERT(tokenObject.isValid());
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(test_a_dbobject_with_an_object);
+
+void test_a_dbobject_with_an_object::setUp()
+{
+ test_a_dbobject::setUp();
+ DBObject tokenObject(connection);
+ CPPUNIT_ASSERT(tokenObject.startTransaction(DBObject::ReadWrite));
+ CPPUNIT_ASSERT(!tokenObject.isValid());
+ CPPUNIT_ASSERT(tokenObject.insert());
+ CPPUNIT_ASSERT(tokenObject.isValid());
+ CPPUNIT_ASSERT_EQUAL(tokenObject.objectId(), (long long)1);
+ CPPUNIT_ASSERT(tokenObject.commitTransaction());
+
+}
+
+void test_a_dbobject_with_an_object::tearDown()
+{
+ test_a_dbobject::tearDown();
+}
+
+void test_a_dbobject_with_an_object::should_store_boolean_attributes()
+{
+ {
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ bool value1 = true;
+ bool value2 = false;
+ bool value3 = true;
+ bool value4 = true;
+ bool value5 = false;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+ OSAttribute attr5(value5);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SENSITIVE, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_EXTRACTABLE, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_NEVER_EXTRACTABLE, attr4));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SIGN, attr5));
+ }
+
+ {
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_TOKEN));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SENSITIVE));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_EXTRACTABLE));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_NEVER_EXTRACTABLE));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SIGN));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SENSITIVE).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_EXTRACTABLE).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_NEVER_EXTRACTABLE).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN).isBooleanAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue());
+ CPPUNIT_ASSERT(!testObject.getAttribute(CKA_SENSITIVE).getBooleanValue());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_EXTRACTABLE).getBooleanValue());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_NEVER_EXTRACTABLE).getBooleanValue());
+ CPPUNIT_ASSERT(!testObject.getAttribute(CKA_SIGN).getBooleanValue());
+
+ bool value6 = true;
+ OSAttribute attr6(value6);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VERIFY, attr6));
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VERIFY).isBooleanAttribute());
+ CPPUNIT_ASSERT_EQUAL(testObject.getAttribute(CKA_VERIFY).getBooleanValue(), value6);
+ CPPUNIT_ASSERT_EQUAL(testObject.getBooleanValue(CKA_VERIFY, false), value6);
+ }
+}
+
+
+void test_a_dbobject_with_an_object::should_store_unsigned_long_attributes()
+{
+ // Add unsigned long attributes to the object
+ {
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ unsigned long value1 = 0x12345678;
+ unsigned long value2 = 0x87654321;
+ unsigned long value3 = 0x01010101;
+ unsigned long value4 = 0x10101010;
+ unsigned long value5 = 0xABCDEF;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+ OSAttribute attr5(value5);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_MODULUS_BITS, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_AUTH_PIN_FLAGS, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SUBPRIME_BITS, attr4));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_KEY_TYPE, attr5));
+ }
+
+ // Now read back the object
+ {
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_MODULUS_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_AUTH_PIN_FLAGS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SUBPRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_KEY_TYPE));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_MODULUS_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_AUTH_PIN_FLAGS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBPRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_KEY_TYPE).isUnsignedLongAttribute());
+
+ CPPUNIT_ASSERT_EQUAL(testObject.getAttribute(CKA_MODULUS_BITS).getUnsignedLongValue(), (unsigned long)0x12345678);
+ CPPUNIT_ASSERT_EQUAL(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue(), (unsigned long)0x87654321);
+ CPPUNIT_ASSERT_EQUAL(testObject.getAttribute(CKA_AUTH_PIN_FLAGS).getUnsignedLongValue(), (unsigned long)0x01010101);
+ CPPUNIT_ASSERT_EQUAL(testObject.getAttribute(CKA_SUBPRIME_BITS).getUnsignedLongValue(), (unsigned long)0x10101010);
+ CPPUNIT_ASSERT_EQUAL(testObject.getAttribute(CKA_KEY_TYPE).getUnsignedLongValue(), (unsigned long)0xABCDEF);
+
+ unsigned long value6 = 0x90909090;
+ OSAttribute attr6(value6);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_CLASS, attr6));
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_CLASS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT_EQUAL(testObject.getAttribute(CKA_CLASS).getUnsignedLongValue(), value6);
+ CPPUNIT_ASSERT_EQUAL(testObject.getUnsignedLongValue(CKA_CLASS, 0x0), value6);
+ }
+}
+
+void test_a_dbobject_with_an_object::should_store_binary_attributes()
+{
+ ByteString value1 = "010203040506070809";
+ ByteString value2 = "ABABABABABABABABABABABABABABABABAB";
+ unsigned long value3 = 0xBDED;
+ ByteString value4 = "98A7E5D798A7E5D798A7E5D798A7E5D798A7E5D798A7E5D7";
+ ByteString value5 = "ABCDABCDABCDABCDABCDABCDABCDABCD";
+
+ // Create the test object
+ {
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+ OSAttribute attr5(value5);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_MODULUS, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_COEFFICIENT, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PUBLIC_EXPONENT, attr4));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SUBJECT, attr5));
+ }
+
+ // Now read back the object
+ {
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_MODULUS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_COEFFICIENT));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_VALUE_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PUBLIC_EXPONENT));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SUBJECT));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_MODULUS).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_COEFFICIENT).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PUBLIC_EXPONENT).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBJECT).isByteStringAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_MODULUS).getByteStringValue() == value1);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_COEFFICIENT).getByteStringValue() == value2);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).getUnsignedLongValue() == value3);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PUBLIC_EXPONENT).getByteStringValue() == value4);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBJECT).getByteStringValue() == value5);
+
+ ByteString value6 = "909090908080808080807070707070FF";
+ OSAttribute attr6(value6);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ISSUER, attr6));
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ISSUER).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getByteStringValue(CKA_ISSUER) == value6);
+ }
+}
+
+void test_a_dbobject_with_an_object::should_store_mechtypeset_attributes()
+{
+
+ // Create the test object
+ {
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ std::set<CK_MECHANISM_TYPE> set;
+ set.insert(CKM_SHA256);
+ set.insert(CKM_SHA512);
+ OSAttribute attr(set);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ALLOWED_MECHANISMS, attr));
+ }
+
+ // Now read back the object
+ {
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_ALLOWED_MECHANISMS));
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ std::set<CK_MECHANISM_TYPE> retrieved =
+ testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue();
+
+ CPPUNIT_ASSERT(retrieved.size() == 2);
+ CPPUNIT_ASSERT(retrieved.find(CKM_SHA256) != retrieved.end());
+ CPPUNIT_ASSERT(retrieved.find(CKM_SHA384) == retrieved.end());
+ CPPUNIT_ASSERT(retrieved.find(CKM_SHA512) != retrieved.end());
+ }
+}
+
+void test_a_dbobject_with_an_object::should_store_attrmap_attributes()
+{
+ bool value1 = true;
+ unsigned long value2 = 0x87654321;
+ ByteString value3 = "BDEBDBEDBBDBEBDEBE792759537328";
+ std::set<CK_MECHANISM_TYPE> value4;
+ value4.insert(CKM_SHA256);
+ value4.insert(CKM_SHA512);
+
+ // Create the test object
+ {
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute> mattr;
+ mattr.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (CKA_TOKEN, attr1));
+ mattr.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (CKA_PRIME_BITS, attr2));
+ mattr.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (CKA_VALUE, attr3));
+ mattr.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (CKA_ALLOWED_MECHANISMS, attr4));
+ OSAttribute attra(mattr);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_WRAP_TEMPLATE, attra));
+ }
+
+ // Now read back the object
+ {
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_WRAP_TEMPLATE));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_UNWRAP_TEMPLATE));
+
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute> mattrb =
+ testObject.getAttribute(CKA_WRAP_TEMPLATE).getAttributeMapValue();
+ CPPUNIT_ASSERT(mattrb.size() == 4);
+ CPPUNIT_ASSERT(mattrb.find(CKA_TOKEN) != mattrb.end());
+ CPPUNIT_ASSERT(mattrb.at(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(mattrb.at(CKA_TOKEN).getBooleanValue() == true);
+ CPPUNIT_ASSERT(mattrb.find(CKA_PRIME_BITS) != mattrb.end());
+ CPPUNIT_ASSERT(mattrb.at(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(mattrb.at(CKA_PRIME_BITS).getUnsignedLongValue() == 0x87654321);
+ CPPUNIT_ASSERT(mattrb.find(CKA_VALUE) != mattrb.end());
+ CPPUNIT_ASSERT(mattrb.at(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(mattrb.at(CKA_VALUE).getByteStringValue() == value3);
+ CPPUNIT_ASSERT(mattrb.find(CKA_ALLOWED_MECHANISMS) != mattrb.end());
+ CPPUNIT_ASSERT(mattrb.at(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+ CPPUNIT_ASSERT(mattrb.at(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4);
+ }
+}
+
+void test_a_dbobject_with_an_object::should_store_mixed_attributes()
+{
+ bool value1 = true;
+ unsigned long value2 = 0x87654321;
+ unsigned long value3 = 0xBDEBDBED;
+ std::set<CK_MECHANISM_TYPE> value4;
+ value4.insert(CKM_SHA256);
+ value4.insert(CKM_SHA512);
+
+ // Create the test object
+ {
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ALLOWED_MECHANISMS, attr4));
+ }
+
+ // Now read back the object
+ {
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_TOKEN));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_VALUE_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_ALLOWED_MECHANISMS));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue());
+ CPPUNIT_ASSERT_EQUAL(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue(), value2);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).getUnsignedLongValue() == value3);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4);
+ }
+}
+
+void test_a_dbobject_with_an_object::should_store_double_attributes()
+{
+ bool value1 = true;
+ bool value1a = false;
+
+ // Create the test object
+ {
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ OSAttribute attr1(value1);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SIGN, attr1));
+ }
+
+ // Now read back the object
+ {
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SIGN));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN).isBooleanAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN).getBooleanValue());
+
+ OSAttribute attr1(value1a);
+
+ // Change the attributes
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SIGN, attr1));
+
+ // Check the attributes
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN).isBooleanAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN).getBooleanValue() == value1a);
+ }
+
+ // Now re-read back the object
+ {
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SIGN));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN).isBooleanAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN).getBooleanValue() == value1a);
+ }
+}
+
+void test_a_dbobject_with_an_object::can_refresh_attributes()
+{
+ bool value1 = true;
+ bool value1a = false;
+ ByteString value2 = "BDEBDBEDBBDBEBDEBE792759537328";
+ ByteString value2a = "466487346943785684957634";
+ ByteString value3 = "0102010201020102010201020102010201020102";
+ std::set<CK_MECHANISM_TYPE> value4;
+ value4.insert(CKM_SHA256);
+ value4.insert(CKM_SHA512);
+ std::set<CK_MECHANISM_TYPE> value4a;
+ value4a.insert(CKM_SHA384);
+ value4a.insert(CKM_SHA512);
+
+ // Create the test object
+ {
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr4(value4);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SIGN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SUBJECT, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ALLOWED_MECHANISMS, attr4));
+ }
+
+ // Now read back the object
+ {
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SIGN));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SUBJECT));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_ALLOWED_MECHANISMS));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBJECT).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN).getBooleanValue());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBJECT).getByteStringValue() == value2);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4);
+
+ OSAttribute attr1(value1a);
+ OSAttribute attr2(value2a);
+ OSAttribute attr4(value4a);
+
+ // Change the attributes
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SIGN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SUBJECT, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ALLOWED_MECHANISMS, attr4));
+
+ // Check the attributes
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBJECT).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN).getBooleanValue() == value1a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBJECT).getByteStringValue() == value2a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4a);
+
+ // Open the object a second time
+ DBObject testObject2(connection);
+ CPPUNIT_ASSERT(testObject2.find(1));
+ CPPUNIT_ASSERT(testObject2.isValid());
+
+ // Check the attributes on the second instance
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_SIGN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_SUBJECT).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_SIGN).getBooleanValue() == value1a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_SUBJECT).getByteStringValue() == value2a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4a);
+
+ // Add an attribute on the second object
+ OSAttribute attr3(value3);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ID, attr3));
+
+ // Check the attribute
+ CPPUNIT_ASSERT(testObject2.attributeExists(CKA_ID));
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ID).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ID).getByteStringValue() == value3);
+
+ // Now check that the first instance also knows about it
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_ID));
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ID).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ID).getByteStringValue() == value3);
+ }
+}
+
+void test_a_dbobject_with_an_object::should_cleanup_statements_during_transactions()
+{
+ // Create an object for accessing object 1 on the first connection.
+ DBObject testObject(connection);
+ // check transaction start(ro)/abort sequence
+ CPPUNIT_ASSERT(testObject.startTransaction(OSObject::ReadOnly));
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+ CPPUNIT_ASSERT(testObject.abortTransaction());
+}
+
+void test_a_dbobject_with_an_object::should_use_transactions()
+{
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ bool value1 = true;
+ unsigned long value2 = 0x87654321;
+ unsigned long value3 = 0xBDEBDBED;
+ ByteString value4 = "AAAAAAAAAAAAAAAFFFFFFFFFFFFFFF";
+ std::set<CK_MECHANISM_TYPE> value5;
+ value5.insert(CKM_SHA256);
+ value5.insert(CKM_SHA512);
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+ OSAttribute attr5(value5);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ID, attr4));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ALLOWED_MECHANISMS, attr5));
+
+ // Create secondary instance for the same object.
+ // This needs to have a different connection to the database to simulate
+ // another process accessing the data.
+ DBObject testObject2(connection2);
+ CPPUNIT_ASSERT(testObject2.find(1));
+ CPPUNIT_ASSERT(testObject2.isValid());
+
+ // Check that it has the same attributes
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ID).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ // Check that the attributes have the same values as set on testObject.
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).getBooleanValue() == value1);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE_BITS).getUnsignedLongValue() == value3);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ID).getByteStringValue() == value4);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value5);
+
+ // New values
+ bool value1a = false;
+ unsigned long value2a = 0x12345678;
+ unsigned long value3a = 0xABABABAB;
+ ByteString value4a = "EDEDEDEDEDEDEDEDEDEDEDEDEDEDED";
+ std::set<CK_MECHANISM_TYPE> value5a;
+ value5a.insert(CKM_SHA384);
+ value5a.insert(CKM_SHA512);
+
+ OSAttribute attr1a(value1a);
+ OSAttribute attr2a(value2a);
+ OSAttribute attr3a(value3a);
+ OSAttribute attr4a(value4a);
+ OSAttribute attr5a(value5a);
+
+ // Start transaction on object
+ CPPUNIT_ASSERT(testObject.startTransaction(DBObject::ReadWrite));
+
+ // Change the attributes
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1a));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2a));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3a));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ID, attr4a));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ALLOWED_MECHANISMS, attr5a));
+
+ // Verify that the attributes were set
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ID).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == value1a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).getUnsignedLongValue() == value3a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ID).getByteStringValue() == value4a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value5a);
+
+ // Verify that they are unchanged on the other instance
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ID).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).getBooleanValue() == value1);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE_BITS).getUnsignedLongValue() == value3);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ID).getByteStringValue() == value4);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value5);
+
+ // Commit the transaction
+ CPPUNIT_ASSERT(testObject.commitTransaction());
+
+ // Verify that non-modifiable attributes did not propagate but modifiable attributes
+ // have now changed on the other instance
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ID).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ // NOTE: 3 attributes below cannot be modified after creation and therefore are not required to propagate.
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).getBooleanValue() != value1a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() != value2a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE_BITS).getUnsignedLongValue() != value3a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() != value5a);
+
+ // CKA_ID attribute can be modified after creation and therefore should have propagated.
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ID).getByteStringValue() == value4a);
+
+ // Start transaction on object
+ CPPUNIT_ASSERT(testObject.startTransaction(DBObject::ReadWrite));
+
+ // Change the attributes
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ID, attr4));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ALLOWED_MECHANISMS, attr5));
+
+ // Verify that the attributes were set
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ID).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == value1);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).getUnsignedLongValue() == value3);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ID).getByteStringValue() == value4);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value5);
+
+ // Create a fresh third instance for the same object to force the data to be retrieved from the database.
+ DBObject testObject3(connection2);
+ CPPUNIT_ASSERT(testObject3.find(1));
+ CPPUNIT_ASSERT(testObject3.isValid());
+
+ // Verify that they are unchanged on the other instance, while the transaction is still in progress.
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_VALUE_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_ID).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ // Verify that the attributes from the database are still hodling the same value as when the transaction started.
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_TOKEN).getBooleanValue() == value1a);
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2a);
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_VALUE_BITS).getUnsignedLongValue() == value3a);
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_ID).getByteStringValue() == value4a);
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value5a);
+
+ // Abort the transaction
+ CPPUNIT_ASSERT(testObject.abortTransaction());
+
+ // Verify that after aborting the transaction the values in testObject have reverted back to their
+ // original state.
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ID).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ // After aborting a transaction the testObject should be back to pre transaction state.
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == value1a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).getUnsignedLongValue() == value3a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ID).getByteStringValue() == value4a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value5a);
+
+ // Verify that testObject3 still has the original values.
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_VALUE_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_ID).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ // Verify that testObject3 still has the original values.
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_TOKEN).getBooleanValue() == value1a);
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2a);
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_VALUE_BITS).getUnsignedLongValue() == value3a);
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_ID).getByteStringValue() == value4a);
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value5a);
+}
+
+void test_a_dbobject_with_an_object::should_fail_to_delete()
+{
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+ // We don't attach the object to a token, and therefore should not be able to destroy it.
+ CPPUNIT_ASSERT(!testObject.destroyObject());
+}
+
diff --git a/SoftHSMv2/src/lib/object_store/test/DBObjectTests.h b/SoftHSMv2/src/lib/object_store/test/DBObjectTests.h
new file mode 100644
index 0000000..136fa81
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/DBObjectTests.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2013 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DBObjectTests.h
+
+ Contains test cases to test the database token object implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DBOBJECTTESTS_H
+#define _SOFTHSM_V2_DBOBJECTTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "DB.h"
+
+class test_a_dbobject : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(test_a_dbobject);
+ CPPUNIT_TEST(should_be_insertable);
+ CPPUNIT_TEST(should_be_selectable);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void setUp();
+ void tearDown();
+
+ void should_be_insertable();
+ void should_be_selectable();
+
+protected:
+ DB::Connection *connection;
+ DB::Connection *connection2;
+
+private:
+};
+
+class test_a_dbobject_with_an_object : public test_a_dbobject
+{
+ CPPUNIT_TEST_SUITE(test_a_dbobject_with_an_object);
+ CPPUNIT_TEST(should_store_boolean_attributes);
+ CPPUNIT_TEST(should_store_unsigned_long_attributes);
+ CPPUNIT_TEST(should_store_binary_attributes);
+ CPPUNIT_TEST(should_store_mechtypeset_attributes);
+ CPPUNIT_TEST(should_store_attrmap_attributes);
+ CPPUNIT_TEST(should_store_mixed_attributes);
+ CPPUNIT_TEST(should_store_double_attributes);
+ CPPUNIT_TEST(can_refresh_attributes);
+ CPPUNIT_TEST(should_cleanup_statements_during_transactions);
+ CPPUNIT_TEST(should_use_transactions);
+ CPPUNIT_TEST(should_fail_to_delete);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void setUp();
+ void tearDown();
+
+ void should_store_boolean_attributes();
+ void should_store_unsigned_long_attributes();
+ void should_store_binary_attributes();
+ void should_store_mechtypeset_attributes();
+ void should_store_attrmap_attributes();
+ void should_store_mixed_attributes();
+ void should_store_double_attributes();
+ void can_refresh_attributes();
+ void should_cleanup_statements_during_transactions();
+ void should_use_transactions();
+ void should_fail_to_delete();
+};
+
+#endif // !_SOFTHSM_V2_DBOBJECTTESTS_H
diff --git a/SoftHSMv2/src/lib/object_store/test/DBTests.cpp b/SoftHSMv2/src/lib/object_store/test/DBTests.cpp
new file mode 100644
index 0000000..d787a83
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/DBTests.cpp
@@ -0,0 +1,648 @@
+/*
+ * Copyright (c) 2013 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DBTests.cpp
+
+ Contains lowest level test cases for the database backend implementation.
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "DBTests.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(test_a_db);
+
+static int dummy_print(const char *, va_list )
+{
+ return 0;
+}
+
+void test_a_db::setUp()
+{
+ CPPUNIT_ASSERT(!system("mkdir testdir"));
+ null = NULL;
+}
+
+void test_a_db::tearDown()
+{
+#ifndef _WIN32
+ CPPUNIT_ASSERT(!system("rm -rf testdir"));
+#else
+ CPPUNIT_ASSERT(!system("rmdir /s /q testdir 2> nul"));
+#endif
+}
+
+void test_a_db::checks_for_empty_connection_parameters()
+{
+ DB::LogErrorHandler eh = DB::setLogErrorHandler(dummy_print);
+
+ DB::Connection *connection = DB::Connection::Create("","TestToken");
+ CPPUNIT_ASSERT_EQUAL(connection, null);
+
+ connection = DB::Connection::Create("testdir","");
+ CPPUNIT_ASSERT_EQUAL(connection, null);
+
+ connection = DB::Connection::Create("","");
+ CPPUNIT_ASSERT_EQUAL(connection, null);
+
+ DB::setLogErrorHandler(eh);
+}
+
+void test_a_db::can_be_connected_to_database()
+{
+
+ DB::Connection *connection = DB::Connection::Create("testdir","TestToken");
+ CPPUNIT_ASSERT(connection != null);
+ bool isConnected = connection->connect();
+ delete connection;
+ CPPUNIT_ASSERT(isConnected);
+#ifndef _WIN32
+ CPPUNIT_ASSERT_EQUAL(system("test -f ./testdir/TestToken"), 0);
+#else
+ CPPUNIT_ASSERT(GetFileAttributes("testdir\\TestToken") != INVALID_FILE_ATTRIBUTES);
+#endif
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(test_a_db_with_a_connection);
+
+void test_a_db_with_a_connection::setUp()
+{
+ test_a_db::setUp();
+ connection = DB::Connection::Create("testdir","TestToken");
+ CPPUNIT_ASSERT(connection != null);
+ CPPUNIT_ASSERT(connection->connect());
+}
+
+void test_a_db_with_a_connection::tearDown()
+{
+ CPPUNIT_ASSERT(connection != null);
+ connection->close();
+ delete connection;
+ test_a_db::tearDown();
+}
+
+void test_a_db_with_a_connection::can_prepare_statements()
+{
+ DB::Statement statement = connection->prepare("PRAGMA database_list;");
+ CPPUNIT_ASSERT(statement.isValid());
+}
+
+void test_a_db_with_a_connection::can_perform_statements()
+{
+ DB::Statement statement = connection->prepare("PRAGMA database_list;");
+ CPPUNIT_ASSERT(statement.isValid());
+ DB::Result result = connection->perform(statement);
+ CPPUNIT_ASSERT(result.isValid());
+ // only expect a single row in the result, so nextRow should now fail
+ CPPUNIT_ASSERT(!result.nextRow());
+}
+
+void test_a_db_with_a_connection::maintains_correct_refcounts()
+{
+ DB::Statement statement = connection->prepare("PRAGMA database_list;");
+ CPPUNIT_ASSERT_EQUAL(statement.refcount(), 1);
+ {
+ DB::Statement statement1 = statement;
+ DB::Statement statement2 = statement;
+ CPPUNIT_ASSERT_EQUAL(statement.refcount(), 3);
+ CPPUNIT_ASSERT(statement1.isValid());
+ CPPUNIT_ASSERT(statement2.isValid());
+ }
+ CPPUNIT_ASSERT(statement.isValid());
+ CPPUNIT_ASSERT_EQUAL(statement.refcount(), 1);
+
+ DB::Result result = connection->perform(statement);
+ CPPUNIT_ASSERT(result.isValid());
+
+ // Statement is referenced by the result because it provides the query record cursor state.
+ CPPUNIT_ASSERT_EQUAL(statement.refcount(), 2);
+
+ result = DB::Result();
+ CPPUNIT_ASSERT_EQUAL(statement.refcount(), 1);
+}
+void test_a_db_with_a_connection::can_create_tables()
+{
+ CPPUNIT_ASSERT(!connection->tableExists("object"));
+ DB::Statement cr_object = connection->prepare("create table object (id integer primary key autoincrement);");
+ CPPUNIT_ASSERT(connection->execute(cr_object));
+ CPPUNIT_ASSERT(connection->tableExists("object"));
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(test_a_db_with_a_connection_with_tables);
+
+void test_a_db_with_a_connection_with_tables::setUp()
+{
+ test_a_db_with_a_connection::setUp();
+ can_create_tables();
+
+ // attribute_text
+ CPPUNIT_ASSERT(!connection->tableExists("attribute_text"));
+ DB::Statement cr_attr_text = connection->prepare(
+ "create table attribute_text ("
+ "value text,"
+ "type integer,"
+ "object_id integer references object(id) on delete cascade,"
+ "id integer primary key autoincrement)"
+ );
+ CPPUNIT_ASSERT(connection->execute(cr_attr_text));
+ CPPUNIT_ASSERT(connection->tableExists("attribute_text"));
+
+ // attribute_integer
+ CPPUNIT_ASSERT(!connection->tableExists("attribute_integer"));
+ DB::Statement cr_attr_integer = connection->prepare(
+ "create table attribute_integer ("
+ "value integer,"
+ "type integer,"
+ "object_id integer references object(id) on delete cascade,"
+ "id integer primary key autoincrement)"
+ );
+ CPPUNIT_ASSERT(connection->execute(cr_attr_integer));
+ CPPUNIT_ASSERT(connection->tableExists("attribute_integer"));
+
+ // attribute_blob
+ CPPUNIT_ASSERT(!connection->tableExists("attribute_blob"));
+ DB::Statement cr_attr_blob = connection->prepare(
+ "create table attribute_blob ("
+ "value blob,"
+ "type integer,"
+ "object_id integer references object(id) on delete cascade,"
+ "id integer primary key autoincrement)"
+ );
+ CPPUNIT_ASSERT(connection->execute(cr_attr_blob));
+ CPPUNIT_ASSERT(connection->tableExists("attribute_blob"));
+
+ // attribute_boolean
+ CPPUNIT_ASSERT(!connection->tableExists("attribute_boolean"));
+ DB::Statement cr_attr_boolean = connection->prepare(
+ "create table attribute_boolean ("
+ "value boolean,"
+ "type integer,"
+ "object_id integer references object(id) on delete cascade,"
+ "id integer primary key autoincrement)"
+ );
+ CPPUNIT_ASSERT(connection->execute(cr_attr_boolean));
+ CPPUNIT_ASSERT(connection->tableExists("attribute_boolean"));
+
+ // attribute_datetime
+ CPPUNIT_ASSERT(!connection->tableExists("attribute_datetime"));
+ DB::Statement cr_attr_datetime = connection->prepare(
+ "create table attribute_datetime ("
+ "value datetime,"
+ "type integer,"
+ "object_id integer references object(id) on delete cascade,"
+ "id integer primary key autoincrement)"
+ );
+ CPPUNIT_ASSERT(connection->execute(cr_attr_datetime));
+ CPPUNIT_ASSERT(connection->tableExists("attribute_datetime"));
+
+ // attribute_real
+ CPPUNIT_ASSERT(!connection->tableExists("attribute_real"));
+ DB::Statement cr_attr_real = connection->prepare(
+ "create table attribute_real ("
+ "value real,"
+ "type integer,"
+ "object_id integer references object(id) on delete cascade,"
+ "id integer primary key autoincrement)"
+ );
+ CPPUNIT_ASSERT(connection->execute(cr_attr_real));
+ CPPUNIT_ASSERT(connection->tableExists("attribute_real"));
+}
+
+void test_a_db_with_a_connection_with_tables::tearDown()
+{
+ test_a_db_with_a_connection::tearDown();
+}
+
+void test_a_db_with_a_connection_with_tables::can_insert_records()
+{
+ DB::Statement statement = connection->prepare("insert into object default values");
+ CPPUNIT_ASSERT(connection->execute(statement));
+ long long object_id = connection->lastInsertRowId();
+ CPPUNIT_ASSERT(object_id != 0);
+
+ statement = connection->prepare(
+ "insert into attribute_text (value,type,object_id) values ('%s',%d,%lld)",
+ "testing testing testing",
+ 1234,
+ object_id);
+ CPPUNIT_ASSERT(connection->execute(statement));
+}
+
+void test_a_db_with_a_connection_with_tables::can_retrieve_records()
+{
+ can_insert_records();
+
+ DB::Statement statement = connection->prepare(
+ "select value from attribute_text as t where t.type=%d",
+ 1234);
+ DB::Result result = connection->perform(statement);
+ CPPUNIT_ASSERT_EQUAL(std::string(result.getString(1)), std::string("testing testing testing"));
+}
+
+void test_a_db_with_a_connection_with_tables::can_cascade_delete_objects_and_attributes()
+{
+ can_insert_records();
+
+ DB::Statement statement = connection->prepare("select id from object");
+ DB::Result result = connection->perform(statement);
+ CPPUNIT_ASSERT(result.isValid());
+
+ long long object_id = result.getLongLong(1);
+
+ statement = connection->prepare("delete from object where id=%lld",object_id);
+ CPPUNIT_ASSERT(connection->execute(statement));
+
+ statement = connection->prepare("select * from attribute_text where object_id=%lld",object_id);
+ result = connection->perform(statement);
+
+ // Check cascade delete was successful.
+ CPPUNIT_ASSERT(!result.isValid());
+}
+
+
+void test_a_db_with_a_connection_with_tables::can_update_text_attribute()
+{
+ can_insert_records();
+
+ // query all objects
+ DB::Statement statement = connection->prepare("select id from object");
+ CPPUNIT_ASSERT(statement.isValid());
+ DB::Result result = connection->perform(statement);
+ CPPUNIT_ASSERT(result.isValid());
+
+ long long object_id = result.getLongLong(1); // field indices start at 1
+
+ statement = connection->prepare(
+ "update attribute_text set value='test test test' where type=%d and object_id=%lld",
+ 1234,
+ object_id);
+ CPPUNIT_ASSERT(statement.isValid());
+ CPPUNIT_ASSERT(connection->execute(statement));
+}
+
+void test_a_db_with_a_connection_with_tables::can_update_text_attribute_bound_value()
+{
+ can_insert_records();
+
+ // query all objects
+ DB::Statement statement = connection->prepare("select id from object");
+ CPPUNIT_ASSERT(statement.isValid());
+ DB::Result result = connection->perform(statement);
+ CPPUNIT_ASSERT(result.isValid());
+
+ long long object_id = result.getLongLong(1); // field indices start at 1
+
+ statement = connection->prepare(
+ "update attribute_text set value=? where type=%d and object_id=%lld",
+ 1234,
+ object_id);
+ CPPUNIT_ASSERT(statement.isValid());
+
+ std::string msg("testing quote ' and accents é.");
+
+ CPPUNIT_ASSERT(DB::Bindings(statement).bindText(1,msg.c_str(),msg.size(),NULL));
+ CPPUNIT_ASSERT(connection->execute(statement));
+
+ statement = connection->prepare(
+ "select value from attribute_text as t where t.type=%d and t.object_id=%lld",
+ 1234,
+ object_id);
+ result = connection->perform(statement);
+ CPPUNIT_ASSERT_EQUAL(std::string(result.getString(1)), msg);
+}
+
+void test_a_db_with_a_connection_with_tables::can_update_integer_attribute_bound_value()
+{
+ // insert new object
+ DB::Statement statement = connection->prepare(
+ "insert into object default values");
+ CPPUNIT_ASSERT(statement.isValid());
+ CPPUNIT_ASSERT(connection->execute(statement));
+ long long object_id = connection->lastInsertRowId();
+ CPPUNIT_ASSERT(object_id != 0);
+
+ // insert integer attribute
+ statement = connection->prepare(
+ "insert into attribute_integer (value,type,object_id) values (%lld,%d,%lld)",
+ 1111,
+ 1235,
+ object_id);
+ CPPUNIT_ASSERT(statement.isValid());
+ CPPUNIT_ASSERT(connection->execute(statement));
+
+ // prepare update integer attribute statement
+ statement = connection->prepare(
+ "update attribute_integer set value=? where type=%d and object_id=%lld",
+ 1235,
+ object_id);
+ CPPUNIT_ASSERT(statement.isValid());
+
+ // bind long long value to the parameter an update the record
+ CPPUNIT_ASSERT(DB::Bindings(statement).bindInt64(1,2222));
+ CPPUNIT_ASSERT(connection->execute(statement));
+
+ // Retrieve the value from the record
+ DB::Statement retrieveStmt = connection->prepare(
+ "select value from attribute_integer as t where t.type=%d and t.object_id=%lld",
+ 1235,
+ object_id);
+ CPPUNIT_ASSERT(retrieveStmt.isValid());
+ DB::Result result = connection->perform(retrieveStmt);
+ CPPUNIT_ASSERT_EQUAL(result.getLongLong(1), (long long)2222);
+
+ // verify that binding to a parameter before resetting the statement will fail.
+ DB::LogErrorHandler eh = DB::setLogErrorHandler(dummy_print);
+ DB::Bindings bindings(statement);
+ CPPUNIT_ASSERT(!bindings.bindInt(1,3333));
+ DB::setLogErrorHandler(eh);
+
+ // reset statement and bind another value to the statement
+ CPPUNIT_ASSERT(bindings.reset());
+ CPPUNIT_ASSERT(bindings.bindInt(1,3333));
+
+ // perform the update statement again with the newly bound value
+ CPPUNIT_ASSERT(connection->execute(statement));
+
+ // reset the retrieve statement and perform it again to get the latest value of the integer attribute
+ CPPUNIT_ASSERT(retrieveStmt.reset());
+ result = connection->perform(retrieveStmt);
+ CPPUNIT_ASSERT(result.isValid());
+ CPPUNIT_ASSERT_EQUAL(result.getLongLong(1), (long long)3333);
+}
+
+void test_a_db_with_a_connection_with_tables::can_update_blob_attribute_bound_value()
+{
+ // insert new object
+ DB::Statement statement = connection->prepare(
+ "insert into object default values");
+ CPPUNIT_ASSERT(statement.isValid());
+ CPPUNIT_ASSERT(connection->execute(statement));
+ long long object_id = connection->lastInsertRowId();
+ CPPUNIT_ASSERT(object_id != 0);
+
+ // insert blob attribute
+ statement = connection->prepare(
+ "insert into attribute_blob (value,type,object_id) values (X'012345',%d,%lld)",
+ 1236,
+ object_id);
+ CPPUNIT_ASSERT(statement.isValid());
+ CPPUNIT_ASSERT(connection->execute(statement));
+
+ // prepare update blob attribute statement
+ statement = connection->prepare(
+ "update attribute_blob set value=? where type=%d and object_id=%lld",
+ 1236,
+ object_id);
+ CPPUNIT_ASSERT(statement.isValid());
+
+ // bind blob (with embedded zero!) to the parameter
+ const char data[] = {10,11,0,12,13,14,15,16};
+ std::string msg(data,sizeof(data));
+ CPPUNIT_ASSERT(DB::Bindings(statement).bindBlob(1,msg.data(),msg.size(),NULL));
+
+ // update the blob value of the attribute
+ CPPUNIT_ASSERT(connection->execute(statement));
+
+ // retrieve the blob value from the attribute
+ statement = connection->prepare(
+ "select value from attribute_blob as t where t.type=%d and t.object_id=%lld",
+ 1236,
+ object_id);
+ CPPUNIT_ASSERT(statement.isValid());
+ DB::Result result = connection->perform(statement);
+ CPPUNIT_ASSERT(result.isValid());
+
+ // check that the retrieved blob value matches the original data.
+ CPPUNIT_ASSERT_EQUAL(result.getFieldLength(1), sizeof(data));
+ std::string msgstored((const char *)result.getBinary(1),result.getFieldLength(1));
+ CPPUNIT_ASSERT_EQUAL(msg, msgstored);
+}
+
+
+void test_a_db_with_a_connection_with_tables::will_not_insert_non_existing_attribute_on_update()
+{
+ DB::Statement statement;
+ DB::Result result;
+
+ // Insert new object
+ statement = connection->prepare(
+ "insert into object default values");
+ CPPUNIT_ASSERT(statement.isValid());
+ CPPUNIT_ASSERT(connection->execute(statement));
+ long long object_id = connection->lastInsertRowId();
+ CPPUNIT_ASSERT(object_id != 0);
+
+ // Updating an attribute before it is created will succeed, but will not insert an attribute.
+ statement = connection->prepare(
+ "update attribute_boolean set value=1 where type=%d and object_id=%lld",
+ 1237,
+ object_id);
+ CPPUNIT_ASSERT(statement.isValid());
+ CPPUNIT_ASSERT(connection->execute(statement));
+
+ // Retrieve the boolean value from the attribute should fail
+ statement = connection->prepare(
+ "select value from attribute_boolean as t where t.type=%d and t.object_id=%lld",
+ 1237,
+ object_id);
+ CPPUNIT_ASSERT(statement.isValid());
+ result = connection->perform(statement);
+ CPPUNIT_ASSERT(!result.isValid());
+}
+
+
+void test_a_db_with_a_connection_with_tables::can_update_boolean_attribute_bound_value()
+{
+ //SQLite doesn't have a boolean data type, use 0 (false) and 1 (true)
+
+ DB::Statement statement;
+ DB::Result result;
+
+ // Insert new object
+ statement = connection->prepare(
+ "insert into object default values");
+ CPPUNIT_ASSERT(statement.isValid());
+ CPPUNIT_ASSERT(connection->execute(statement));
+ long long object_id = connection->lastInsertRowId();
+ CPPUNIT_ASSERT(object_id != 0);
+
+ // insert boolean attribute
+ statement = connection->prepare(
+ "insert into attribute_boolean (value,type,object_id) values (1,%d,%lld)",
+ 1237,
+ object_id);
+ CPPUNIT_ASSERT(statement.isValid());
+ CPPUNIT_ASSERT(connection->execute(statement));
+
+ // prepare update boolean attribute statement
+ statement = connection->prepare(
+ "update attribute_boolean set value=? where type=%d and object_id=%lld",
+ 1237,
+ object_id);
+ CPPUNIT_ASSERT(statement.isValid());
+
+ // Bind 0 (false) to the first parameter
+ CPPUNIT_ASSERT(DB::Bindings(statement).bindInt(1,0));
+
+ // Execute the statement to update the attribute value.
+ CPPUNIT_ASSERT(connection->execute(statement));
+
+ // Retrieve the boolean value from the attribute
+ statement = connection->prepare(
+ "select value from attribute_boolean as t where t.type=%d and t.object_id=%lld",
+ 1237,
+ object_id);
+ CPPUNIT_ASSERT(statement.isValid());
+ result = connection->perform(statement);
+ CPPUNIT_ASSERT(result.isValid());
+
+ // check that the retrieved value matches the original value
+ CPPUNIT_ASSERT_EQUAL(result.getInt(1), 0);
+}
+
+
+void test_a_db_with_a_connection_with_tables::can_update_real_attribute_bound_value()
+{
+ // insert new object
+ DB::Statement statement = connection->prepare(
+ "insert into object default values");
+ CPPUNIT_ASSERT(statement.isValid());
+ CPPUNIT_ASSERT(connection->execute(statement));
+ long long object_id = connection->lastInsertRowId();
+ CPPUNIT_ASSERT(object_id != 0);
+
+ // insert real value
+ statement = connection->prepare(
+ "insert into attribute_real (value,type,object_id) values(%f,%d,%lld)",
+ 1.238,
+ 1238,
+ object_id);
+ CPPUNIT_ASSERT(statement.isValid());
+ CPPUNIT_ASSERT(connection->execute(statement));
+
+ // prepare update real attribute statement
+ statement = connection->prepare(
+ "update attribute_real set value=? where type=%d and object_id=%lld",
+ 1238,
+ object_id);
+ CPPUNIT_ASSERT(statement.isValid());
+
+ // Bind 3333.3333 to the first parameter
+ CPPUNIT_ASSERT(DB::Bindings(statement).bindDouble(1,3333.3333));
+
+ // Execute the statement to update the attribute value
+ CPPUNIT_ASSERT(connection->execute(statement));
+
+ // Retrieve the double value from the attribute
+ statement = connection->prepare(
+ "select value from attribute_real as t where t.type=%d and t.object_id=%lld",
+ 1238,
+ object_id);
+ CPPUNIT_ASSERT(statement.isValid());
+ DB::Result result = connection->perform(statement);
+ CPPUNIT_ASSERT(result.isValid());
+
+ // check that the retrieved value matches the original value.
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(result.getDouble(1), 3333.3333, 0.00001);
+}
+
+void test_a_db_with_a_connection_with_tables::supports_transactions()
+{
+ DB::LogErrorHandler eh = DB::setLogErrorHandler(dummy_print);
+ CPPUNIT_ASSERT(!connection->rollbackTransaction());
+ DB::setLogErrorHandler(eh);
+
+ CPPUNIT_ASSERT(connection->beginTransactionRW());
+ CPPUNIT_ASSERT(connection->rollbackTransaction());
+
+ eh = DB::setLogErrorHandler(dummy_print);
+ CPPUNIT_ASSERT(!connection->commitTransaction());
+ DB::setLogErrorHandler(eh);
+
+ CPPUNIT_ASSERT(connection->beginTransactionRW());
+ can_update_real_attribute_bound_value();
+ CPPUNIT_ASSERT(connection->commitTransaction());
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(test_a_db_with_a_connection_with_tables_with_a_second_connection_open);
+
+void test_a_db_with_a_connection_with_tables_with_a_second_connection_open::setUp()
+{
+ test_a_db_with_a_connection_with_tables::setUp();
+ connection2 = DB::Connection::Create("testdir","TestToken");
+ CPPUNIT_ASSERT(connection2 != null);
+ CPPUNIT_ASSERT(connection2->connect());
+ connection2->setBusyTimeout(10);
+}
+
+void test_a_db_with_a_connection_with_tables_with_a_second_connection_open::tearDown()
+{
+ CPPUNIT_ASSERT(connection2 != null);
+ connection2->close();
+ delete connection2;
+ test_a_db_with_a_connection_with_tables::tearDown();
+}
+
+void test_a_db_with_a_connection_with_tables_with_a_second_connection_open::handles_nested_transactions()
+{
+ DB::LogErrorHandler eh = DB::setLogErrorHandler(dummy_print);
+
+ DB::Connection *connection1 = connection;
+
+ CPPUNIT_ASSERT(connection1->beginTransactionRW());
+
+ CPPUNIT_ASSERT(connection2->beginTransactionRO());
+ CPPUNIT_ASSERT(connection2->rollbackTransaction());
+ CPPUNIT_ASSERT(!connection2->beginTransactionRW());
+
+ CPPUNIT_ASSERT(connection1->commitTransaction());
+
+ DB::setLogErrorHandler(eh);
+}
+
+
+void test_a_db_with_a_connection_with_tables_with_a_second_connection_open::supports_transactions_with_other_connections_open()
+{
+ CPPUNIT_ASSERT(connection2->beginTransactionRO());
+
+ supports_transactions();
+
+ // Retrieve the double value from the attribute
+ DB::Statement statement = connection2->prepare(
+ "select value from attribute_real as t where t.type=%d and t.object_id=%lld",
+ 1238,
+ connection->lastInsertRowId());
+ CPPUNIT_ASSERT(statement.isValid());
+ DB::Result result = connection2->perform(statement);
+ CPPUNIT_ASSERT(result.isValid());
+
+ // check that the retrieved value matches the original value.
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(result.getDouble(1), 3333.3333, 0.00001);
+
+ CPPUNIT_ASSERT(connection2->commitTransaction());
+}
diff --git a/SoftHSMv2/src/lib/object_store/test/DBTests.h b/SoftHSMv2/src/lib/object_store/test/DBTests.h
new file mode 100644
index 0000000..422cbce
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/DBTests.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2013 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DBTests.h
+
+ Contains lowest level test cases for the database backend implementation.
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DBTESTS_H
+#define _SOFTHSM_V2_DBTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "DB.h"
+
+class test_a_db : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(test_a_db);
+ CPPUNIT_TEST(checks_for_empty_connection_parameters);
+ CPPUNIT_TEST(can_be_connected_to_database);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void checks_for_empty_connection_parameters();
+ void can_be_connected_to_database();
+
+ void setUp();
+ void tearDown();
+
+protected:
+ DB::Connection *null;
+
+private:
+};
+
+class test_a_db_with_a_connection : public test_a_db
+{
+ CPPUNIT_TEST_SUITE(test_a_db_with_a_connection);
+ CPPUNIT_TEST(can_prepare_statements);
+ CPPUNIT_TEST(can_perform_statements);
+ CPPUNIT_TEST(maintains_correct_refcounts);
+ CPPUNIT_TEST(can_create_tables);
+ CPPUNIT_TEST_SUITE_END();
+public:
+ void setUp();
+ void tearDown();
+
+ void can_prepare_statements();
+ void can_perform_statements();
+ void maintains_correct_refcounts();
+ void can_create_tables();
+protected:
+ DB::Connection *connection;
+
+private:
+};
+
+class test_a_db_with_a_connection_with_tables : public test_a_db_with_a_connection
+{
+ CPPUNIT_TEST_SUITE(test_a_db_with_a_connection_with_tables);
+ CPPUNIT_TEST(can_insert_records);
+ CPPUNIT_TEST(can_retrieve_records);
+ CPPUNIT_TEST(can_cascade_delete_objects_and_attributes);
+ CPPUNIT_TEST(can_update_text_attribute);
+ CPPUNIT_TEST(can_update_text_attribute_bound_value);
+ CPPUNIT_TEST(can_update_integer_attribute_bound_value);
+ CPPUNIT_TEST(can_update_blob_attribute_bound_value);
+ CPPUNIT_TEST(will_not_insert_non_existing_attribute_on_update);
+ CPPUNIT_TEST(can_update_boolean_attribute_bound_value);
+ CPPUNIT_TEST(can_update_real_attribute_bound_value);
+ CPPUNIT_TEST(supports_transactions);
+ CPPUNIT_TEST_SUITE_END();
+public:
+ void setUp();
+ void tearDown();
+
+ void can_insert_records();
+ void can_retrieve_records();
+ void can_cascade_delete_objects_and_attributes();
+ void can_update_text_attribute();
+ void can_update_text_attribute_bound_value();
+ void can_update_integer_attribute_bound_value();
+ void can_update_blob_attribute_bound_value();
+ void will_not_insert_non_existing_attribute_on_update();
+ void can_update_boolean_attribute_bound_value();
+ void can_update_real_attribute_bound_value();
+ void supports_transactions();
+protected:
+
+private:
+};
+
+class test_a_db_with_a_connection_with_tables_with_a_second_connection_open : public test_a_db_with_a_connection_with_tables
+{
+ CPPUNIT_TEST_SUITE(test_a_db_with_a_connection_with_tables_with_a_second_connection_open);
+ CPPUNIT_TEST(handles_nested_transactions);
+ CPPUNIT_TEST(supports_transactions_with_other_connections_open);
+ CPPUNIT_TEST_SUITE_END();
+public:
+ void setUp();
+ void tearDown();
+
+ void handles_nested_transactions();
+ void supports_transactions_with_other_connections_open();
+protected:
+ DB::Connection *connection2;
+
+private:
+};
+
+#endif // !_SOFTHSM_V2_DBTESTS_H
diff --git a/SoftHSMv2/src/lib/object_store/test/DBTokenTests.cpp b/SoftHSMv2/src/lib/object_store/test/DBTokenTests.cpp
new file mode 100644
index 0000000..ab0cff1
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/DBTokenTests.cpp
@@ -0,0 +1,491 @@
+/*
+ * Copyright (c) 2013 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DBTokenTests.cpp
+
+ Contains test cases to test the database token implementation
+ *****************************************************************************/
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "DBTokenTests.h"
+#include "DBToken.h"
+#include "DB.h"
+
+#include <cstdio>
+
+#ifndef HAVE_SQLITE3_H
+#error expected sqlite3 to be available
+#endif
+
+CPPUNIT_TEST_SUITE_REGISTRATION(test_a_dbtoken);
+
+static int dummy_print(const char *, va_list )
+{
+ return 0;
+}
+
+void test_a_dbtoken::setUp()
+{
+ CPPUNIT_ASSERT(!system("mkdir testdir"));
+}
+
+void test_a_dbtoken::tearDown()
+{
+#ifndef _WIN32
+ CPPUNIT_ASSERT(!system("rm -rf testdir"));
+#else
+ CPPUNIT_ASSERT(!system("rmdir /s /q testdir 2> nul"));
+#endif
+}
+
+void test_a_dbtoken::should_be_creatable()
+{
+ ByteString label = "40414243"; // ABCD
+ ByteString serial = "0102030405060708";
+
+ ObjectStoreToken* newToken = new DBToken("testdir", "newToken", label, serial);
+
+ CPPUNIT_ASSERT(newToken != NULL);
+
+ CPPUNIT_ASSERT(newToken->isValid());
+
+ delete newToken;
+}
+
+void test_a_dbtoken::should_support_pin_setting_getting()
+{
+ // Create a new token
+ ByteString label = "40414243"; // ABCD
+ ByteString serial = "0102030405060708";
+
+ ObjectStoreToken* newToken = new DBToken("testdir", "newToken", label, serial);
+
+ CPPUNIT_ASSERT(newToken != NULL);
+
+ CPPUNIT_ASSERT(newToken->isValid());
+
+ // Check the flags
+ CK_ULONG flags;
+ CPPUNIT_ASSERT(newToken->getTokenFlags(flags));
+ CPPUNIT_ASSERT_EQUAL(flags, (CK_ULONG)( CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED | CKF_SO_PIN_LOCKED | CKF_SO_PIN_TO_BE_CHANGED));
+
+ // Set the SO PIN
+ ByteString soPIN = "3132333435363738"; // 12345678
+
+ CPPUNIT_ASSERT(newToken->setSOPIN(soPIN));
+
+ // Set the user PIN
+ ByteString userPIN = "31323334"; // 1234
+
+ CPPUNIT_ASSERT(newToken->setUserPIN(userPIN));
+
+ CPPUNIT_ASSERT(newToken->getTokenFlags(flags));
+ CPPUNIT_ASSERT_EQUAL(flags, (CK_ULONG)(CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED | CKF_USER_PIN_INITIALIZED));
+
+ delete newToken;
+
+ // Now reopen the newly created token
+ DBToken reopenedToken("testdir","newToken");
+
+ CPPUNIT_ASSERT(reopenedToken.isValid());
+
+ // Retrieve the flags, user PIN and so PIN
+ ByteString retrievedSOPIN, retrievedUserPIN;
+
+ CPPUNIT_ASSERT(reopenedToken.getSOPIN(retrievedSOPIN));
+ CPPUNIT_ASSERT(reopenedToken.getUserPIN(retrievedUserPIN));
+ CPPUNIT_ASSERT(reopenedToken.getTokenFlags(flags));
+
+ CPPUNIT_ASSERT(retrievedSOPIN == soPIN);
+ CPPUNIT_ASSERT(retrievedUserPIN == userPIN);
+ CPPUNIT_ASSERT_EQUAL(flags, (CK_ULONG)(CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED | CKF_USER_PIN_INITIALIZED));
+}
+
+void test_a_dbtoken::should_allow_object_enumeration()
+{
+ ByteString label = "40414243"; // ABCD
+ ByteString serial = "0102030405060708";
+ ByteString soPIN = "31323334"; // 1234
+ ByteString userPIN = "30303030"; // 0000
+ ByteString id[3] = { "112233445566", "AABBCCDDEEFF", "ABABABABABAB" };
+
+ {
+ // Instantiate a new token
+ ObjectStoreToken* newToken = new DBToken("testdir", "existingToken", label, serial);
+ CPPUNIT_ASSERT(newToken != NULL);
+ CPPUNIT_ASSERT(newToken->isValid());
+ CPPUNIT_ASSERT(newToken->setSOPIN(soPIN));
+ CPPUNIT_ASSERT(newToken->setUserPIN(userPIN));
+
+ // Test IDs
+ OSAttribute idAtt[3] = { id[0], id[1], id[2] };
+
+ // Create 3 objects on the token
+ OSObject* obj1 = newToken->createObject();
+ CPPUNIT_ASSERT(obj1 != NULL);
+ OSObject* obj2 = newToken->createObject();
+ CPPUNIT_ASSERT(obj2 != NULL);
+ OSObject* obj3 = newToken->createObject();
+ CPPUNIT_ASSERT(obj3 != NULL);
+
+ // Now set the IDs of the 3 objects
+ obj1->startTransaction(OSObject::ReadWrite);
+ CPPUNIT_ASSERT(obj1->setAttribute(CKA_ID, idAtt[0]));
+ obj1->commitTransaction();
+
+ obj2->startTransaction(OSObject::ReadWrite);
+ CPPUNIT_ASSERT(obj2->setAttribute(CKA_ID, idAtt[1]));
+ obj2->commitTransaction();
+
+ obj3->startTransaction(OSObject::ReadWrite);
+ CPPUNIT_ASSERT(obj3->setAttribute(CKA_ID, idAtt[2]));
+ obj3->commitTransaction();
+
+ delete newToken;
+ }
+
+ // Now open the token
+ DBToken existingToken("testdir","existingToken");
+
+ CPPUNIT_ASSERT(existingToken.isValid());
+
+ // Retrieve SO PIN, user PIN, label, serial number and flags
+ ByteString retrievedSOPIN, retrievedUserPIN, retrievedLabel, retrievedSerial;
+ CK_ULONG flags;
+
+ CPPUNIT_ASSERT(existingToken.getSOPIN(retrievedSOPIN));
+ CPPUNIT_ASSERT(existingToken.getUserPIN(retrievedUserPIN));
+ CPPUNIT_ASSERT(existingToken.getTokenLabel(retrievedLabel));
+ CPPUNIT_ASSERT(existingToken.getTokenSerial(retrievedSerial));
+ CPPUNIT_ASSERT(existingToken.getTokenFlags(flags));
+
+ CPPUNIT_ASSERT(retrievedSOPIN == soPIN);
+ CPPUNIT_ASSERT(retrievedUserPIN == userPIN);
+ CPPUNIT_ASSERT(retrievedLabel == label);
+ CPPUNIT_ASSERT(retrievedSerial == serial);
+ CPPUNIT_ASSERT_EQUAL(flags, (CK_ULONG)(CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED | CKF_USER_PIN_INITIALIZED));
+
+ // Check that the token contains 3 objects
+ CPPUNIT_ASSERT_EQUAL(existingToken.getObjects().size(), (size_t)3);
+
+ // Check that all the tokens are presented
+ bool present[3] = { false, false, false };
+ std::set<OSObject*> objects = existingToken.getObjects();
+
+ for (std::set<OSObject*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID).isByteStringAttribute());
+
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[0])
+ {
+ present[0] = true;
+ }
+ else if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[1])
+ {
+ present[1] = true;
+ }
+ else if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[2])
+ {
+ present[2] = true;
+ }
+ }
+
+ CPPUNIT_ASSERT(present[0]);
+ CPPUNIT_ASSERT(present[1]);
+ CPPUNIT_ASSERT(present[2]);
+}
+
+void test_a_dbtoken::should_fail_to_open_nonexistant_tokens()
+{
+ DBToken doesntExist("testdir","doesntExist");
+
+ CPPUNIT_ASSERT(!doesntExist.isValid());
+}
+
+void test_a_dbtoken::support_create_delete_objects()
+{
+ // Test IDs
+ ByteString id[5] = { "112233445566", "AABBCCDDEEFF", "ABABABABABAB", "557788991122", "005500550055" };
+ OSAttribute idAtt[5] = { id[0], id[1], id[2], id[3], id[4] };
+ ByteString label = "AABBCCDDEEFF";
+ ByteString serial = "1234567890";
+
+ // Instantiate a new token
+ ObjectStoreToken* testToken = new DBToken("testdir", "testToken", label, serial);
+ CPPUNIT_ASSERT(testToken != NULL);
+ CPPUNIT_ASSERT(testToken->isValid());
+
+ // Open the same token
+ DBToken sameToken("testdir","testToken");
+ CPPUNIT_ASSERT(sameToken.isValid());
+
+ // Create 3 objects on the token
+ OSObject* obj1 = testToken->createObject();
+ CPPUNIT_ASSERT(obj1 != NULL);
+ OSObject* obj2 = testToken->createObject();
+ CPPUNIT_ASSERT(obj2 != NULL);
+ OSObject* obj3 = testToken->createObject();
+ CPPUNIT_ASSERT(obj3 != NULL);
+
+ // Now set the IDs of the 3 objects
+ obj1->setAttribute(CKA_ID, idAtt[0]);
+ obj2->setAttribute(CKA_ID, idAtt[1]);
+ obj3->setAttribute(CKA_ID, idAtt[2]);
+
+ // Check that the token contains 3 objects
+ CPPUNIT_ASSERT_EQUAL(testToken->getObjects().size(), (size_t)3);
+
+ // Check that all three objects are distinct and present
+ std::set<OSObject*> objects = testToken->getObjects();
+ bool present1[3] = { false, false, false };
+
+ for (std::set<OSObject*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID).isByteStringAttribute());
+
+ for (int j = 0; j < 3; j++)
+ {
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[j])
+ {
+ present1[j] = true;
+ }
+ }
+ }
+
+ for (int j = 0; j < 3; j++)
+ {
+ CPPUNIT_ASSERT(present1[j]);
+ }
+
+ // Now check that the same objects are present in the other instance of the same token
+ std::set<OSObject*> otherObjects = sameToken.getObjects();
+ CPPUNIT_ASSERT_EQUAL(otherObjects.size(), (size_t)3);
+
+ bool present2[3] = { false, false, false };
+
+ for (std::set<OSObject*>::iterator i = otherObjects.begin(); i != otherObjects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID).isByteStringAttribute());
+
+ for (int j = 0; j < 3; j++)
+ {
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[j])
+ {
+ present2[j] = true;
+ }
+ }
+ }
+
+ for (int j = 0; j < 3; j++)
+ {
+ CPPUNIT_ASSERT(present2[j]);
+ }
+
+ // Now delete the second object
+ for (std::set<OSObject*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID).isByteStringAttribute());
+
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[1])
+ {
+ CPPUNIT_ASSERT(testToken->deleteObject(*i));
+ break;
+ }
+ }
+
+ // Verify that it was indeed removed
+ CPPUNIT_ASSERT_EQUAL(testToken->getObjects().size(),(size_t)2);
+
+ objects = testToken->getObjects();
+ bool present3[2] = { false, false };
+
+ for (std::set<OSObject*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID).isByteStringAttribute());
+
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[0])
+ {
+ present3[0] = true;
+ }
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[2])
+ {
+ present3[1] = true;
+ }
+ }
+
+ for (int j = 0; j < 2; j++)
+ {
+ CPPUNIT_ASSERT(present3[j]);
+ }
+
+ // Now check the other instance
+ CPPUNIT_ASSERT_EQUAL(sameToken.getObjects().size(), (size_t)2);
+
+ otherObjects = sameToken.getObjects();
+ bool present4[2] = { false, false };
+
+ for (std::set<OSObject*>::iterator i = otherObjects.begin(); i != otherObjects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID).isByteStringAttribute());
+
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[0])
+ {
+ present4[0] = true;
+ }
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[2])
+ {
+ present4[1] = true;
+ }
+ }
+
+ for (int j = 0; j < 2; j++)
+ {
+ CPPUNIT_ASSERT(present4[j]);
+ }
+
+
+ // Release the test token
+ delete testToken;
+}
+
+void test_a_dbtoken::support_clearing_a_token()
+{
+ // Create a new token
+ ByteString label = "40414243"; // ABCD
+ ByteString serial = "0102030405060708";
+
+ ObjectStoreToken* newToken = new DBToken("testdir", "newToken", label, serial);
+
+ CPPUNIT_ASSERT(newToken != NULL);
+ CPPUNIT_ASSERT(newToken->isValid());
+
+ // Check the flags
+ CK_ULONG flags;
+ CPPUNIT_ASSERT(newToken->getTokenFlags(flags));
+ CPPUNIT_ASSERT_EQUAL(flags, (CK_ULONG)(CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED | CKF_SO_PIN_LOCKED | CKF_SO_PIN_TO_BE_CHANGED));
+
+ // Set the SO PIN
+ ByteString soPIN = "3132333435363738"; // 12345678
+
+ CPPUNIT_ASSERT(newToken->setSOPIN(soPIN));
+
+ // Set the user PIN
+ ByteString userPIN = "31323334"; // 1234
+
+ CPPUNIT_ASSERT(newToken->setUserPIN(userPIN));
+
+ CPPUNIT_ASSERT(newToken->getTokenFlags(flags));
+ CPPUNIT_ASSERT_EQUAL(flags, (CK_ULONG)(CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED | CKF_USER_PIN_INITIALIZED));
+
+ CPPUNIT_ASSERT(newToken->createObject() != NULL);
+
+ delete newToken;
+
+#if 1
+ // Reopen the newly created token and keep a reference around.
+ DBToken referencingToken("testdir", "newToken");
+ CPPUNIT_ASSERT(referencingToken.isValid());
+#endif
+ // Now reopen the newly created token
+ DBToken reopenedToken("testdir","newToken");
+
+ CPPUNIT_ASSERT(reopenedToken.isValid());
+
+ // Retrieve the flags, user PIN and so PIN
+ ByteString retrievedSOPIN, retrievedUserPIN;
+
+ CPPUNIT_ASSERT(reopenedToken.getSOPIN(retrievedSOPIN));
+ CPPUNIT_ASSERT(reopenedToken.getUserPIN(retrievedUserPIN));
+ CPPUNIT_ASSERT(reopenedToken.getTokenFlags(flags));
+
+ CPPUNIT_ASSERT(retrievedSOPIN == soPIN);
+ CPPUNIT_ASSERT(retrievedUserPIN == userPIN);
+ CPPUNIT_ASSERT_EQUAL(flags, (CK_ULONG)(CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED | CKF_USER_PIN_INITIALIZED));
+
+ // Now reset the token
+ CPPUNIT_ASSERT(reopenedToken.resetToken(label));
+ CPPUNIT_ASSERT(reopenedToken.getSOPIN(retrievedSOPIN));
+ CPPUNIT_ASSERT(!reopenedToken.getUserPIN(retrievedUserPIN));
+ CPPUNIT_ASSERT(reopenedToken.getTokenFlags(flags));
+ CPPUNIT_ASSERT(retrievedSOPIN == soPIN);
+ CPPUNIT_ASSERT_EQUAL(flags, (CK_ULONG)(CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED));
+ CPPUNIT_ASSERT(reopenedToken.isValid());
+
+ // Now clear the token
+ CPPUNIT_ASSERT(reopenedToken.clearToken());
+ CPPUNIT_ASSERT(!reopenedToken.isValid());
+
+ DB::LogErrorHandler eh = DB::setLogErrorHandler(dummy_print);
+
+ // Try to open it once more and make sure it has been deleted.
+ DBToken clearedToken("testdir","newToken");
+ CPPUNIT_ASSERT(!clearedToken.isValid());
+
+#if 1
+ // Verify that it is no longer possible to access the database...
+ CPPUNIT_ASSERT(!referencingToken.getSOPIN(retrievedSOPIN));
+ CPPUNIT_ASSERT(retrievedSOPIN == soPIN);
+
+ std::set<OSObject *> objects = referencingToken.getObjects();
+ CPPUNIT_ASSERT_EQUAL(objects.size(), (size_t)0);
+
+ CPPUNIT_ASSERT(!referencingToken.isValid());
+#endif
+
+ DB::setLogErrorHandler(eh);
+}
diff --git a/SoftHSMv2/src/lib/object_store/test/DBTokenTests.h b/SoftHSMv2/src/lib/object_store/test/DBTokenTests.h
new file mode 100644
index 0000000..de25195
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/DBTokenTests.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2013 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DBTokenTests.h
+
+ Contains test cases to test the database token implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DBTOKENTESTS_H
+#define _SOFTHSM_V2_DBTOKENTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "DBToken.h"
+
+class test_a_dbtoken : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(test_a_dbtoken);
+ CPPUNIT_TEST(should_be_creatable);
+ CPPUNIT_TEST(should_support_pin_setting_getting);
+ CPPUNIT_TEST(should_allow_object_enumeration);
+ CPPUNIT_TEST(should_fail_to_open_nonexistant_tokens);
+ CPPUNIT_TEST(support_create_delete_objects);
+ CPPUNIT_TEST(support_clearing_a_token);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void setUp();
+ void tearDown();
+
+ void should_be_creatable();
+ void should_support_pin_setting_getting();
+ void should_allow_object_enumeration();
+ void should_fail_to_open_nonexistant_tokens();
+ void support_create_delete_objects();
+ void support_clearing_a_token();
+
+protected:
+
+private:
+};
+
+#endif // !_SOFTHSM_V2_DBTOKENTESTS_H
diff --git a/SoftHSMv2/src/lib/object_store/test/DirectoryTests.cpp b/SoftHSMv2/src/lib/object_store/test/DirectoryTests.cpp
new file mode 100644
index 0000000..2b56a5a
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/DirectoryTests.cpp
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DirectoryTests.cpp
+
+ Contains test cases to test the directory implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "DirectoryTests.h"
+#include "Directory.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(DirectoryTests);
+
+void DirectoryTests::setUp()
+{
+#ifndef _WIN32
+ CPPUNIT_ASSERT(!system("mkdir testdir"));
+ CPPUNIT_ASSERT(!system("mkdir testdir/anotherdir"));
+ CPPUNIT_ASSERT(!system("mkdir testdir/anotherdir2"));
+ CPPUNIT_ASSERT(!system("mkdir testdir/anotherdir3"));
+ CPPUNIT_ASSERT(!system("echo someStuff > testdir/afile"));
+ CPPUNIT_ASSERT(!system("echo someOtherStuff > testdir/anotherFile"));
+ CPPUNIT_ASSERT(!system("echo justStuff > testdir/justaFile"));
+#else
+ CPPUNIT_ASSERT(!system("mkdir testdir"));
+ CPPUNIT_ASSERT(!system("mkdir testdir\\anotherdir"));
+ CPPUNIT_ASSERT(!system("mkdir testdir\\anotherdir2"));
+ CPPUNIT_ASSERT(!system("mkdir testdir\\anotherdir3"));
+ CPPUNIT_ASSERT(!system("echo someStuff > testdir\\afile"));
+ CPPUNIT_ASSERT(!system("echo someOtherStuff > testdir\\anotherFile"));
+ CPPUNIT_ASSERT(!system("echo justStuff > testdir\\justaFile"));
+#endif
+}
+
+void DirectoryTests::tearDown()
+{
+#ifndef _WIN32
+ CPPUNIT_ASSERT(!system("rm -rf testdir"));
+#else
+ CPPUNIT_ASSERT(!system("rmdir /s /q testdir 2> nul"));
+#endif
+}
+
+void DirectoryTests::testDirectory()
+{
+#ifndef _WIN32
+ Directory testdir("./testdir");
+#else
+ Directory testdir(".\\testdir");
+#endif
+
+ CPPUNIT_ASSERT(testdir.isValid());
+
+ std::vector<std::string> files = testdir.getFiles();
+ std::vector<std::string> subDirs = testdir.getSubDirs();
+
+ CPPUNIT_ASSERT(files.size() == 3);
+ CPPUNIT_ASSERT(subDirs.size() == 3);
+
+ CPPUNIT_ASSERT(testdir.refresh());
+
+ CPPUNIT_ASSERT(files.size() == 3);
+ CPPUNIT_ASSERT(subDirs.size() == 3);
+
+ bool fileSeen[3] = { false, false, false };
+
+ for (std::vector<std::string>::iterator i = files.begin(); i != files.end(); i++)
+ {
+ if (!i->compare("afile"))
+ {
+ fileSeen[0] = true;
+ }
+ else if (!i->compare("anotherFile"))
+ {
+ fileSeen[1] = true;
+ }
+ else if (!i->compare("justaFile"))
+ {
+ fileSeen[2] = true;
+ }
+ else
+ {
+ CPPUNIT_ASSERT(false);
+ }
+ }
+
+ CPPUNIT_ASSERT(fileSeen[0] && fileSeen[1] && fileSeen[2]);
+
+ bool dirSeen[3] = { false, false, false };
+
+ for (std::vector<std::string>::iterator i = subDirs.begin(); i != subDirs.end(); i++)
+ {
+ if (!i->compare("anotherdir"))
+ {
+ dirSeen[0] = true;
+ }
+ else if (!i->compare("anotherdir2"))
+ {
+ dirSeen[1] = true;
+ }
+ else if (!i->compare("anotherdir3"))
+ {
+ dirSeen[2] = true;
+ }
+ else
+ {
+ CPPUNIT_ASSERT(false);
+ }
+ }
+
+ CPPUNIT_ASSERT(dirSeen[0] && dirSeen[1] && dirSeen[2]);
+
+ // Create a directory
+ CPPUNIT_ASSERT(testdir.mkdir("newDir"));
+
+ subDirs = testdir.getSubDirs();
+
+ bool dirSeen2[4] = { false, false, false, false };
+
+ for (std::vector<std::string>::iterator i = subDirs.begin(); i != subDirs.end(); i++)
+ {
+ if (!i->compare("anotherdir"))
+ {
+ dirSeen2[0] = true;
+ }
+ else if (!i->compare("anotherdir2"))
+ {
+ dirSeen2[1] = true;
+ }
+ else if (!i->compare("anotherdir3"))
+ {
+ dirSeen2[2] = true;
+ }
+ else if (!i->compare("newDir"))
+ {
+ dirSeen2[3] = true;
+ }
+ else
+ {
+ CPPUNIT_ASSERT(false);
+ }
+ }
+
+ CPPUNIT_ASSERT(dirSeen2[0] && dirSeen2[1] && dirSeen2[2] && dirSeen2[3]);
+
+ // Remove a directory
+ CPPUNIT_ASSERT(testdir.rmdir("anotherdir2", true));
+
+ subDirs = testdir.getSubDirs();
+
+ bool dirSeen3[3] = { false, false, false };
+
+ for (std::vector<std::string>::iterator i = subDirs.begin(); i != subDirs.end(); i++)
+ {
+ if (!i->compare("anotherdir"))
+ {
+ dirSeen3[0] = true;
+ }
+ else if (!i->compare("newDir"))
+ {
+ dirSeen3[1] = true;
+ }
+ else if (!i->compare("anotherdir3"))
+ {
+ dirSeen3[2] = true;
+ }
+ else
+ {
+ CPPUNIT_ASSERT(false);
+ }
+ }
+
+ CPPUNIT_ASSERT(dirSeen3[0] && dirSeen3[1] && dirSeen3[2]);
+
+ // Remove a file
+ CPPUNIT_ASSERT(testdir.remove("anotherFile"));
+
+ files = testdir.getFiles();
+
+ bool fileSeen2[2] = { false, false };
+
+ for (std::vector<std::string>::iterator i = files.begin(); i != files.end(); i++)
+ {
+ if (!i->compare("afile"))
+ {
+ fileSeen2[0] = true;
+ }
+ else if (!i->compare("justaFile"))
+ {
+ fileSeen2[1] = true;
+ }
+ else
+ {
+ CPPUNIT_ASSERT(false);
+ }
+ }
+
+ CPPUNIT_ASSERT(fileSeen2[0] && fileSeen2[1]);
+}
+
diff --git a/SoftHSMv2/src/lib/object_store/test/DirectoryTests.h b/SoftHSMv2/src/lib/object_store/test/DirectoryTests.h
new file mode 100644
index 0000000..777f1a8
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/DirectoryTests.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DirectoryTests.h
+
+ Contains test cases to test the Directory implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DIRECTORYTESTS_H
+#define _SOFTHSM_V2_DIRECTORYTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class DirectoryTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(DirectoryTests);
+ CPPUNIT_TEST(testDirectory);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testDirectory();
+
+ void setUp();
+ void tearDown();
+
+private:
+};
+
+#endif // !_SOFTHSM_V2_DIRECTORYTESTS_H
+
diff --git a/SoftHSMv2/src/lib/object_store/test/FileTests.cpp b/SoftHSMv2/src/lib/object_store/test/FileTests.cpp
new file mode 100644
index 0000000..9ac0979
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/FileTests.cpp
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ FileTests.cpp
+
+ Contains test cases to test the file implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "FileTests.h"
+#include "File.h"
+#include "Directory.h"
+#include "CryptoFactory.h"
+#include "RNG.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(FileTests);
+
+// FIXME: all pathnames in this file are *NIX/BSD specific
+
+void FileTests::setUp()
+{
+#ifndef _WIN32
+ int rv = system("rm -rf testdir");
+#else
+ int rv = system("rmdir /s /q testdir 2> nul");
+#endif
+ (void) rv;
+
+ CPPUNIT_ASSERT(!system("mkdir testdir"));
+}
+
+void FileTests::tearDown()
+{
+#ifndef _WIN32
+ CPPUNIT_ASSERT(!system("rm -rf testdir"));
+#else
+ CPPUNIT_ASSERT(!system("rmdir /s /q testdir 2> nul"));
+#endif
+}
+
+void FileTests::testExistNotExist()
+{
+ // Test pre-condition
+ CPPUNIT_ASSERT(!exists("nonExistentFile"));
+
+ // Attempt to open a file known not to exist
+#ifndef _WIN32
+ File doesntExist("testdir/nonExistentFile");
+#else
+ File doesntExist("testdir\\nonExistentFile");
+#endif
+
+ CPPUNIT_ASSERT(!doesntExist.isValid());
+
+ // Attempt to open a file known to exist
+#ifndef _WIN32
+ CPPUNIT_ASSERT(!system("echo someStuff > testdir/existingFile"));
+#else
+ CPPUNIT_ASSERT(!system("echo someStuff > testdir\\existingFile"));
+#endif
+ CPPUNIT_ASSERT(exists("existingFile"));
+
+#ifndef _WIN32
+ File exists("testdir/existingFile");
+#else
+ File exists("testdir\\existingFile");
+#endif
+
+ CPPUNIT_ASSERT(exists.isValid());
+}
+
+void FileTests::testCreateNotCreate()
+{
+ // Test pre-condition
+ CPPUNIT_ASSERT(!exists("nonExistentFile"));
+ CPPUNIT_ASSERT(!exists("nonExistentFile2"));
+
+ // Attempt to open a file known not to exist
+#ifndef _WIN32
+ File doesntExist("testdir/nonExistentFile", true, true, false);
+#else
+ File doesntExist("testdir\\nonExistentFile", true, true, false);
+#endif
+
+ CPPUNIT_ASSERT(!doesntExist.isValid());
+ CPPUNIT_ASSERT(!exists("nonExistentFile"));
+
+ // Attempt to open a file known not to exist in create mode
+#ifndef _WIN32
+ File willBeCreated("testdir/nonExistentFile2", true, true, true);
+#else
+ File willBeCreated("testdir\\nonExistentFile2", true, true, true);
+#endif
+
+ CPPUNIT_ASSERT(willBeCreated.isValid());
+ CPPUNIT_ASSERT(exists("nonExistentFile2"));
+}
+
+void FileTests::testLockUnlock()
+{
+ // Create pre-condition
+#ifndef _WIN32
+ CPPUNIT_ASSERT(!system("echo someStuff > testdir/existingFile"));
+#else
+ CPPUNIT_ASSERT(!system("echo someStuff > testdir\\existingFile"));
+#endif
+ CPPUNIT_ASSERT(exists("existingFile"));
+
+#ifndef _WIN32
+ File file1("testdir/existingFile");
+ File file2("testdir/existingFile");
+#else
+ File file1("testdir\\existingFile");
+ File file2("testdir\\existingFile");
+#endif
+
+ CPPUNIT_ASSERT(file1.lock(false));
+ CPPUNIT_ASSERT(!file1.lock(false));
+ CPPUNIT_ASSERT(file2.lock(false));
+ CPPUNIT_ASSERT(file2.unlock());
+ CPPUNIT_ASSERT(file1.unlock());
+ CPPUNIT_ASSERT(file1.lock());
+ CPPUNIT_ASSERT(file2.lock());
+ CPPUNIT_ASSERT(file2.unlock());
+ CPPUNIT_ASSERT(file1.unlock());
+}
+
+void FileTests::testWriteRead()
+{
+ // Generate some test data
+ RNG* rng = CryptoFactory::i()->getRNG();
+
+ ByteString testData1;
+
+ CPPUNIT_ASSERT(rng->generateRandom(testData1, 187));
+
+ // More test data
+ std::string testString = "This is a test of the File class";
+ std::set<CK_MECHANISM_TYPE> testSet;
+ testSet.insert(CKM_RSA_PKCS);
+ testSet.insert(CKM_SHA256_RSA_PKCS);
+
+ // Create a file for writing
+ {
+#ifndef _WIN32
+ File newFile("testdir/newFile", false, true);
+#else
+ File newFile("testdir\\newFile", false, true);
+#endif
+
+ CPPUNIT_ASSERT(newFile.isValid());
+
+ // Write two booleans into the file
+ CPPUNIT_ASSERT(newFile.writeBool(true));
+ CPPUNIT_ASSERT(newFile.writeBool(false));
+
+ // Write an ulong into the file
+ CPPUNIT_ASSERT(newFile.writeULong(0x12345678));
+
+ // Write a ByteString into the file
+ CPPUNIT_ASSERT(newFile.writeByteString(testData1));
+
+ // Write a string into the file
+ CPPUNIT_ASSERT(newFile.writeString(testString));
+
+ // Write a set into the file
+ CPPUNIT_ASSERT(newFile.writeMechanismTypeSet(testSet));
+ }
+
+ CPPUNIT_ASSERT(exists("newFile"));
+
+ // Read the created file back
+ {
+#ifndef _WIN32
+ File newFile("testdir/newFile");
+#else
+ File newFile("testdir\\newFile");
+#endif
+
+ CPPUNIT_ASSERT(newFile.isValid());
+
+ // Read back the two booleans
+ bool b1, b2;
+
+ CPPUNIT_ASSERT(newFile.readBool(b1) && newFile.readBool(b2));
+ CPPUNIT_ASSERT(b1 && !b2);
+
+ // Read back the ulong
+ unsigned long ulongValue;
+
+ CPPUNIT_ASSERT(newFile.readULong(ulongValue));
+ CPPUNIT_ASSERT(ulongValue == 0x12345678);
+
+ // Read back the byte string
+ ByteString bsValue;
+
+ CPPUNIT_ASSERT(newFile.readByteString(bsValue));
+ CPPUNIT_ASSERT(bsValue == testData1);
+
+ // Read back the string value
+ std::string stringVal;
+
+ CPPUNIT_ASSERT(newFile.readString(stringVal));
+ CPPUNIT_ASSERT(!testString.compare(stringVal));
+
+ // Read back the set value
+ std::set<CK_MECHANISM_TYPE> setVal;
+
+ CPPUNIT_ASSERT(newFile.readMechanismTypeSet(setVal));
+ CPPUNIT_ASSERT(setVal == testSet);
+
+ // Check for EOF
+ CPPUNIT_ASSERT(!newFile.readBool(b1));
+ CPPUNIT_ASSERT(newFile.isEOF());
+ }
+}
+
+void FileTests::testSeek()
+{
+ ByteString t1 = "112233445566778899"; // 9 long
+ ByteString t2 = "AABBCCDDEEFFAABBCCDDEEFF"; // 12 long
+
+ {
+ // Create the test file
+#ifndef _WIN32
+ File testFile("testdir/testFile", false, true, true);
+#else
+ File testFile("testdir\\testFile", false, true, true);
+#endif
+
+ CPPUNIT_ASSERT(testFile.isValid());
+
+ // Write the test data to the test file
+ CPPUNIT_ASSERT(testFile.writeByteString(t1) && testFile.writeByteString(t2));
+ }
+
+ // Open the test file for reading
+#ifndef _WIN32
+ File testFile("testdir/testFile");
+#else
+ File testFile("testdir\\testFile");
+#endif
+
+ CPPUNIT_ASSERT(testFile.isValid());
+
+ // First, read back the test data
+ ByteString tr1, tr2;
+
+ CPPUNIT_ASSERT(testFile.readByteString(tr1) && testFile.readByteString(tr2));
+ CPPUNIT_ASSERT(tr1 == t1);
+ CPPUNIT_ASSERT(tr2 == t2);
+
+ // Seek to the length field of the second byte string
+ CPPUNIT_ASSERT(testFile.seek(8+9));
+
+ // Read back the size as an ulong value
+ unsigned long value;
+ unsigned long expectedValue = (unsigned long)0x1122334455667788ULL;
+
+ CPPUNIT_ASSERT(testFile.readULong(value));
+ CPPUNIT_ASSERT(value == 12);
+
+ // Seek to the start of the first byte string's data
+ CPPUNIT_ASSERT(testFile.seek(8));
+
+ // Read back the ulong value stored there
+ CPPUNIT_ASSERT(testFile.readULong(value));
+
+ CPPUNIT_ASSERT(value == expectedValue);
+
+ // Seek to the start of second byte string
+ CPPUNIT_ASSERT(testFile.seek(8+9));
+
+ // Read it
+ ByteString trr2;
+
+ CPPUNIT_ASSERT(testFile.readByteString(trr2));
+ CPPUNIT_ASSERT(trr2 == t2);
+
+ // Rewind the file
+ CPPUNIT_ASSERT(testFile.rewind());
+
+ // Read back both byte strings
+ ByteString trrr1, trrr2;
+
+ CPPUNIT_ASSERT(testFile.readByteString(trrr1) && testFile.readByteString(trrr2));
+ CPPUNIT_ASSERT(trrr1 == t1);
+ CPPUNIT_ASSERT(trrr2 == t2);
+}
+
+bool FileTests::exists(std::string name)
+{
+#ifndef _WIN32
+ Directory dir("./testdir");
+#else
+ Directory dir(".\\testdir");
+#endif
+
+
+ CPPUNIT_ASSERT(dir.isValid());
+
+ std::vector<std::string> files = dir.getFiles();
+
+ for (std::vector<std::string>::iterator i = files.begin(); i != files.end(); i++)
+ {
+ if (!i->compare(name))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
diff --git a/SoftHSMv2/src/lib/object_store/test/FileTests.h b/SoftHSMv2/src/lib/object_store/test/FileTests.h
new file mode 100644
index 0000000..0b87f26
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/FileTests.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ FileTests.h
+
+ Contains test cases to test the File implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_FILETESTS_H
+#define _SOFTHSM_V2_FILETESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class FileTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(FileTests);
+ CPPUNIT_TEST(testExistNotExist);
+ CPPUNIT_TEST(testCreateNotCreate);
+ CPPUNIT_TEST(testLockUnlock);
+ CPPUNIT_TEST(testWriteRead);
+ CPPUNIT_TEST(testSeek);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testExistNotExist();
+ void testCreateNotCreate();
+ void testLockUnlock();
+ void testWriteRead();
+ void testSeek();
+
+ void setUp();
+ void tearDown();
+
+private:
+ bool exists(std::string path);
+};
+
+#endif // !_SOFTHSM_V2_FILETESTS_H
+
diff --git a/SoftHSMv2/src/lib/object_store/test/Makefile.am b/SoftHSMv2/src/lib/object_store/test/Makefile.am
new file mode 100644
index 0000000..71de7dd
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/Makefile.am
@@ -0,0 +1,39 @@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/.. \
+ -I$(srcdir)/../.. \
+ -I$(srcdir)/../../common \
+ -I$(srcdir)/../../crypto \
+ -I$(srcdir)/../../data_mgr \
+ -I$(srcdir)/../../pkcs11 \
+ -I$(srcdir)/../../session_mgr \
+ -I$(srcdir)/../../slot_mgr \
+ @CPPUNIT_CFLAGS@ \
+ @CRYPTO_INCLUDES@
+
+check_PROGRAMS = objstoretest
+
+objstoretest_SOURCES = objstoretest.cpp \
+ DirectoryTests.cpp \
+ UUIDTests.cpp \
+ FileTests.cpp \
+ ObjectFileTests.cpp \
+ OSTokenTests.cpp \
+ ObjectStoreTests.cpp \
+ SessionObjectTests.cpp \
+ SessionObjectStoreTests.cpp
+
+if BUILD_OBJECTSTORE_BACKEND_DB
+objstoretest_SOURCES += DBTests.cpp \
+ DBObjectTests.cpp \
+ DBTokenTests.cpp \
+ DBObjectStoreTests.cpp
+endif
+
+objstoretest_LDADD = ../../libsofthsm_convarch.la
+
+objstoretest_LDFLAGS = @CRYPTO_LIBS@ @CPPUNIT_LIBS@ -no-install -pthread
+
+TESTS = objstoretest
+
+EXTRA_DIST = $(srcdir)/*.h
diff --git a/SoftHSMv2/src/lib/object_store/test/OSTokenTests.cpp b/SoftHSMv2/src/lib/object_store/test/OSTokenTests.cpp
new file mode 100644
index 0000000..5afd583
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/OSTokenTests.cpp
@@ -0,0 +1,504 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSTokenTests.cpp
+
+ Contains test cases to test the object file implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "OSTokenTests.h"
+#include "OSToken.h"
+#include "ObjectFile.h"
+#include "File.h"
+#include "Directory.h"
+#include "OSAttribute.h"
+#include "OSAttributes.h"
+#include "cryptoki.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(OSTokenTests);
+
+// FIXME: all pathnames in this file are *NIX/BSD specific
+
+void OSTokenTests::setUp()
+{
+ CPPUNIT_ASSERT(!system("mkdir testdir"));
+}
+
+void OSTokenTests::tearDown()
+{
+#ifndef _WIN32
+ CPPUNIT_ASSERT(!system("rm -rf testdir"));
+#else
+ CPPUNIT_ASSERT(!system("rmdir /s /q testdir 2> nul"));
+#endif
+}
+
+void OSTokenTests::testNewToken()
+{
+ // Create a new token
+ ByteString label = "40414243"; // ABCD
+ ByteString serial = "0102030405060708";
+
+#ifndef _WIN32
+ OSToken* newToken = OSToken::createToken("./testdir", "newToken", label, serial);
+#else
+ OSToken* newToken = OSToken::createToken(".\\testdir", "newToken", label, serial);
+#endif
+
+ CPPUNIT_ASSERT(newToken != NULL);
+
+ // Check the flags
+ CK_ULONG flags;
+ CPPUNIT_ASSERT(newToken->getTokenFlags(flags));
+ CPPUNIT_ASSERT(flags == (CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED | CKF_SO_PIN_LOCKED | CKF_SO_PIN_TO_BE_CHANGED));
+
+ // Set the SO PIN
+ ByteString soPIN = "3132333435363738"; // 12345678
+
+ CPPUNIT_ASSERT(newToken->setSOPIN(soPIN));
+
+ // Set the user PIN
+ ByteString userPIN = "31323334"; // 1234
+
+ CPPUNIT_ASSERT(newToken->setUserPIN(userPIN));
+
+ CPPUNIT_ASSERT(newToken->getTokenFlags(flags));
+ CPPUNIT_ASSERT(flags == (CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED | CKF_USER_PIN_INITIALIZED));
+
+ delete newToken;
+
+ // Now reopen the newly created token
+#ifndef _WIN32
+ OSToken reopenedToken("./testdir/newToken");
+#else
+ OSToken reopenedToken(".\\testdir\\newToken");
+#endif
+
+ CPPUNIT_ASSERT(reopenedToken.isValid());
+
+ // Retrieve the flags, user PIN and so PIN
+ ByteString retrievedSOPIN, retrievedUserPIN;
+
+ CPPUNIT_ASSERT(reopenedToken.getSOPIN(retrievedSOPIN));
+ CPPUNIT_ASSERT(reopenedToken.getUserPIN(retrievedUserPIN));
+ CPPUNIT_ASSERT(reopenedToken.getTokenFlags(flags));
+
+ CPPUNIT_ASSERT(retrievedSOPIN == soPIN);
+ CPPUNIT_ASSERT(retrievedUserPIN == userPIN);
+ CPPUNIT_ASSERT(flags == (CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED | CKF_USER_PIN_INITIALIZED));
+}
+
+void OSTokenTests::testExistingToken()
+{
+ ByteString label = "40414243"; // ABCD
+ ByteString serial = "0102030405060708";
+ ByteString soPIN = "31323334"; // 1234
+ ByteString userPIN = "30303030"; // 0000
+ ByteString id1 = "ABCDEF";
+ ByteString id2 = "FEDCBA";
+ ByteString id3 = "AABBCC";
+
+ {
+ // Create the token dir
+#ifndef _WIN32
+ CPPUNIT_ASSERT(!system("mkdir testdir/existingToken"));
+#else
+ CPPUNIT_ASSERT(!system("mkdir testdir\\existingToken"));
+#endif
+
+ // Create the token object
+#ifndef _WIN32
+ ObjectFile tokenObject(NULL, "./testdir/existingToken/token.object", "./testdir/existingToken/token.lock", true);
+#else
+ ObjectFile tokenObject(NULL, ".\\testdir\\existingToken\\token.object", ".\\testdir\\existingToken\\token.lock", true);
+#endif
+
+ OSAttribute labelAtt(label);
+ CPPUNIT_ASSERT(tokenObject.setAttribute(CKA_OS_TOKENLABEL, labelAtt));
+ OSAttribute serialAtt(serial);
+ CPPUNIT_ASSERT(tokenObject.setAttribute(CKA_OS_TOKENSERIAL, serialAtt));
+ OSAttribute soPINAtt(soPIN);
+ CPPUNIT_ASSERT(tokenObject.setAttribute(CKA_OS_SOPIN, soPINAtt));
+ OSAttribute userPINAtt(userPIN);
+ CPPUNIT_ASSERT(tokenObject.setAttribute(CKA_OS_USERPIN, userPINAtt));
+ CK_ULONG flags = CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED;
+ OSAttribute flagsAtt(flags);
+ CPPUNIT_ASSERT(tokenObject.setAttribute(CKA_OS_TOKENFLAGS, flagsAtt));
+
+ // Create 3 objects
+#ifndef _WIN32
+ ObjectFile obj1(NULL, "./testdir/existingToken/1.object", "./testdir/existingToken/1.lock", true);
+ ObjectFile obj2(NULL, "./testdir/existingToken/2.object", "./testdir/existingToken/2.lock", true);
+ ObjectFile obj3(NULL, "./testdir/existingToken/3.object", "./testdir/existingToken/3.lock", true);
+#else
+ ObjectFile obj1(NULL, ".\\testdir\\existingToken\\1.object", ".\\testdir\\existingToken\\1.lock", true);
+ ObjectFile obj2(NULL, ".\\testdir\\existingToken\\2.object", ".\\testdir\\existingToken\\2.lock", true);
+ ObjectFile obj3(NULL, ".\\testdir\\existingToken\\3.object", ".\\testdir\\existingToken\\3.lock", true);
+#endif
+
+ OSAttribute id1Att(id1);
+ OSAttribute id2Att(id2);
+ OSAttribute id3Att(id3);
+
+ CPPUNIT_ASSERT(obj1.setAttribute(CKA_ID, id1));
+ CPPUNIT_ASSERT(obj2.setAttribute(CKA_ID, id2));
+ CPPUNIT_ASSERT(obj3.setAttribute(CKA_ID, id3));
+ }
+
+ // Now open the token
+#ifndef _WIN32
+ OSToken existingToken("./testdir/existingToken");
+#else
+ OSToken existingToken(".\\testdir\\existingToken");
+#endif
+
+
+ CPPUNIT_ASSERT(existingToken.isValid());
+
+ // Retrieve SO PIN, user PIN, label, serial number and flags
+ ByteString retrievedSOPIN, retrievedUserPIN, retrievedLabel, retrievedSerial;
+ CK_ULONG flags;
+
+ CPPUNIT_ASSERT(existingToken.getSOPIN(retrievedSOPIN));
+ CPPUNIT_ASSERT(existingToken.getUserPIN(retrievedUserPIN));
+ CPPUNIT_ASSERT(existingToken.getTokenLabel(retrievedLabel));
+ CPPUNIT_ASSERT(existingToken.getTokenSerial(retrievedSerial));
+ CPPUNIT_ASSERT(existingToken.getTokenFlags(flags));
+
+ CPPUNIT_ASSERT(retrievedSOPIN == soPIN);
+ CPPUNIT_ASSERT(retrievedUserPIN == userPIN);
+ CPPUNIT_ASSERT(retrievedLabel == label);
+ CPPUNIT_ASSERT(retrievedSerial == serial);
+ CPPUNIT_ASSERT(flags == (CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED | CKF_USER_PIN_INITIALIZED));
+
+ // Check that the token contains 3 objects
+ CPPUNIT_ASSERT(existingToken.getObjects().size() == 3);
+
+ // Check that all the tokens are presented
+ bool present[3] = { false, false, false };
+ std::set<OSObject*> objects = existingToken.getObjects();
+
+ for (std::set<OSObject*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID).isByteStringAttribute());
+
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id1)
+ {
+ present[0] = true;
+ }
+ else if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id2)
+ {
+ present[1] = true;
+ }
+ else if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id3)
+ {
+ present[2] = true;
+ }
+ }
+
+ CPPUNIT_ASSERT(present[0] == true);
+ CPPUNIT_ASSERT(present[1] == true);
+ CPPUNIT_ASSERT(present[2] == true);
+}
+
+void OSTokenTests::testNonExistentToken()
+{
+#ifndef _WIN32
+ OSToken doesntExist("./testdir/doesntExist");
+#else
+ OSToken doesntExist(".\\testdir\\doesntExist");
+#endif
+
+ CPPUNIT_ASSERT(!doesntExist.isValid());
+}
+
+void OSTokenTests::testCreateDeleteObjects()
+{
+ // Test IDs
+ ByteString id[5] = { "112233445566", "AABBCCDDEEFF", "ABABABABABAB", "557788991122", "005500550055" };
+ OSAttribute idAtt[5] = { id[0], id[1], id[2], id[3], id[4] };
+ ByteString label = "AABBCCDDEEFF";
+ ByteString serial = "1234567890";
+
+ // Instantiate a new token
+#ifndef _WIN32
+ OSToken* testToken = OSToken::createToken("./testdir", "testToken", label, serial);
+#else
+ OSToken* testToken = OSToken::createToken(".\\testdir", "testToken", label, serial);
+#endif
+
+ CPPUNIT_ASSERT(testToken != NULL);
+ CPPUNIT_ASSERT(testToken->isValid());
+
+ // Open the same token
+#ifndef _WIN32
+ OSToken sameToken("./testdir/testToken");
+#else
+ OSToken sameToken(".\\testdir\\testToken");
+#endif
+
+ CPPUNIT_ASSERT(sameToken.isValid());
+
+ // Create 3 objects on the token
+ OSObject* obj1 = testToken->createObject();
+ CPPUNIT_ASSERT(obj1 != NULL);
+ OSObject* obj2 = testToken->createObject();
+ CPPUNIT_ASSERT(obj2 != NULL);
+ OSObject* obj3 = testToken->createObject();
+ CPPUNIT_ASSERT(obj3 != NULL);
+
+ // Now set the IDs of the 3 objects
+ obj1->setAttribute(CKA_ID, idAtt[0]);
+ obj2->setAttribute(CKA_ID, idAtt[1]);
+ obj3->setAttribute(CKA_ID, idAtt[2]);
+
+ // Check that the token contains 3 objects
+ CPPUNIT_ASSERT(testToken->getObjects().size() == 3);
+
+ // Check that all three objects are distinct and present
+ std::set<OSObject*> objects = testToken->getObjects();
+ bool present1[3] = { false, false, false };
+
+ for (std::set<OSObject*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID).isByteStringAttribute());
+
+ for (int j = 0; j < 3; j++)
+ {
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[j])
+ {
+ present1[j] = true;
+ }
+ }
+ }
+
+ for (int j = 0; j < 3; j++)
+ {
+ CPPUNIT_ASSERT(present1[j] == true);
+ }
+
+ // Now check that the same objects are present in the other instance of the same token
+ std::set<OSObject*> otherObjects = sameToken.getObjects();
+ CPPUNIT_ASSERT(otherObjects.size() == 3);
+
+ bool present2[3] = { false, false, false };
+
+ for (std::set<OSObject*>::iterator i = otherObjects.begin(); i != otherObjects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID).isByteStringAttribute());
+
+ for (int j = 0; j < 3; j++)
+ {
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[j])
+ {
+ present2[j] = true;
+ }
+ }
+ }
+
+ for (int j = 0; j < 3; j++)
+ {
+ CPPUNIT_ASSERT(present2[j] == true);
+ }
+
+ // Now delete the second object
+ for (std::set<OSObject*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID).isByteStringAttribute());
+
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[1])
+ {
+ CPPUNIT_ASSERT(testToken->deleteObject(*i));
+ break;
+ }
+ }
+
+ // Verify that it was indeed removed
+ CPPUNIT_ASSERT(testToken->getObjects().size() == 2);
+
+ objects = testToken->getObjects();
+ bool present3[2] = { false, false };
+
+ for (std::set<OSObject*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID).isByteStringAttribute());
+
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[0])
+ {
+ present3[0] = true;
+ }
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[2])
+ {
+ present3[1] = true;
+ }
+ }
+
+ for (int j = 0; j < 2; j++)
+ {
+ CPPUNIT_ASSERT(present3[j] == true);
+ }
+
+ // Now check the other instance
+ CPPUNIT_ASSERT(sameToken.getObjects().size() == 2);
+
+ otherObjects = sameToken.getObjects();
+ bool present4[2] = { false, false };
+
+ for (std::set<OSObject*>::iterator i = otherObjects.begin(); i != otherObjects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID).isByteStringAttribute());
+
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[0])
+ {
+ present4[0] = true;
+ }
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[2])
+ {
+ present4[1] = true;
+ }
+ }
+
+ for (int j = 0; j < 2; j++)
+ {
+ CPPUNIT_ASSERT(present4[j] == true);
+ }
+
+
+ // Release the test token
+ delete testToken;
+}
+
+void OSTokenTests::testClearToken()
+{
+ // Create a new token
+ ByteString label = "40414243"; // ABCD
+ ByteString serial = "0102030405060708";
+
+#ifndef _WIN32
+ OSToken* newToken = OSToken::createToken("./testdir", "newToken", label, serial);
+#else
+ OSToken* newToken = OSToken::createToken(".\\testdir", "newToken", label, serial);
+#endif
+
+ CPPUNIT_ASSERT(newToken != NULL);
+
+ // Check the flags
+ CK_ULONG flags;
+ CPPUNIT_ASSERT(newToken->getTokenFlags(flags));
+ CPPUNIT_ASSERT(flags == (CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED | CKF_SO_PIN_LOCKED | CKF_SO_PIN_TO_BE_CHANGED));
+
+ // Set the SO PIN
+ ByteString soPIN = "3132333435363738"; // 12345678
+
+ CPPUNIT_ASSERT(newToken->setSOPIN(soPIN));
+
+ // Set the user PIN
+ ByteString userPIN = "31323334"; // 1234
+
+ CPPUNIT_ASSERT(newToken->setUserPIN(userPIN));
+
+ CPPUNIT_ASSERT(newToken->getTokenFlags(flags));
+ CPPUNIT_ASSERT(flags == (CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED | CKF_USER_PIN_INITIALIZED));
+
+ delete newToken;
+
+ // Now reopen the newly created token
+#ifndef _WIN32
+ OSToken reopenedToken("./testdir/newToken");
+#else
+ OSToken reopenedToken(".\\testdir\\newToken");
+#endif
+
+ CPPUNIT_ASSERT(reopenedToken.isValid());
+
+ // Retrieve the flags, user PIN and so PIN
+ ByteString retrievedSOPIN, retrievedUserPIN;
+
+ CPPUNIT_ASSERT(reopenedToken.getSOPIN(retrievedSOPIN));
+ CPPUNIT_ASSERT(reopenedToken.getUserPIN(retrievedUserPIN));
+ CPPUNIT_ASSERT(reopenedToken.getTokenFlags(flags));
+
+ CPPUNIT_ASSERT(retrievedSOPIN == soPIN);
+ CPPUNIT_ASSERT(retrievedUserPIN == userPIN);
+ CPPUNIT_ASSERT(flags == (CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED | CKF_USER_PIN_INITIALIZED));
+
+ // Now reset the token
+ CPPUNIT_ASSERT(reopenedToken.resetToken(label));
+ CPPUNIT_ASSERT(reopenedToken.getSOPIN(retrievedSOPIN));
+ CPPUNIT_ASSERT(!reopenedToken.getUserPIN(retrievedUserPIN));
+ CPPUNIT_ASSERT(reopenedToken.getTokenFlags(flags));
+ CPPUNIT_ASSERT(retrievedSOPIN == soPIN);
+ CPPUNIT_ASSERT(flags == (CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED));
+ CPPUNIT_ASSERT(reopenedToken.isValid());
+
+ // Now clear the token
+ CPPUNIT_ASSERT(reopenedToken.clearToken());
+ CPPUNIT_ASSERT(!reopenedToken.isValid());
+
+ // Try to open it once more
+#ifndef _WIN32
+ OSToken clearedToken("./testdir/newToken");
+#else
+ OSToken clearedToken(".\\testdir\\newToken");
+#endif
+
+ CPPUNIT_ASSERT(!clearedToken.isValid());
+}
+
diff --git a/SoftHSMv2/src/lib/object_store/test/OSTokenTests.h b/SoftHSMv2/src/lib/object_store/test/OSTokenTests.h
new file mode 100644
index 0000000..1155fcf
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/OSTokenTests.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSTokenTests.h
+
+ Contains test cases to test the object file implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSTOKENTESTS_H
+#define _SOFTHSM_V2_OSTOKENTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class OSTokenTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(OSTokenTests);
+ CPPUNIT_TEST(testNewToken);
+ CPPUNIT_TEST(testExistingToken);
+ CPPUNIT_TEST(testNonExistentToken);
+ CPPUNIT_TEST(testCreateDeleteObjects);
+ CPPUNIT_TEST(testClearToken);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testNewToken();
+ void testExistingToken();
+ void testNonExistentToken();
+ void testCreateDeleteObjects();
+ void testClearToken();
+
+ void setUp();
+ void tearDown();
+};
+
+#endif // !_SOFTHSM_V2_OSTOKENTESTS_H
+
diff --git a/SoftHSMv2/src/lib/object_store/test/ObjectFileTests.cpp b/SoftHSMv2/src/lib/object_store/test/ObjectFileTests.cpp
new file mode 100644
index 0000000..9f0f5bd
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/ObjectFileTests.cpp
@@ -0,0 +1,911 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ObjectObjectFileTests.cpp
+
+ Contains test cases to test the object file implementation
+ *****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "ObjectFileTests.h"
+#include "ObjectFile.h"
+#include "File.h"
+#include "Directory.h"
+#include "OSAttribute.h"
+#include "CryptoFactory.h"
+#include "RNG.h"
+#include "cryptoki.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(ObjectFileTests);
+
+// FIXME: all pathnames in this file are *NIX/BSD specific
+
+void ObjectFileTests::setUp()
+{
+ CPPUNIT_ASSERT(!system("mkdir testdir"));
+}
+
+void ObjectFileTests::tearDown()
+{
+#ifndef _WIN32
+ CPPUNIT_ASSERT(!system("rm -rf testdir"));
+#else
+ CPPUNIT_ASSERT(!system("rmdir /s /q testdir 2> nul"));
+#endif
+}
+
+void ObjectFileTests::testBoolAttr()
+{
+ // Create the test object
+ {
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock", true);
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock", true);
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ bool value1 = true;
+ bool value2 = false;
+ bool value3 = true;
+ bool value4 = true;
+ bool value5 = false;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+ OSAttribute attr5(value5);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SENSITIVE, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_EXTRACTABLE, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_NEVER_EXTRACTABLE, attr4));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SIGN, attr5));
+ }
+
+ // Now read back the object
+ {
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock");
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock");
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_TOKEN));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SENSITIVE));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_EXTRACTABLE));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_NEVER_EXTRACTABLE));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SIGN));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SENSITIVE).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_EXTRACTABLE).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_NEVER_EXTRACTABLE).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN).isBooleanAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SENSITIVE).getBooleanValue() == false);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_EXTRACTABLE).getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_NEVER_EXTRACTABLE).getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN).getBooleanValue() == false);
+
+ bool value6 = true;
+ OSAttribute attr6(value6);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VERIFY, attr6));
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VERIFY).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VERIFY).getBooleanValue() == value6);
+ CPPUNIT_ASSERT(testObject.getBooleanValue(CKA_VERIFY, false) == value6);
+ }
+}
+
+void ObjectFileTests::testULongAttr()
+{
+ // Create the test object
+ {
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock", true);
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock", true);
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ unsigned long value1 = 0x12345678;
+ unsigned long value2 = 0x87654321;
+ unsigned long value3 = 0x01010101;
+ unsigned long value4 = 0x10101010;
+ unsigned long value5 = 0xABCDEF;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+ OSAttribute attr5(value5);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_MODULUS_BITS, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_AUTH_PIN_FLAGS, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SUBPRIME_BITS, attr4));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_KEY_TYPE, attr5));
+ }
+
+ // Now read back the object
+ {
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock");
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock");
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_MODULUS_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_AUTH_PIN_FLAGS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SUBPRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_KEY_TYPE));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_MODULUS_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_AUTH_PIN_FLAGS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBPRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_KEY_TYPE).isUnsignedLongAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_MODULUS_BITS).getUnsignedLongValue() == 0x12345678);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == 0x87654321);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_AUTH_PIN_FLAGS).getUnsignedLongValue() == 0x01010101);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBPRIME_BITS).getUnsignedLongValue() == 0x10101010);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_KEY_TYPE).getUnsignedLongValue() == 0xABCDEF);
+
+ unsigned long value6 = 0x90909090;
+ OSAttribute attr6(value6);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_CLASS, attr6));
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_CLASS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_CLASS).getUnsignedLongValue() == value6);
+ CPPUNIT_ASSERT(testObject.getUnsignedLongValue(CKA_CLASS, 0x0) == value6);
+ }
+}
+
+void ObjectFileTests::testByteStrAttr()
+{
+ ByteString value1 = "010203040506070809";
+ ByteString value2 = "ABABABABABABABABABABABABABABABABAB";
+ ByteString value3 = "BDEBDBEDBBDBEBDEBE792759537328";
+ ByteString value4 = "98A7E5D798A7E5D798A7E5D798A7E5D798A7E5D798A7E5D7";
+ ByteString value5 = "ABCDABCDABCDABCDABCDABCDABCDABCD";
+
+ // Create the test object
+ {
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock", true);
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock", true);
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+ OSAttribute attr5(value5);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_MODULUS, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_COEFFICIENT, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PUBLIC_EXPONENT, attr4));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SUBJECT, attr5));
+ }
+
+ // Now read back the object
+ {
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock");
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock");
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_MODULUS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_COEFFICIENT));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_VALUE));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PUBLIC_EXPONENT));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SUBJECT));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_MODULUS).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_COEFFICIENT).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PUBLIC_EXPONENT).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBJECT).isByteStringAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_MODULUS).getByteStringValue() == value1);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_COEFFICIENT).getByteStringValue() == value2);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).getByteStringValue() == value3);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PUBLIC_EXPONENT).getByteStringValue() == value4);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBJECT).getByteStringValue() == value5);
+
+ ByteString value6 = "909090908080808080807070707070FF";
+ OSAttribute attr6(value6);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ISSUER, attr6));
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ISSUER).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getByteStringValue(CKA_ISSUER) == value6);
+ }
+}
+
+void ObjectFileTests::testMechTypeSetAttr()
+{
+ // Create the test object
+ {
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock", true);
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock", true);
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ std::set<CK_MECHANISM_TYPE> set;
+ set.insert(CKM_SHA256);
+ set.insert(CKM_SHA512);
+ OSAttribute attr(set);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ALLOWED_MECHANISMS, attr));
+ }
+
+ // Now read back the object
+ {
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock");
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock");
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_ALLOWED_MECHANISMS));
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ std::set<CK_MECHANISM_TYPE> retrieved =
+ testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue();
+
+ CPPUNIT_ASSERT(retrieved.size() == 2);
+ CPPUNIT_ASSERT(retrieved.find(CKM_SHA256) != retrieved.end());
+ CPPUNIT_ASSERT(retrieved.find(CKM_SHA384) == retrieved.end());
+ CPPUNIT_ASSERT(retrieved.find(CKM_SHA512) != retrieved.end());
+ }
+}
+
+void ObjectFileTests::testAttrMapAttr()
+{
+ ByteString value3 = "BDEBDBEDBBDBEBDEBE792759537328";
+ std::set<CK_MECHANISM_TYPE> value4;
+ value4.insert(CKM_SHA256);
+ value4.insert(CKM_SHA512);
+
+ // Create the test object
+ {
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock", true);
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock", true);
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ bool value1 = true;
+ unsigned long value2 = 0x87654321;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute> mattr;
+ mattr.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (CKA_TOKEN, attr1));
+ mattr.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (CKA_PRIME_BITS, attr2));
+ mattr.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (CKA_VALUE, attr3));
+ mattr.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (CKA_ALLOWED_MECHANISMS, attr4));
+ OSAttribute attra(mattr);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_WRAP_TEMPLATE, attra));
+ }
+
+ // Now read back the object
+ {
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock");
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock");
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_WRAP_TEMPLATE));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_UNWRAP_TEMPLATE));
+
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute> mattrb =
+ testObject.getAttribute(CKA_WRAP_TEMPLATE).getAttributeMapValue();
+ CPPUNIT_ASSERT(mattrb.size() == 4);
+ CPPUNIT_ASSERT(mattrb.find(CKA_TOKEN) != mattrb.end());
+ CPPUNIT_ASSERT(mattrb.at(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(mattrb.at(CKA_TOKEN).getBooleanValue() == true);
+ CPPUNIT_ASSERT(mattrb.find(CKA_PRIME_BITS) != mattrb.end());
+ CPPUNIT_ASSERT(mattrb.at(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(mattrb.at(CKA_PRIME_BITS).getUnsignedLongValue() == 0x87654321);
+ CPPUNIT_ASSERT(mattrb.find(CKA_VALUE) != mattrb.end());
+ CPPUNIT_ASSERT(mattrb.at(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(mattrb.at(CKA_VALUE).getByteStringValue() == value3);
+ CPPUNIT_ASSERT(mattrb.find(CKA_ALLOWED_MECHANISMS) != mattrb.end());
+ CPPUNIT_ASSERT(mattrb.at(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+ CPPUNIT_ASSERT(mattrb.at(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4);
+ }
+}
+
+void ObjectFileTests::testMixedAttr()
+{
+ ByteString value3 = "BDEBDBEDBBDBEBDEBE792759537328";
+ std::set<CK_MECHANISM_TYPE> value4;
+ value4.insert(CKM_SHA256);
+ value4.insert(CKM_SHA512);
+
+ // Create the test object
+ {
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock", true);
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock", true);
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ bool value1 = true;
+ unsigned long value2 = 0x87654321;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ALLOWED_MECHANISMS, attr4));
+ }
+
+ // Now read back the object
+ {
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock");
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock");
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_TOKEN));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_VALUE));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_ALLOWED_MECHANISMS));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == 0x87654321);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).getByteStringValue() == value3);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4);
+ }
+}
+
+void ObjectFileTests::testDoubleAttr()
+{
+ ByteString value3 = "BDEBDBEDBBDBEBDEBE792759537328";
+ ByteString value3a = "466487346943785684957634";
+ std::set<CK_MECHANISM_TYPE> value4;
+ value4.insert(CKM_SHA256);
+ value4.insert(CKM_SHA512);
+ std::set<CK_MECHANISM_TYPE> value4a;
+ value4a.insert(CKM_SHA384);
+ value4a.insert(CKM_SHA512);
+
+ // Create the test object
+ {
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock", true);
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock", true);
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ bool value1 = true;
+ unsigned long value2 = 0x87654321;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ALLOWED_MECHANISMS, attr4));
+ }
+
+ // Now read back the object
+ {
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock");
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock");
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_TOKEN));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_VALUE));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_ALLOWED_MECHANISMS));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == 0x87654321);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).getByteStringValue() == value3);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4);
+
+ bool value1 = false;
+ unsigned long value2 = 0x76767676;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3a);
+ OSAttribute attr4(value4a);
+
+ // Change the attributes
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ALLOWED_MECHANISMS, attr4));
+
+ // Check the attributes
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == value1);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).getByteStringValue() == value3a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4a);
+ }
+
+ // Now re-read back the object
+ {
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock");
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock");
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_TOKEN));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_VALUE));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_ALLOWED_MECHANISMS));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ bool value1 = false;
+ unsigned long value2 = 0x76767676;
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == value1);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).getByteStringValue() == value3a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4a);
+ }
+}
+
+void ObjectFileTests::testRefresh()
+{
+ ByteString value3 = "BDEBDBEDBBDBEBDEBE792759537328";
+ ByteString value3a = "466487346943785684957634";
+ std::set<CK_MECHANISM_TYPE> value4;
+ value4.insert(CKM_SHA256);
+ value4.insert(CKM_SHA512);
+ std::set<CK_MECHANISM_TYPE> value4a;
+ value4a.insert(CKM_SHA384);
+ value4a.insert(CKM_SHA512);
+
+ // Create the test object
+ {
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock", true);
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock", true);
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ bool value1 = true;
+ unsigned long value2 = 0x87654321;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ALLOWED_MECHANISMS, attr4));
+ }
+
+ // Now read back the object
+ {
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock");
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock");
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_TOKEN));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_VALUE));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_ALLOWED_MECHANISMS));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == 0x87654321);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).getByteStringValue() == value3);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4);
+
+ bool value1 = false;
+ unsigned long value2 = 0x76767676;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3a);
+ OSAttribute attr4(value4a);
+
+ // Change the attributes
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ALLOWED_MECHANISMS, attr4));
+
+ // Check the attributes
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == value1);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).getByteStringValue() == value3a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4a);
+
+ // Open the object a second time
+#ifndef _WIN32
+ ObjectFile testObject2(NULL, "testdir/test.object", "testdir/test.lock");
+#else
+ ObjectFile testObject2(NULL, "testdir\\test.object", "testdir\\test.lock");
+#endif
+
+ CPPUNIT_ASSERT(testObject2.isValid());
+
+ // Check the attributes on the second instance
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).getBooleanValue() == value1);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE).getByteStringValue() == value3a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4a);
+
+ // Add an attribute on the second object
+ ByteString id = "0102010201020102010201020102010201020102";
+
+ OSAttribute attr5(id);
+
+ CPPUNIT_ASSERT(testObject2.setAttribute(CKA_ID, attr5));
+
+ // Check the attribute
+ CPPUNIT_ASSERT(testObject2.attributeExists(CKA_ID));
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ID).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ID).getByteStringValue() == id);
+
+ // Now check that the first instance also knows about it
+ CPPUNIT_ASSERT(testObject.isValid());
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_ID));
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ID).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ID).getByteStringValue() == id);
+
+ // Now change another attribute
+ unsigned long value2a = 0x89898989;
+
+ OSAttribute attr2a(value2a);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2a));
+
+ // Check the attribute
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2a);
+
+ // Now check that the second instance also knows about the change
+ CPPUNIT_ASSERT(testObject2.isValid());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2a);
+ }
+}
+
+void ObjectFileTests::testCorruptFile()
+{
+#ifndef _WIN32
+ FILE* stream = fopen("testdir/test.object", "w");
+#else
+ FILE* stream = fopen("testdir\\test.object", "wb");
+#endif
+ RNG* rng = CryptoFactory::i()->getRNG();
+ ByteString randomData;
+
+ CPPUNIT_ASSERT(stream != NULL);
+ CPPUNIT_ASSERT(rng->generateRandom(randomData, 312));
+ CPPUNIT_ASSERT(fwrite(randomData.const_byte_str(), 1, randomData.size(), stream) == randomData.size());
+ CPPUNIT_ASSERT(!fclose(stream));
+
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock");
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock");
+#endif
+
+ CPPUNIT_ASSERT(!testObject.isValid());
+}
+
+void ObjectFileTests::testTransactions()
+{
+ // Create test object instance
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock", true);
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock", true);
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ bool value1 = true;
+ unsigned long value2 = 0x87654321;
+ ByteString value3 = "BDEBDBEDBBDBEBDEBE792759537328";
+ std::set<CK_MECHANISM_TYPE> value4;
+ value4.insert(CKM_SHA256);
+ value4.insert(CKM_SHA512);
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ALLOWED_MECHANISMS, attr4));
+
+ // Create secondary instance for the same object
+#ifndef _WIN32
+ ObjectFile testObject2(NULL, "testdir/test.object", "testdir/test.lock");
+#else
+ ObjectFile testObject2(NULL, "testdir\\test.object", "testdir\\test.lock");
+#endif
+
+ CPPUNIT_ASSERT(testObject2.isValid());
+
+ // Check that it has the same attributes
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).getBooleanValue() == value1);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE).getByteStringValue() == value3);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4);
+
+ // New values
+ bool value1a = false;
+ unsigned long value2a = 0x12345678;
+ ByteString value3a = "ABABABABABABABABABABABABABABAB";
+ std::set<CK_MECHANISM_TYPE> value4a;
+ value4a.insert(CKM_SHA384);
+ value4a.insert(CKM_SHA512);
+
+ OSAttribute attr1a(value1a);
+ OSAttribute attr2a(value2a);
+ OSAttribute attr3a(value3a);
+ OSAttribute attr4a(value4a);
+
+ // Start transaction on object
+ CPPUNIT_ASSERT(testObject.startTransaction(ObjectFile::ReadWrite));
+
+ // Change the attributes
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1a));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2a));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE, attr3a));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ALLOWED_MECHANISMS, attr4a));
+
+ // Verify that the attributes were set
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == value1a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).getByteStringValue() == value3a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4a);
+
+ // Verify that they are unchanged on the other instance
+ CPPUNIT_ASSERT(testObject2.isValid());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).getBooleanValue() == value1);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE).getByteStringValue() == value3);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4);
+
+ // Commit the transaction
+ CPPUNIT_ASSERT(testObject.commitTransaction());
+
+ // Verify that they have now changed on the other instance
+ CPPUNIT_ASSERT(testObject2.isValid());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).getBooleanValue() == value1a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE).getByteStringValue() == value3a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4a);
+
+ // Start transaction on object
+ CPPUNIT_ASSERT(testObject.startTransaction(ObjectFile::ReadWrite));
+
+ // Change the attributes
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ALLOWED_MECHANISMS, attr4));
+
+ // Verify that the attributes were set
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == value1);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).getByteStringValue() == value3);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4);
+
+ // Verify that they are unchanged on the other instance
+ CPPUNIT_ASSERT(testObject2.isValid());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).getBooleanValue() == value1a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE).getByteStringValue() == value3a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4a);
+
+ // Abort the transaction
+ CPPUNIT_ASSERT(testObject.abortTransaction());
+
+ // Verify that they are unchanged on both instances
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == value1a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).getByteStringValue() == value3a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4a);
+
+ CPPUNIT_ASSERT(testObject2.isValid());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).getBooleanValue() == value1a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE).getByteStringValue() == value3a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4a);
+}
+
+void ObjectFileTests::testDestroyObjectFails()
+{
+ // Create test object instance
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock", true);
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock", true);
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ OSObject* testIF = (OSObject*) &testObject;
+
+ CPPUNIT_ASSERT(!testIF->destroyObject());
+}
+
diff --git a/SoftHSMv2/src/lib/object_store/test/ObjectFileTests.h b/SoftHSMv2/src/lib/object_store/test/ObjectFileTests.h
new file mode 100644
index 0000000..8342a64
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/ObjectFileTests.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ObjectFileTests.h
+
+ Contains test cases to test the object file implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OBJECTFILETESTS_H
+#define _SOFTHSM_V2_OBJECTFILETESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class ObjectFileTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(ObjectFileTests);
+ CPPUNIT_TEST(testBoolAttr);
+ CPPUNIT_TEST(testULongAttr);
+ CPPUNIT_TEST(testByteStrAttr);
+ CPPUNIT_TEST(testMechTypeSetAttr);
+ CPPUNIT_TEST(testAttrMapAttr);
+ CPPUNIT_TEST(testMixedAttr);
+ CPPUNIT_TEST(testDoubleAttr);
+ CPPUNIT_TEST(testRefresh);
+ CPPUNIT_TEST(testCorruptFile);
+ CPPUNIT_TEST(testTransactions);
+ CPPUNIT_TEST(testDestroyObjectFails);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testBoolAttr();
+ void testULongAttr();
+ void testByteStrAttr();
+ void testMechTypeSetAttr();
+ void testAttrMapAttr();
+ void testMixedAttr();
+ void testDoubleAttr();
+ void testRefresh();
+ void testCorruptFile();
+ void testTransactions();
+ void testDestroyObjectFails();
+
+ void setUp();
+ void tearDown();
+};
+
+#endif // !_SOFTHSM_V2_OBJECTFILETESTS_H
+
diff --git a/SoftHSMv2/src/lib/object_store/test/ObjectStoreTests.cpp b/SoftHSMv2/src/lib/object_store/test/ObjectStoreTests.cpp
new file mode 100644
index 0000000..0cad27b
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/ObjectStoreTests.cpp
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ObjectStoreTests.cpp
+
+ Contains test cases to test the object store implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "ObjectStoreTests.h"
+#include "ObjectStore.h"
+#include "File.h"
+#include "Directory.h"
+#include "OSAttribute.h"
+#include "OSAttributes.h"
+#include "cryptoki.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(ObjectStoreTests);
+
+// FIXME: all pathnames in this file are *NIX/BSD specific
+
+void ObjectStoreTests::setUp()
+{
+ CPPUNIT_ASSERT(!system("mkdir testdir"));
+}
+
+void ObjectStoreTests::tearDown()
+{
+#ifndef _WIN32
+ CPPUNIT_ASSERT(!system("rm -rf testdir"));
+#else
+ CPPUNIT_ASSERT(!system("rmdir /s /q testdir 2> nul"));
+#endif
+}
+
+void ObjectStoreTests::testEmptyStore()
+{
+ // Create the store for an empty dir
+#ifndef _WIN32
+ ObjectStore store("./testdir");
+#else
+ ObjectStore store(".\\testdir");
+#endif
+
+ CPPUNIT_ASSERT(store.getTokenCount() == 0);
+}
+
+void ObjectStoreTests::testNewTokens()
+{
+ ByteString label1 = "DEADC0FFEE";
+ ByteString label2 = "DEADBEEF";
+
+ {
+ // Create an empty store
+#ifndef _WIN32
+ ObjectStore store("./testdir");
+#else
+ ObjectStore store(".\\testdir");
+#endif
+
+ CPPUNIT_ASSERT(store.getTokenCount() == 0);
+
+ // Create a new token
+ ObjectStoreToken* token1 = store.newToken(label1);
+
+ CPPUNIT_ASSERT(token1 != NULL);
+
+ CPPUNIT_ASSERT(store.getTokenCount() == 1);
+
+ // Create another new token
+ ObjectStoreToken* token2 = store.newToken(label2);
+
+ CPPUNIT_ASSERT(token2 != NULL);
+
+ CPPUNIT_ASSERT(store.getTokenCount() == 2);
+ }
+
+ // Now reopen that same store
+#ifndef _WIN32
+ ObjectStore store("./testdir");
+#else
+ ObjectStore store(".\\testdir");
+#endif
+
+ CPPUNIT_ASSERT(store.getTokenCount() == 2);
+
+ // Retrieve both tokens and check that both are present
+ ObjectStoreToken* token1 = store.getToken(0);
+ ObjectStoreToken* token2 = store.getToken(1);
+
+ ByteString retrieveLabel1, retrieveLabel2;
+
+ CPPUNIT_ASSERT(token1->getTokenLabel(retrieveLabel1));
+ CPPUNIT_ASSERT(token2->getTokenLabel(retrieveLabel2));
+
+ CPPUNIT_ASSERT((retrieveLabel1 == label1) || (retrieveLabel2 == label1));
+ CPPUNIT_ASSERT((retrieveLabel2 == label1) || (retrieveLabel2 == label2));
+
+ ByteString retrieveSerial1, retrieveSerial2;
+
+ CPPUNIT_ASSERT(token1->getTokenSerial(retrieveSerial1));
+ CPPUNIT_ASSERT(token2->getTokenSerial(retrieveSerial2));
+
+ CPPUNIT_ASSERT(retrieveSerial1 != retrieveSerial2);
+}
+
+void ObjectStoreTests::testExistingTokens()
+{
+ // Create some tokens
+ ByteString label1 = "DEADC0FFEE";
+ ByteString label2 = "DEADBEEF";
+ ByteString serial1 = "0011001100110011";
+ ByteString serial2 = "2233223322332233";
+
+#ifndef _WIN32
+ ObjectStoreToken* token1 = ObjectStoreToken::createToken("./testdir", "token1", label1, serial1);
+ ObjectStoreToken* token2 = ObjectStoreToken::createToken("./testdir", "token2", label2, serial2);
+#else
+ ObjectStoreToken* token1 = ObjectStoreToken::createToken(".\\testdir", "token1", label1, serial1);
+ ObjectStoreToken* token2 = ObjectStoreToken::createToken(".\\testdir", "token2", label2, serial2);
+#endif
+
+ CPPUNIT_ASSERT((token1 != NULL) && (token2 != NULL));
+
+ delete token1;
+ delete token2;
+
+ // Now associate a store with the test directory
+#ifndef _WIN32
+ ObjectStore store("./testdir");
+#else
+ ObjectStore store(".\\testdir");
+#endif
+
+ CPPUNIT_ASSERT(store.getTokenCount() == 2);
+
+ // Retrieve both tokens and check that both are present
+ ObjectStoreToken* retrieveToken1 = store.getToken(0);
+ ObjectStoreToken* retrieveToken2 = store.getToken(1);
+
+ ByteString retrieveLabel1, retrieveLabel2, retrieveSerial1, retrieveSerial2;
+
+ CPPUNIT_ASSERT(retrieveToken1 != NULL);
+ CPPUNIT_ASSERT(retrieveToken2 != NULL);
+
+ CPPUNIT_ASSERT(retrieveToken1->getTokenLabel(retrieveLabel1));
+ CPPUNIT_ASSERT(retrieveToken2->getTokenLabel(retrieveLabel2));
+ CPPUNIT_ASSERT(retrieveToken1->getTokenSerial(retrieveSerial1));
+ CPPUNIT_ASSERT(retrieveToken2->getTokenSerial(retrieveSerial2));
+
+ CPPUNIT_ASSERT((retrieveLabel1 == label1) || (retrieveLabel1 == label2));
+ CPPUNIT_ASSERT((retrieveLabel2 == label1) || (retrieveLabel2 == label2));
+ CPPUNIT_ASSERT(retrieveLabel1 != retrieveLabel2);
+ CPPUNIT_ASSERT((retrieveSerial1 == serial1) || (retrieveSerial1 == serial2));
+ CPPUNIT_ASSERT((retrieveSerial2 == serial1) || (retrieveSerial2 == serial2));
+ CPPUNIT_ASSERT(retrieveSerial1 != retrieveSerial2);
+}
+
+void ObjectStoreTests::testDeleteToken()
+{
+ // Create some tokens
+ ByteString label1 = "DEADC0FFEE";
+ ByteString label2 = "DEADBEEF";
+ ByteString serial1 = "0011001100110011";
+ ByteString serial2 = "2233223322332233";
+
+#ifndef _WIN32
+ ObjectStoreToken* token1 = ObjectStoreToken::createToken("./testdir", "token1", label1, serial1);
+ ObjectStoreToken* token2 = ObjectStoreToken::createToken("./testdir", "token2", label2, serial2);
+#else
+ ObjectStoreToken* token1 = ObjectStoreToken::createToken(".\\testdir", "token1", label1, serial1);
+ ObjectStoreToken* token2 = ObjectStoreToken::createToken(".\\testdir", "token2", label2, serial2);
+#endif
+
+ CPPUNIT_ASSERT((token1 != NULL) && (token2 != NULL));
+
+ delete token1;
+ delete token2;
+
+ // Now associate a store with the test directory
+#ifndef _WIN32
+ ObjectStore store("./testdir");
+#else
+ ObjectStore store(".\\testdir");
+#endif
+
+ CPPUNIT_ASSERT(store.getTokenCount() == 2);
+
+ // Retrieve both tokens and check that both are present
+ ObjectStoreToken* retrieveToken1 = store.getToken(0);
+ ObjectStoreToken* retrieveToken2 = store.getToken(1);
+
+ ByteString retrieveLabel1, retrieveLabel2, retrieveSerial1, retrieveSerial2;
+
+ CPPUNIT_ASSERT(retrieveToken1 != NULL);
+ CPPUNIT_ASSERT(retrieveToken2 != NULL);
+
+ CPPUNIT_ASSERT(retrieveToken1->getTokenLabel(retrieveLabel1));
+ CPPUNIT_ASSERT(retrieveToken2->getTokenLabel(retrieveLabel2));
+ CPPUNIT_ASSERT(retrieveToken1->getTokenSerial(retrieveSerial1));
+ CPPUNIT_ASSERT(retrieveToken2->getTokenSerial(retrieveSerial2));
+
+ CPPUNIT_ASSERT((retrieveLabel1 == label1) || (retrieveLabel1 == label2));
+ CPPUNIT_ASSERT((retrieveLabel2 == label1) || (retrieveLabel2 == label2));
+ CPPUNIT_ASSERT(retrieveLabel1 != retrieveLabel2);
+ CPPUNIT_ASSERT((retrieveSerial1 == serial1) || (retrieveSerial1 == serial2));
+ CPPUNIT_ASSERT((retrieveSerial2 == serial1) || (retrieveSerial2 == serial2));
+ CPPUNIT_ASSERT(retrieveSerial1 != retrieveSerial2);
+
+ // Now, delete token #1
+ CPPUNIT_ASSERT(store.destroyToken(retrieveToken1));
+
+ CPPUNIT_ASSERT(store.getTokenCount() == 1);
+
+ ObjectStoreToken* retrieveToken_ = store.getToken(0);
+
+ ByteString retrieveLabel_,retrieveSerial_;
+
+ CPPUNIT_ASSERT(retrieveToken_->getTokenLabel(retrieveLabel_));
+ CPPUNIT_ASSERT(retrieveToken_->getTokenSerial(retrieveSerial_));
+
+ CPPUNIT_ASSERT(((retrieveLabel_ == label1) && (retrieveSerial_ == serial1)) ||
+ ((retrieveLabel_ == label2) && (retrieveSerial_ == serial2)));
+
+ // Now add a new token
+ ByteString label3 = "DEADC0FFEEBEEF";
+
+ // Create a new token
+ ObjectStoreToken* tokenNew = store.newToken(label3);
+
+ CPPUNIT_ASSERT(tokenNew != NULL);
+
+ CPPUNIT_ASSERT(store.getTokenCount() == 2);
+
+ // Retrieve both tokens and check that both are present
+ ObjectStoreToken* retrieveToken1_ = store.getToken(0);
+ ObjectStoreToken* retrieveToken2_ = store.getToken(1);
+
+ CPPUNIT_ASSERT(retrieveToken1_ != NULL);
+ CPPUNIT_ASSERT(retrieveToken2_ != NULL);
+
+ CPPUNIT_ASSERT(retrieveToken1_->getTokenLabel(retrieveLabel1));
+ CPPUNIT_ASSERT(retrieveToken2_->getTokenLabel(retrieveLabel2));
+ CPPUNIT_ASSERT(retrieveToken1_->getTokenSerial(retrieveSerial1));
+ CPPUNIT_ASSERT(retrieveToken2_->getTokenSerial(retrieveSerial2));
+
+ CPPUNIT_ASSERT((retrieveLabel1 == label3) || (retrieveLabel2 == label3));
+ CPPUNIT_ASSERT(((retrieveLabel1 == label1) && (retrieveLabel2 != label2)) ||
+ ((retrieveLabel1 == label2) && (retrieveLabel2 != label1)));
+ CPPUNIT_ASSERT(retrieveLabel1 != retrieveLabel2);
+}
+
diff --git a/SoftHSMv2/src/lib/object_store/test/ObjectStoreTests.h b/SoftHSMv2/src/lib/object_store/test/ObjectStoreTests.h
new file mode 100644
index 0000000..3f03c5a
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/ObjectStoreTests.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ObjectStoreTests.h
+
+ Contains test cases to test the object store implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OBJECTSTORETESTS_H
+#define _SOFTHSM_V2_OBJECTSTORETESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class ObjectStoreTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(ObjectStoreTests);
+ CPPUNIT_TEST(testEmptyStore);
+ CPPUNIT_TEST(testNewTokens);
+ CPPUNIT_TEST(testExistingTokens);
+ CPPUNIT_TEST(testDeleteToken);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testEmptyStore();
+ void testNewTokens();
+ void testExistingTokens();
+ void testDeleteToken();
+
+ void setUp();
+ void tearDown();
+};
+
+#endif // !_SOFTHSM_V2_OBJECTSTORETESTS_H
+
diff --git a/SoftHSMv2/src/lib/object_store/test/SessionObjectStoreTests.cpp b/SoftHSMv2/src/lib/object_store/test/SessionObjectStoreTests.cpp
new file mode 100644
index 0000000..2c41eb0
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/SessionObjectStoreTests.cpp
@@ -0,0 +1,319 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SessionObjectStoreTests.cpp
+
+ Contains test cases to test the session object store implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <memory>
+#include "SessionObjectStoreTests.h"
+#include "SessionObjectStore.h"
+#include "SessionObject.h"
+#include "OSAttribute.h"
+#include "OSAttributes.h"
+#include "cryptoki.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SessionObjectStoreTests);
+
+void SessionObjectStoreTests::setUp()
+{
+}
+
+void SessionObjectStoreTests::tearDown()
+{
+}
+
+void SessionObjectStoreTests::testCreateDeleteObjects()
+{
+ // Test IDs
+ ByteString id[5] = { "112233445566", "AABBCCDDEEFF", "ABABABABABAB", "557788991122", "005500550055" };
+ OSAttribute idAtt[5] = { id[0], id[1], id[2], id[3], id[4] };
+ ByteString label = "AABBCCDDEEFF";
+ ByteString serial = "1234567890";
+
+ // Get access to the session object store
+ SessionObjectStore* testStore = new SessionObjectStore();
+
+ // Create 3 objects in the store
+ SessionObject* obj1 = testStore->createObject(1, 1);
+ CPPUNIT_ASSERT(obj1 != NULL);
+ SessionObject* obj2 = testStore->createObject(1, 1);
+ CPPUNIT_ASSERT(obj2 != NULL);
+ SessionObject* obj3 = testStore->createObject(1, 1);
+ CPPUNIT_ASSERT(obj3 != NULL);
+
+ // Now set the IDs of the 3 objects
+ obj1->setAttribute(CKA_ID, idAtt[0]);
+ obj2->setAttribute(CKA_ID, idAtt[1]);
+ obj3->setAttribute(CKA_ID, idAtt[2]);
+
+ // Check that the store contains 3 objects
+ CPPUNIT_ASSERT(testStore->getObjects().size() == 3);
+
+ // Check that all three objects are distinct and present
+ std::set<SessionObject*> objects = testStore->getObjects();
+ bool present1[3] = { false, false, false };
+
+ for (std::set<SessionObject*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID).isByteStringAttribute());
+
+ for (int j = 0; j < 3; j++)
+ {
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[j])
+ {
+ present1[j] = true;
+ }
+ }
+ }
+
+ for (int j = 0; j < 3; j++)
+ {
+ CPPUNIT_ASSERT(present1[j] == true);
+ }
+
+ // Now delete the second object
+ for (std::set<SessionObject*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID).isByteStringAttribute());
+
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[1])
+ {
+ CPPUNIT_ASSERT(testStore->deleteObject(*i));
+ break;
+ }
+ }
+
+ // Verify that it was indeed removed
+ CPPUNIT_ASSERT(testStore->getObjects().size() == 2);
+
+ objects = testStore->getObjects();
+ bool present3[2] = { false, false };
+
+ for (std::set<SessionObject*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID).isByteStringAttribute());
+
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[0])
+ {
+ present3[0] = true;
+ }
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[2])
+ {
+ present3[1] = true;
+ }
+ }
+
+ for (int j = 0; j < 2; j++)
+ {
+ CPPUNIT_ASSERT(present3[j] == true);
+ }
+
+ delete testStore;
+}
+
+void SessionObjectStoreTests::testMultiSession()
+{
+ // Get access to the store
+ SessionObjectStore* store = new SessionObjectStore();
+
+ // Check that the store is empty
+ CPPUNIT_ASSERT(store->getObjects().size() == 0);
+
+ // Test IDs
+ ByteString id[5] = { "112233445566", "AABBCCDDEEFF", "ABABABABABAB", "557788991122", "005500550055" };
+ OSAttribute idAtt[5] = { id[0], id[1], id[2], id[3], id[4] };
+
+ // Create 3 objects in the store for three different sessions
+ SessionObject* obj1 = store->createObject(1, 1);
+ CPPUNIT_ASSERT(obj1 != NULL);
+ SessionObject* obj2 = store->createObject(1, 2);
+ CPPUNIT_ASSERT(obj2 != NULL);
+ SessionObject* obj3 = store->createObject(1, 3);
+ CPPUNIT_ASSERT(obj3 != NULL);
+
+ // Now set the IDs of the 3 objects
+ obj1->setAttribute(CKA_ID, idAtt[0]);
+ obj2->setAttribute(CKA_ID, idAtt[1]);
+ obj3->setAttribute(CKA_ID, idAtt[2]);
+
+ // Check that the store contains 3 objects
+ CPPUNIT_ASSERT(store->getObjects().size() == 3);
+
+ // Check that all three objects are distinct and present
+ std::set<SessionObject*> objects = store->getObjects();
+ bool present1[3] = { false, false, false };
+
+ for (std::set<SessionObject*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID).isByteStringAttribute());
+
+ for (int j = 0; j < 3; j++)
+ {
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[j])
+ {
+ present1[j] = true;
+ }
+ }
+ }
+
+ for (int j = 0; j < 3; j++)
+ {
+ CPPUNIT_ASSERT(present1[j] == true);
+ }
+
+ // Now indicate that the second session has been closed
+ store->sessionClosed(2);
+
+ // Verify that it was indeed removed
+ CPPUNIT_ASSERT(store->getObjects().size() == 2);
+
+ objects = store->getObjects();
+ bool present3[2] = { false, false };
+
+ for (std::set<SessionObject*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID).isByteStringAttribute());
+
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[0])
+ {
+ present3[0] = true;
+ }
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[2])
+ {
+ present3[1] = true;
+ }
+ }
+
+ for (int j = 0; j < 2; j++)
+ {
+ CPPUNIT_ASSERT(present3[j] == true);
+ }
+
+ // Create two more objects for session 7
+ SessionObject* obj4 = store->createObject(1, 7);
+ CPPUNIT_ASSERT(obj4 != NULL);
+ SessionObject* obj5 = store->createObject(1, 7);
+ CPPUNIT_ASSERT(obj5 != NULL);
+
+ CPPUNIT_ASSERT(store->getObjects().size() == 4);
+
+ // Close session 1
+ store->sessionClosed(1);
+
+ CPPUNIT_ASSERT(store->getObjects().size() == 3);
+
+ objects = store->getObjects();
+
+ CPPUNIT_ASSERT(objects.find(obj1) == objects.end());
+ CPPUNIT_ASSERT(objects.find(obj2) == objects.end());
+ CPPUNIT_ASSERT(objects.find(obj3) != objects.end());
+ CPPUNIT_ASSERT(objects.find(obj4) != objects.end());
+ CPPUNIT_ASSERT(objects.find(obj5) != objects.end());
+
+ CPPUNIT_ASSERT(!obj1->isValid());
+ CPPUNIT_ASSERT(!obj2->isValid());
+ CPPUNIT_ASSERT(obj3->isValid());
+ CPPUNIT_ASSERT(obj4->isValid());
+ CPPUNIT_ASSERT(obj5->isValid());
+
+ // Close session 7
+ store->sessionClosed(7);
+
+ CPPUNIT_ASSERT(store->getObjects().size() == 1);
+
+ objects = store->getObjects();
+
+ CPPUNIT_ASSERT(objects.find(obj1) == objects.end());
+ CPPUNIT_ASSERT(objects.find(obj2) == objects.end());
+ CPPUNIT_ASSERT(objects.find(obj3) != objects.end());
+ CPPUNIT_ASSERT(objects.find(obj4) == objects.end());
+ CPPUNIT_ASSERT(objects.find(obj5) == objects.end());
+
+ CPPUNIT_ASSERT(!obj1->isValid());
+ CPPUNIT_ASSERT(!obj2->isValid());
+ CPPUNIT_ASSERT(obj3->isValid());
+ CPPUNIT_ASSERT(!obj4->isValid());
+ CPPUNIT_ASSERT(!obj5->isValid());
+
+ delete store;
+}
+
+void SessionObjectStoreTests::testWipeStore()
+{
+ // Get access to the store
+ SessionObjectStore* store = new SessionObjectStore();
+
+ // Check that the store is empty
+ CPPUNIT_ASSERT(store->getObjects().size() == 0);
+
+ // Create 3 objects in the store for three different sessions
+ SessionObject* obj1 = store->createObject(1, 1);
+ CPPUNIT_ASSERT(obj1 != NULL);
+ SessionObject* obj2 = store->createObject(1, 2);
+ CPPUNIT_ASSERT(obj2 != NULL);
+ SessionObject* obj3 = store->createObject(1, 3);
+ CPPUNIT_ASSERT(obj3 != NULL);
+
+ // Wipe the store
+ store->clearStore();
+
+ // Check that the store is empty
+ CPPUNIT_ASSERT(store->getObjects().size() == 0);
+
+ delete store;
+}
+
diff --git a/SoftHSMv2/src/lib/object_store/test/SessionObjectStoreTests.h b/SoftHSMv2/src/lib/object_store/test/SessionObjectStoreTests.h
new file mode 100644
index 0000000..374eeaa
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/SessionObjectStoreTests.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SessionObjectStoreTests.h
+
+ Contains test cases to test the session object store implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SESSIONOBJECTSTORETESTS_H
+#define _SOFTHSM_V2_SESSIONOBJECTSTORETESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class SessionObjectStoreTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(SessionObjectStoreTests);
+ CPPUNIT_TEST(testCreateDeleteObjects);
+ CPPUNIT_TEST(testMultiSession);
+ CPPUNIT_TEST(testWipeStore);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testCreateDeleteObjects();
+ void testMultiSession();
+ void testWipeStore();
+
+ void setUp();
+ void tearDown();
+};
+
+#endif // !_SOFTHSM_V2_SESSIONOBJECTSTORETESTS_H
+
diff --git a/SoftHSMv2/src/lib/object_store/test/SessionObjectTests.cpp b/SoftHSMv2/src/lib/object_store/test/SessionObjectTests.cpp
new file mode 100644
index 0000000..6183ec6
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/SessionObjectTests.cpp
@@ -0,0 +1,436 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SessionObjectTests.cpp
+
+ Contains test cases to test the session object implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "SessionObjectTests.h"
+#include "SessionObject.h"
+#include "File.h"
+#include "Directory.h"
+#include "OSAttribute.h"
+#include "cryptoki.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SessionObjectTests);
+
+void SessionObjectTests::setUp()
+{
+}
+
+void SessionObjectTests::tearDown()
+{
+}
+
+void SessionObjectTests::testBoolAttr()
+{
+ SessionObject testObject(NULL, 1, 1);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ bool value1 = true;
+ bool value2 = false;
+ bool value3 = true;
+ bool value4 = true;
+ bool value5 = false;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+ OSAttribute attr5(value5);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SENSITIVE, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_EXTRACTABLE, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_NEVER_EXTRACTABLE, attr4));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SIGN, attr5));
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_TOKEN));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SENSITIVE));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_EXTRACTABLE));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_NEVER_EXTRACTABLE));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SIGN));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SENSITIVE).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_EXTRACTABLE).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_NEVER_EXTRACTABLE).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN).isBooleanAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SENSITIVE).getBooleanValue() == false);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_EXTRACTABLE).getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_NEVER_EXTRACTABLE).getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN).getBooleanValue() == false);
+
+ bool value6 = true;
+ OSAttribute attr6(value6);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VERIFY, attr6));
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VERIFY).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VERIFY).getBooleanValue() == value6);
+ CPPUNIT_ASSERT(testObject.getBooleanValue(CKA_VERIFY, false) == value6);
+}
+
+void SessionObjectTests::testULongAttr()
+{
+ SessionObject testObject(NULL, 1, 1);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ unsigned long value1 = 0x12345678;
+ unsigned long value2 = 0x87654321;
+ unsigned long value3 = 0x01010101;
+ unsigned long value4 = 0x10101010;
+ unsigned long value5 = 0xABCDEF;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+ OSAttribute attr5(value5);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_MODULUS_BITS, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_AUTH_PIN_FLAGS, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SUBPRIME_BITS, attr4));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_KEY_TYPE, attr5));
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_MODULUS_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_AUTH_PIN_FLAGS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SUBPRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_KEY_TYPE));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_MODULUS_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_AUTH_PIN_FLAGS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBPRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_KEY_TYPE).isUnsignedLongAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_MODULUS_BITS).getUnsignedLongValue() == 0x12345678);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == 0x87654321);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_AUTH_PIN_FLAGS).getUnsignedLongValue() == 0x01010101);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBPRIME_BITS).getUnsignedLongValue() == 0x10101010);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_KEY_TYPE).getUnsignedLongValue() == 0xABCDEF);
+
+ unsigned long value6 = 0x90909090;
+ OSAttribute attr6(value6);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_CLASS, attr6));
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_CLASS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_CLASS).getUnsignedLongValue() == value6);
+ CPPUNIT_ASSERT(testObject.getUnsignedLongValue(CKA_CLASS, 0x0) == value6);
+}
+
+void SessionObjectTests::testByteStrAttr()
+{
+ ByteString value1 = "010203040506070809";
+ ByteString value2 = "ABABABABABABABABABABABABABABABABAB";
+ ByteString value3 = "BDEBDBEDBBDBEBDEBE792759537328";
+ ByteString value4 = "98A7E5D798A7E5D798A7E5D798A7E5D798A7E5D798A7E5D7";
+ ByteString value5 = "ABCDABCDABCDABCDABCDABCDABCDABCD";
+
+ SessionObject testObject(NULL, 1, 1);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+ OSAttribute attr5(value5);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_MODULUS, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_COEFFICIENT, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PUBLIC_EXPONENT, attr4));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SUBJECT, attr5));
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_MODULUS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_COEFFICIENT));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_VALUE_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PUBLIC_EXPONENT));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SUBJECT));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_MODULUS).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_COEFFICIENT).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PUBLIC_EXPONENT).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBJECT).isByteStringAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_MODULUS).getByteStringValue() == value1);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_COEFFICIENT).getByteStringValue() == value2);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).getByteStringValue() == value3);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PUBLIC_EXPONENT).getByteStringValue() == value4);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBJECT).getByteStringValue() == value5);
+
+ ByteString value6 = "909090908080808080807070707070FF";
+ OSAttribute attr6(value6);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ISSUER, attr6));
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ISSUER).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getByteStringValue(CKA_ISSUER) == value6);
+}
+
+void SessionObjectTests::testMechTypeSetAttr()
+{
+ SessionObject testObject(NULL, 1, 1);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ std::set<CK_MECHANISM_TYPE> set;
+ set.insert(CKM_SHA256);
+ set.insert(CKM_SHA512);
+
+ OSAttribute attr(set);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ALLOWED_MECHANISMS, attr));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_ALLOWED_MECHANISMS));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ std::set<CK_MECHANISM_TYPE> retrieved =
+ testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue();
+
+ CPPUNIT_ASSERT(retrieved.size() == 2);
+ CPPUNIT_ASSERT(retrieved.find(CKM_SHA256) != retrieved.end());
+ CPPUNIT_ASSERT(retrieved.find(CKM_SHA384) == retrieved.end());
+ CPPUNIT_ASSERT(retrieved.find(CKM_SHA512) != retrieved.end());
+}
+
+void SessionObjectTests::testAttrMapAttr()
+{
+ SessionObject testObject(NULL, 1, 1);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ bool value1 = true;
+ unsigned long value2 = 0x87654321;
+ ByteString value3 = "BDEBDBEDBBDBEBDEBE792759537328";
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute> mattr;
+ mattr.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (CKA_TOKEN, attr1));
+ mattr.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (CKA_PRIME_BITS, attr2));
+ mattr.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (CKA_VALUE_BITS, attr3));
+ OSAttribute attra(mattr);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_WRAP_TEMPLATE, attra));
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_WRAP_TEMPLATE));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_UNWRAP_TEMPLATE));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_WRAP_TEMPLATE).isAttributeMapAttribute());
+
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute> mattrb =
+ testObject.getAttribute(CKA_WRAP_TEMPLATE).getAttributeMapValue();
+ CPPUNIT_ASSERT(mattrb.size() == 3);
+ CPPUNIT_ASSERT(mattrb.find(CKA_TOKEN) != mattrb.end());
+ CPPUNIT_ASSERT(mattrb.at(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(mattrb.at(CKA_TOKEN).getBooleanValue() == true);
+ CPPUNIT_ASSERT(mattrb.find(CKA_PRIME_BITS) != mattrb.end());
+ CPPUNIT_ASSERT(mattrb.at(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(mattrb.at(CKA_PRIME_BITS).getUnsignedLongValue() == 0x87654321);
+ CPPUNIT_ASSERT(mattrb.find(CKA_VALUE_BITS) != mattrb.end());
+ CPPUNIT_ASSERT(mattrb.at(CKA_VALUE_BITS).isByteStringAttribute());
+ CPPUNIT_ASSERT(mattrb.at(CKA_VALUE_BITS).getByteStringValue() == value3);
+
+}
+
+void SessionObjectTests::testMixedAttr()
+{
+ ByteString value3 = "BDEBDBEDBBDBEBDEBE792759537328";
+
+ SessionObject testObject(NULL, 1, 1);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ bool value1 = true;
+ unsigned long value2 = 0x87654321;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3));
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_TOKEN));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_VALUE_BITS));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).isByteStringAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == 0x87654321);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).getByteStringValue() == value3);
+}
+
+void SessionObjectTests::testDoubleAttr()
+{
+ ByteString value3 = "BDEBDBEDBBDBEBDEBE792759537328";
+ ByteString value3a = "466487346943785684957634";
+
+ SessionObject testObject(NULL, 1, 1);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ bool value1 = true;
+ unsigned long value2 = 0x87654321;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3));
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_TOKEN));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_VALUE_BITS));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).isByteStringAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == 0x87654321);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).getByteStringValue() == value3);
+
+ bool value1a = false;
+ unsigned long value2a = 0x76767676;
+
+ OSAttribute attr1a(value1a);
+ OSAttribute attr2a(value2a);
+ OSAttribute attr3a(value3a);
+
+ // Change the attributes
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1a));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2a));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3a));
+
+ // Check the attributes
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).isByteStringAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == value1a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).getByteStringValue() == value3a);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+}
+
+void SessionObjectTests::testCloseSession()
+{
+ ByteString value3 = "BDEBDBEDBBDBEBDEBE792759537328";
+
+ SessionObject testObject(NULL, 1, 1);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ bool value1 = true;
+ unsigned long value2 = 0x87654321;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3));
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_TOKEN));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_VALUE_BITS));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).isByteStringAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == 0x87654321);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).getByteStringValue() == value3);
+
+ // Now close the session
+ testObject.removeOnSessionClose(1);
+
+ CPPUNIT_ASSERT(!testObject.isValid());
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_TOKEN));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_PRIME_BITS));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_VALUE_BITS));
+}
+
+void SessionObjectTests::testDestroyObjectFails()
+{
+ // Create test object instance
+ SessionObject testObject(NULL, 1, 1);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ OSObject* testIF = (OSObject*) &testObject;
+
+ CPPUNIT_ASSERT(!testIF->destroyObject());
+}
+
diff --git a/SoftHSMv2/src/lib/object_store/test/SessionObjectTests.h b/SoftHSMv2/src/lib/object_store/test/SessionObjectTests.h
new file mode 100644
index 0000000..76fa02e
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/SessionObjectTests.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SessionObjectTests.h
+
+ Contains test cases to test the session object implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SESSIONOBJECTTESTS_H
+#define _SOFTHSM_V2_SESSIONOBJECTTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class SessionObjectTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(SessionObjectTests);
+ CPPUNIT_TEST(testBoolAttr);
+ CPPUNIT_TEST(testULongAttr);
+ CPPUNIT_TEST(testByteStrAttr);
+ CPPUNIT_TEST(testMechTypeSetAttr);
+ CPPUNIT_TEST(testAttrMapAttr);
+ CPPUNIT_TEST(testMixedAttr);
+ CPPUNIT_TEST(testDoubleAttr);
+ CPPUNIT_TEST(testCloseSession);
+ CPPUNIT_TEST(testDestroyObjectFails);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testBoolAttr();
+ void testULongAttr();
+ void testByteStrAttr();
+ void testMechTypeSetAttr();
+ void testAttrMapAttr();
+ void testMixedAttr();
+ void testDoubleAttr();
+ void testCloseSession();
+ void testDestroyObjectFails();
+
+ void setUp();
+ void tearDown();
+};
+
+#endif // !_SOFTHSM_V2_SESSIONOBJECTTESTS_H
+
diff --git a/SoftHSMv2/src/lib/object_store/test/UUIDTests.cpp b/SoftHSMv2/src/lib/object_store/test/UUIDTests.cpp
new file mode 100644
index 0000000..84a49d2
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/UUIDTests.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ UUIDTests.cpp
+
+ Contains test cases to test the UUID implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "UUIDTests.h"
+#include "UUID.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(UUIDTests);
+
+void UUIDTests::setUp()
+{
+}
+
+void UUIDTests::tearDown()
+{
+}
+
+void UUIDTests::testUUID()
+{
+ std::string uuid1 = UUID::newUUID();
+ std::string uuid2 = UUID::newUUID();
+ std::string uuid3 = UUID::newUUID();
+
+ CPPUNIT_ASSERT((uuid1.size() == 36) && (uuid2.size() == 36) && (uuid3.size() == 36));
+
+ CPPUNIT_ASSERT(uuid1.compare(uuid2));
+ CPPUNIT_ASSERT(uuid1.compare(uuid3));
+ CPPUNIT_ASSERT(uuid2.compare(uuid3));
+}
+
diff --git a/SoftHSMv2/src/lib/object_store/test/UUIDTests.h b/SoftHSMv2/src/lib/object_store/test/UUIDTests.h
new file mode 100644
index 0000000..374d509
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/UUIDTests.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ UUIDTests.h
+
+ Contains test cases to test the UUID implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_UUIDTESTS_H
+#define _SOFTHSM_V2_UUIDTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class UUIDTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(UUIDTests);
+ CPPUNIT_TEST(testUUID);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testUUID();
+
+ void setUp();
+ void tearDown();
+
+private:
+};
+
+#endif // !_SOFTHSM_V2_UUIDTESTS_H
+
diff --git a/SoftHSMv2/src/lib/object_store/test/objstoretest.cpp b/SoftHSMv2/src/lib/object_store/test/objstoretest.cpp
new file mode 100644
index 0000000..7e4b854
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/objstoretest.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ objstoretest.cpp
+
+ The main test executor for tests on the object store in SoftHSM v2
+ *****************************************************************************/
+
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/ui/text/TestRunner.h>
+#include <cppunit/TestResult.h>
+#include <cppunit/TestResultCollector.h>
+#include <cppunit/XmlOutputter.h>
+#include <fstream>
+
+#include "config.h"
+#include "MutexFactory.h"
+#include "SecureMemoryRegistry.h"
+
+#if defined(WITH_OPENSSL)
+#include "OSSLCryptoFactory.h"
+#else
+#include "BotanCryptoFactory.h"
+#endif
+
+// Initialise the one-and-only instance
+#ifdef HAVE_CXX11
+
+std::unique_ptr<MutexFactory> MutexFactory::instance(nullptr);
+std::unique_ptr<SecureMemoryRegistry> SecureMemoryRegistry::instance(nullptr);
+#if defined(WITH_OPENSSL)
+std::unique_ptr<OSSLCryptoFactory> OSSLCryptoFactory::instance(nullptr);
+#else
+std::unique_ptr<BotanCryptoFactory> BotanCryptoFactory::instance(nullptr);
+#endif
+
+#else
+
+std::auto_ptr<MutexFactory> MutexFactory::instance(NULL);
+std::auto_ptr<SecureMemoryRegistry> SecureMemoryRegistry::instance(NULL);
+#if defined(WITH_OPENSSL)
+std::auto_ptr<OSSLCryptoFactory> OSSLCryptoFactory::instance(NULL);
+#else
+std::auto_ptr<BotanCryptoFactory> BotanCryptoFactory::instance(NULL);
+#endif
+
+#endif
+
+int main(int /*argc*/, char** /*argv*/)
+{
+ CppUnit::TestResult controller;
+ CppUnit::TestResultCollector result;
+ CppUnit::TextUi::TestRunner runner;
+ controller.addListener(&result);
+ CppUnit::TestFactoryRegistry &registry = CppUnit::TestFactoryRegistry::getRegistry();
+
+ runner.addTest(registry.makeTest());
+ runner.run(controller);
+
+ std::ofstream xmlFileOut("test-results.xml");
+ CppUnit::XmlOutputter xmlOut(&result, xmlFileOut);
+ xmlOut.write();
+
+ CryptoFactory::reset();
+
+ return result.wasSuccessful() ? 0 : 1;
+}