// 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 "object_impl.h"

#include <string>

#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "chaps_factory_mock.h"
#include "object_policy_mock.h"

using std::string;
using ::testing::_;
using ::testing::AnyNumber;
using ::testing::InvokeWithoutArgs;
using ::testing::Return;
using ::testing::SetArgumentPointee;

namespace chaps {

// Test fixture for an initialized ObjectImpl instance.
class TestObject: public ::testing::Test {
 public:
  TestObject() {
    scoped_policy_.reset(CreatePolicy());
    next_policy_ = scoped_policy_.get();
    policy_ = NULL;
    EXPECT_CALL(factory_, CreateObjectPolicy(_))
        .WillRepeatedly(InvokeWithoutArgs(this, &TestObject::GetPolicy));
    object_.reset(new ObjectImpl(&factory_));
  }

 protected:
  ObjectPolicyMock* CreatePolicy() {
    ObjectPolicyMock* policy = new ObjectPolicyMock();
    EXPECT_CALL(*policy, Init(_)).Times(AnyNumber());
    EXPECT_CALL(*policy, IsReadAllowed(_)).WillRepeatedly(Return(true));
    EXPECT_CALL(*policy, IsModifyAllowed(_, _)).WillRepeatedly(Return(true));
    EXPECT_CALL(*policy, IsObjectComplete()).WillRepeatedly(Return(true));
    EXPECT_CALL(*policy, SetDefaultAttributes()).Times(AnyNumber());
    return policy;
  }
  ObjectPolicy* GetPolicy() {
    policy_ = scoped_policy_.release();
    scoped_policy_.reset(CreatePolicy());
    next_policy_ = scoped_policy_.get();
    return policy_;
  }
  ChapsFactoryMock factory_;
  ObjectPolicyMock* policy_;  // The policy in use (if any).
  ObjectPolicyMock* next_policy_;  // The policy to be used next.
  scoped_ptr<ObjectPolicyMock> scoped_policy_;  // Owns next_policy_ until used.
  scoped_ptr<ObjectImpl> object_;
};

// Test that the Object class asserts when ChapsFactory fails.
TEST(DeathTest, FactoryFailure) {
  ChapsFactoryMock factory;
  ObjectPolicy* null_policy = NULL;
  EXPECT_CALL(factory, CreateObjectPolicy(1))
      .WillRepeatedly(Return(null_policy));
  ObjectImpl obj(&factory);
  obj.SetAttributeInt(CKA_CLASS, 1);
  EXPECT_DEATH_IF_SUPPORTED(obj.FinalizeNewObject(), "Check failed");
}

// Test object lifecycle management.
TEST_F(TestObject, GetStage) {
  EXPECT_EQ(kCreate, object_->GetStage());
  ObjectImpl object2(&factory_);
  object2.SetAttributeInt(CKA_CLASS, CKO_PUBLIC_KEY);
  EXPECT_EQ(CKR_OK, object_->Copy(&object2));
  EXPECT_EQ(kCopy, object_->GetStage());
  EXPECT_EQ(CKR_OK, object_->FinalizeNewObject());
  EXPECT_EQ(kModify, object_->GetStage());
}

// Perform a sanity check for object size.
TEST_F(TestObject, GetSize) {
  EXPECT_EQ(0, object_->GetSize());
  object_->SetAttributeString(1, string(20, 'a'));
  EXPECT_LT(20, object_->GetSize());
}

// Test the convenience methods for common attributes.
TEST_F(TestObject, BuiltInAttributes) {
  object_->SetAttributeInt(CKA_CLASS, CKO_PUBLIC_KEY);
  object_->SetAttributeBool(CKA_TOKEN, true);
  object_->SetAttributeBool(CKA_MODIFIABLE, true);
  object_->SetAttributeBool(CKA_PRIVATE, false);
  EXPECT_EQ(CKO_PUBLIC_KEY, object_->GetObjectClass());
  EXPECT_TRUE(object_->IsTokenObject());
  EXPECT_TRUE(object_->IsModifiable());
  EXPECT_FALSE(object_->IsPrivate());
}

// Test basic consistency for attribute manipulation.
TEST_F(TestObject, AttributeConsistency) {
  // [G|S]etAttributeInt
  EXPECT_FALSE(object_->IsAttributePresent(1));
  EXPECT_EQ(0, object_->GetAttributeInt(1, 0));
  object_->SetAttributeInt(1, 2);
  EXPECT_TRUE(object_->IsAttributePresent(1));
  EXPECT_EQ(2, object_->GetAttributeInt(1, 0));
  // [G|S]etAttributeBool
  EXPECT_FALSE(object_->IsAttributePresent(2));
  EXPECT_FALSE(object_->GetAttributeBool(2, false));
  object_->SetAttributeBool(2, true);
  EXPECT_TRUE(object_->IsAttributePresent(2));
  EXPECT_TRUE(object_->GetAttributeBool(2, false));
  // [G|S]etAttributeString
  EXPECT_FALSE(object_->IsAttributePresent(3));
  EXPECT_EQ("", object_->GetAttributeString(3));
  object_->SetAttributeString(3, "test");
  EXPECT_TRUE(object_->IsAttributePresent(3));
  EXPECT_EQ("test", object_->GetAttributeString(3));
  // RemoveAttribute
  object_->RemoveAttribute(3);
  EXPECT_FALSE(object_->IsAttributePresent(3));
  // [G|S]etAttributes
  CK_ULONG val = 0x1234;
  CK_ATTRIBUTE templ[] = {{1, &val, sizeof(CK_ULONG)}};
  EXPECT_EQ(CKR_OK, object_->SetAttributes(templ, 1));
  EXPECT_EQ(0x1234, object_->GetAttributeInt(1, 0));
  CK_ULONG val2 = 0;
  CK_ATTRIBUTE templ2[] = {{1, &val2, 17}};
  EXPECT_EQ(CKR_OK, object_->GetAttributes(templ2, 1));
  EXPECT_EQ(sizeof(CK_ULONG), templ2[0].ulValueLen);
  EXPECT_EQ(0x1234, val2);
}

// Test object policy assignment and validation when finalizing.
TEST_F(TestObject, FinalizeNewObject) {
  // Finalize before setting object class.
  EXPECT_EQ(CKR_TEMPLATE_INCOMPLETE, object_->FinalizeNewObject());
  // Finalize after setting read-only attribute.
  EXPECT_CALL(*next_policy_, IsModifyAllowed(1, "test"))
      .WillRepeatedly(Return(false));
  CK_OBJECT_CLASS classval = CKO_PUBLIC_KEY;
  CK_ATTRIBUTE attr[] = {
    {CKA_CLASS, &classval, sizeof(classval)},
    {1, (void*)"test", 4},
    {2, (void*)"test2", 5}};
  object_->SetAttributes(attr, 3);
  EXPECT_EQ(CKR_ATTRIBUTE_READ_ONLY, object_->FinalizeNewObject());
  // Finalize before object is complete.
  EXPECT_CALL(*next_policy_, IsModifyAllowed(1, "test"))
      .WillRepeatedly(Return(false));
  EXPECT_CALL(*next_policy_, IsObjectComplete())
      .WillOnce(Return(false))
      .WillRepeatedly(Return(true));
  CK_ATTRIBUTE attr2[] = {
    {1, (void*)"test3", 5}};
  object_->SetAttributes(attr2, 1);
  EXPECT_EQ(CKR_TEMPLATE_INCOMPLETE, object_->FinalizeNewObject());
  EXPECT_EQ(CKR_OK, object_->FinalizeNewObject());
}

// Test GetAttributes in more detail.
TEST_F(TestObject, GetAttributes) {
  EXPECT_CALL(*next_policy_, IsReadAllowed(CKA_CLASS))
      .WillOnce(Return(false))
      .WillRepeatedly(Return(true));
  // Attempt to read an attribute before it has been set.
  CK_ATTRIBUTE templ[] = {{CKA_CLASS, NULL, 0}};
  EXPECT_EQ(CKR_ATTRIBUTE_TYPE_INVALID, object_->GetAttributes(templ, 1));
  EXPECT_EQ(-1, templ[0].ulValueLen);
  // Attempt to read a read-only attribute (IsReadAllowed returns false once).
  object_->SetAttributeInt(CKA_CLASS, CKO_PUBLIC_KEY);
  object_->FinalizeNewObject();
  EXPECT_EQ(CKR_ATTRIBUTE_SENSITIVE, object_->GetAttributes(templ, 1));
  EXPECT_EQ(-1, templ[0].ulValueLen);
  // Read an attribute's length (pValue == NULL) successfully.
  EXPECT_EQ(CKR_OK, object_->GetAttributes(templ, 1));
  EXPECT_EQ(sizeof(CK_ULONG), templ[0].ulValueLen);
  // Read an attribute with not enough buffer.
  CK_ULONG val = 0;
  templ[0].ulValueLen = 1;
  templ[0].pValue = &val;
  EXPECT_EQ(CKR_BUFFER_TOO_SMALL, object_->GetAttributes(templ, 1));
  EXPECT_EQ(-1, templ[0].ulValueLen);
  // Read an attribute successfully.
  templ[0].ulValueLen = sizeof(CK_ULONG);
  EXPECT_EQ(CKR_OK, object_->GetAttributes(templ, 1));
  EXPECT_EQ(CKO_PUBLIC_KEY, val);
}

// Test SetAttributes in more detail.
TEST_F(TestObject, SetAttributes) {
  CK_ULONG val = CKO_PUBLIC_KEY;
  CK_ATTRIBUTE templ[] = {{CKA_CLASS, &val, sizeof(CK_ULONG)}};
  // Modify attributes before finalizing (object creation stage).
  EXPECT_EQ(CKR_OK, object_->SetAttributes(templ, 1));
  EXPECT_EQ(CKR_OK, object_->FinalizeNewObject());
  // Attempt to modify read-only attributes.
  EXPECT_CALL(*policy_, IsModifyAllowed(_, _))
      .WillOnce(Return(false))
      .WillRepeatedly(Return(true));
  EXPECT_EQ(CKR_ATTRIBUTE_READ_ONLY, object_->SetAttributes(templ, 1));
  // Mofify attributes successfully.
  EXPECT_EQ(CKR_OK, object_->SetAttributes(templ, 1));
  EXPECT_EQ(CKO_PUBLIC_KEY, object_->GetObjectClass());
}

}  // namespace chaps

int main(int argc, char** argv) {
  ::testing::InitGoogleMock(&argc, argv);
  return RUN_ALL_TESTS();
}
