blob: ef43a646dbccec852339dca71db500ea4bf2b485 [file] [log] [blame]
// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chaps/object_pool_impl.h"
#include <map>
#include <string>
#include <vector>
#include <base/scoped_ptr.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "chaps/attributes.pb.h"
#include "chaps/chaps_factory_mock.h"
#include "chaps/handle_generator_mock.h"
#include "chaps/object_mock.h"
#include "chaps/object_store_mock.h"
using std::map;
using std::string;
using std::vector;
using ::testing::_;
using ::testing::AnyNumber;
using ::testing::DoAll;
using ::testing::Invoke;
using ::testing::Return;
using ::testing::SetArgumentPointee;
namespace chaps {
namespace {
Object* CreateObjectMock() {
ObjectMock* o = new ObjectMock();
o->SetupFake();
EXPECT_CALL(*o, GetObjectClass()).Times(AnyNumber());
EXPECT_CALL(*o, SetAttributes(_, _)).Times(AnyNumber());
EXPECT_CALL(*o, FinalizeNewObject()).WillRepeatedly(Return(CKR_OK));
EXPECT_CALL(*o, Copy(_)).WillRepeatedly(Return(CKR_OK));
EXPECT_CALL(*o, IsTokenObject()).Times(AnyNumber());
EXPECT_CALL(*o, IsPrivate()).Times(AnyNumber());
EXPECT_CALL(*o, IsAttributePresent(_)).Times(AnyNumber());
EXPECT_CALL(*o, GetAttributeString(_)).Times(AnyNumber());
EXPECT_CALL(*o, GetAttributeInt(_, _)).Times(AnyNumber());
EXPECT_CALL(*o, GetAttributeBool(_, _)).Times(AnyNumber());
EXPECT_CALL(*o, SetAttributeString(_, _)).Times(AnyNumber());
EXPECT_CALL(*o, SetAttributeInt(_, _)).Times(AnyNumber());
EXPECT_CALL(*o, SetAttributeBool(_, _)).Times(AnyNumber());
EXPECT_CALL(*o, GetAttributeMap()).Times(AnyNumber());
EXPECT_CALL(*o, set_handle(_)).Times(AnyNumber());
EXPECT_CALL(*o, set_store_id(_)).Times(AnyNumber());
EXPECT_CALL(*o, handle()).Times(AnyNumber());
EXPECT_CALL(*o, store_id()).Times(AnyNumber());
return o;
}
int CreateHandle() {
static int last_handle = 0;
return ++last_handle;
}
} // namespace
// A test fixture for object pools.
class TestObjectPool : public ::testing::Test {
public:
TestObjectPool() {
// Setup the factory to return functional fake objects.
EXPECT_CALL(factory_, CreateObject())
.WillRepeatedly(Invoke(CreateObjectMock));
EXPECT_CALL(handle_generator_, CreateHandle())
.WillRepeatedly(Invoke(CreateHandle));
// Create object pools to test with.
store_ = new ObjectStoreMock();
pool_.reset(new ObjectPoolImpl(&factory_, &handle_generator_, store_));
pool2_.reset(new ObjectPoolImpl(&factory_, &handle_generator_, NULL));
}
ChapsFactoryMock factory_;
ObjectStoreMock* store_;
HandleGeneratorMock handle_generator_;
scoped_ptr<ObjectPoolImpl> pool_;
scoped_ptr<ObjectPoolImpl> pool2_;
};
// Test object pool initialization when using an object store.
TEST_F(TestObjectPool, Init) {
// Create some fake persistent objects for the mock store to return.
map<int, string> persistent_objects;
AttributeList l;
Attribute* a = l.add_attribute();
a->set_type(CKA_ID);
a->set_value("value");
string s;
l.SerializeToString(&s);
persistent_objects[1] = s;
persistent_objects[2] = "not_valid_protobuf";
EXPECT_CALL(*store_, LoadAllObjectBlobs(_))
.WillOnce(Return(false))
.WillRepeatedly(DoAll(SetArgumentPointee<0>(persistent_objects),
Return(true)));
EXPECT_TRUE(pool2_->Init());
EXPECT_FALSE(pool_->Init());
EXPECT_TRUE(pool_->Init());
vector<const Object*> v;
scoped_ptr<Object> find_all(CreateObjectMock());
EXPECT_TRUE(pool_->Find(find_all.get(), &v));
ASSERT_EQ(1, v.size());
EXPECT_TRUE(v[0]->GetAttributeString(CKA_ID) == string("value"));
}
// Test the methods that should just pass through to the object store.
TEST_F(TestObjectPool, StorePassThrough) {
string s("test");
EXPECT_CALL(*store_, GetInternalBlob(1, _))
.WillOnce(Return(false))
.WillOnce(Return(true));
EXPECT_CALL(*store_, SetInternalBlob(1, s))
.WillOnce(Return(false))
.WillOnce(Return(true));
EXPECT_CALL(*store_, SetEncryptionKey(s)).Times(1);
EXPECT_FALSE(pool2_->GetInternalBlob(1, &s));
EXPECT_FALSE(pool2_->SetInternalBlob(1, s));
pool2_->SetEncryptionKey(s);
EXPECT_FALSE(pool_->GetInternalBlob(1, &s));
EXPECT_TRUE(pool_->GetInternalBlob(1, &s));
EXPECT_FALSE(pool_->SetInternalBlob(1, s));
EXPECT_TRUE(pool_->SetInternalBlob(1, s));
pool_->SetEncryptionKey(s);
}
// Test basic object management operations.
TEST_F(TestObjectPool, InsertFindUpdateDelete) {
EXPECT_CALL(*store_, InsertObjectBlob(false, CKO_DATA, "", _, _))
.WillOnce(Return(false))
.WillRepeatedly(DoAll(SetArgumentPointee<4>(3), Return(true)));
EXPECT_CALL(*store_, UpdateObjectBlob(3, _))
.WillOnce(Return(false))
.WillRepeatedly(Return(true));
EXPECT_CALL(*store_, DeleteObjectBlob(3))
.WillOnce(Return(false))
.WillRepeatedly(Return(true));
vector<const Object*> v;
scoped_ptr<Object> find_all(CreateObjectMock());
EXPECT_TRUE(pool2_->Find(find_all.get(), &v));
EXPECT_EQ(0, v.size());
EXPECT_TRUE(pool2_->Insert(CreateObjectMock()));
EXPECT_TRUE(pool2_->Insert(CreateObjectMock()));
EXPECT_TRUE(pool2_->Find(find_all.get(), &v));
ASSERT_EQ(2, v.size());
Object* o = pool2_->GetModifiableObject(v[0]);
EXPECT_TRUE(pool2_->Flush(o));
EXPECT_TRUE(pool2_->Delete(v[0]));
EXPECT_TRUE(pool2_->Delete(v[1]));
v.clear();
EXPECT_TRUE(pool2_->Find(find_all.get(), &v));
EXPECT_EQ(0, v.size());
// Now with the persistent pool.
EXPECT_TRUE(pool_->Find(find_all.get(), &v));
EXPECT_EQ(0, v.size());
Object* tmp = CreateObjectMock();
EXPECT_FALSE(pool_->Insert(tmp));
EXPECT_TRUE(pool_->Insert(tmp));
EXPECT_TRUE(pool_->Find(find_all.get(), &v));
ASSERT_EQ(1, v.size());
o = pool_->GetModifiableObject(v[0]);
EXPECT_FALSE(pool_->Flush(o));
EXPECT_TRUE(pool_->Flush(o));
EXPECT_FALSE(pool_->Delete(v[0]));
EXPECT_TRUE(pool_->Delete(v[0]));
v.clear();
EXPECT_TRUE(pool_->Find(find_all.get(), &v));
EXPECT_EQ(0, v.size());
}
// Test handling of an invalid object pointer.
TEST_F(TestObjectPool, UnknownObject) {
scoped_ptr<Object> o(CreateObjectMock());
EXPECT_FALSE(pool_->Flush(o.get()));
EXPECT_FALSE(pool_->Delete(o.get()));
EXPECT_FALSE(pool2_->Flush(o.get()));
EXPECT_FALSE(pool2_->Delete(o.get()));
}
// Test multiple insertion of the same object pointer.
TEST_F(TestObjectPool, DuplicateObject) {
Object* o = CreateObjectMock();
EXPECT_CALL(*store_, InsertObjectBlob(false, CKO_DATA, "", _, _))
.WillRepeatedly(DoAll(SetArgumentPointee<4>(3), Return(true)));
EXPECT_TRUE(pool_->Insert(o));
EXPECT_FALSE(pool_->Insert(o));
Object* o2 = CreateObjectMock();
EXPECT_TRUE(pool2_->Insert(o2));
EXPECT_FALSE(pool2_->Insert(o2));
}
} // namespace chaps
int main(int argc, char** argv) {
::testing::InitGoogleMock(&argc, argv);
return RUN_ALL_TESTS();
}