// Copyright (c) 2013 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.
//
// Unit tests for Service

#include "service.h"

#include <base/at_exit.h>
#include <base/threading/platform_thread.h>
#include <base/file_util.h>
#include <base/time/time.h>
#include <chaps/token_manager_client_mock.h>
#include <chromeos/cryptohome.h>
#include <chromeos/secure_blob.h>
#include <gtest/gtest.h>
#include <policy/libpolicy.h>
#include <policy/mock_device_policy.h>
#include <string>

#include "crypto.h"
#include "make_tests.h"
#include "mock_attestation.h"
#include "mock_boot_lockbox.h"
#include "mock_crypto.h"
#include "mock_dbus_transition.h"
#include "mock_homedirs.h"
#include "mock_install_attributes.h"
#include "mock_mount.h"
#include "mock_mount_factory.h"
#include "mock_platform.h"
#include "mock_tpm.h"
#include "username_passkey.h"

using base::PlatformThread;
using chromeos::SecureBlob;

namespace cryptohome {
using ::testing::_;
using ::testing::DoAll;
using ::testing::EndsWith;
using ::testing::Invoke;
using ::testing::NiceMock;
using ::testing::Return;
using ::testing::SaveArg;
using ::testing::SaveArgPointee;
using ::testing::StartsWith;
using ::testing::StrEq;
using ::testing::SetArgumentPointee;

const char kImageDir[] = "test_image_dir";
const char kSaltFile[] = "test_image_dir/salt";
class ServiceInterfaceTest : public ::testing::Test {
 public:
  ServiceInterfaceTest() { }
  virtual ~ServiceInterfaceTest() { }

  void SetUp() {
    test_helper_.SetUpSystemSalt();
  }
  void TearDown() {
    test_helper_.TearDownSystemSalt();
  }

 protected:
  MakeTests test_helper_;

 private:
  DISALLOW_COPY_AND_ASSIGN(ServiceInterfaceTest);
};

class ServiceSubclass : public Service {
 public:
  ServiceSubclass()
    : Service(),
      completed_tasks_() { }
  virtual ~ServiceSubclass() { }

  virtual void NotifyEvent(CryptohomeEventBase* result) {
    if (strcmp(result->GetEventName(), kMountTaskResultEventType))
      return;
    MountTaskResult* r = static_cast<MountTaskResult*>(result);
    completed_tasks_.push_back(*r);
  }

  virtual void Dispatch() {
    DispatchEvents();
  }

  std::vector<MountTaskResult> completed_tasks_;
};

TEST_F(ServiceInterfaceTest, CheckKeySuccessTest) {
  MockHomeDirs homedirs;
  scoped_refptr<MockMount> mount = new MockMount();
  EXPECT_CALL(homedirs, FreeDiskSpace())
      .WillOnce(Return(true));
  EXPECT_CALL(*mount, AreSameUser(_))
      .WillOnce(Return(false));
  EXPECT_CALL(homedirs, AreCredentialsValid(_))
      .WillOnce(Return(true));

  Service service;
  service.set_homedirs(&homedirs);
  service.set_mount_for_user("chromeos-user", mount.get());
  NiceMock<MockInstallAttributes> attrs;
  service.set_install_attrs(&attrs);
  NiceMock<MockAttestation> attest;
  service.set_attestation(&attest);
  NiceMock<chaps::TokenManagerClientMock> chaps;
  NiceMock<MockPlatform> platform;
  service.set_platform(&platform);
  service.set_chaps_client(&chaps);
  service.set_initialize_tpm(false);
  EXPECT_CALL(homedirs, Init(&platform, service.crypto()))
    .WillOnce(Return(true));

  service.Initialize();
  gboolean out = FALSE;
  GError *error = NULL;

  char user[] = "chromeos-user";
  char key[] = "274146c6e8886a843ddfea373e2dc71b";
  EXPECT_TRUE(service.CheckKey(user, key, &out, &error));
  EXPECT_TRUE(out);
}

class CheckKeyExInterfaceTest : public ::testing::Test {
 public:
  CheckKeyExInterfaceTest() { }
  virtual ~CheckKeyExInterfaceTest() { }

  void SetUp() {
    mount_ = new MockMount();
    EXPECT_CALL(homedirs_, FreeDiskSpace())
        .WillOnce(Return(true));

    service_.set_reply_factory(&reply_factory_);
    service_.set_homedirs(&homedirs_);
    service_.set_mount_for_user("chromeos-user", mount_.get());
    service_.set_install_attrs(&attrs_);
    service_.set_attestation(&attest_);
    service_.set_platform(&platform_);
    service_.set_chaps_client(&chaps_);
    service_.set_initialize_tpm(false);
    EXPECT_CALL(homedirs_, Init(&platform_, service_.crypto()))
        .WillOnce(Return(true));
    service_.Initialize();
  }
  void TearDown() {
  }

 protected:
  MockHomeDirs homedirs_;
  MockDBusReplyFactory reply_factory_;
  NiceMock<MockInstallAttributes> attrs_;
  NiceMock<MockAttestation> attest_;
  NiceMock<chaps::TokenManagerClientMock> chaps_;
  NiceMock<MockPlatform> platform_;
  scoped_refptr<MockMount> mount_;
  Service service_;

 private:
  DISALLOW_COPY_AND_ASSIGN(CheckKeyExInterfaceTest);
};
TEST_F(CheckKeyExInterfaceTest, CheckKeyExMountTest) {
  static const char kUser[] = "chromeos-user";
  static const char kKey[] = "274146c6e8886a843ddfea373e2dc71b";
  scoped_ptr<AccountIdentifier> id(new AccountIdentifier);
  scoped_ptr<AuthorizationRequest> auth(new AuthorizationRequest);
  scoped_ptr<CheckKeyRequest> req(new CheckKeyRequest);
  id->set_email(kUser);
  auth->mutable_key()->set_secret(kKey);

  // event_source_ will delete reply on cleanup.
  std::string* base_reply_ptr = NULL;
  MockDBusReply* reply = new MockDBusReply();
  EXPECT_CALL(reply_factory_, NewReply(NULL, _))
    .WillOnce(DoAll(SaveArg<1>(&base_reply_ptr), Return(reply)));

  EXPECT_CALL(*mount_, AreSameUser(_))
      .WillOnce(Return(true));
  EXPECT_CALL(*mount_, AreValid(_))
       .WillOnce(Return(true));
  // Run will never be called because we aren't running the event loop.
  service_.DoCheckKeyEx(id.get(), auth.get(), req.get(), NULL);

  // Expect an empty reply as success.
  BaseReply expected_reply;
  std::string expected_reply_str;
  expected_reply.SerializeToString(&expected_reply_str);
  ASSERT_TRUE(base_reply_ptr);
  EXPECT_EQ(expected_reply_str, *base_reply_ptr);
  delete base_reply_ptr;
  base_reply_ptr = NULL;

  // Rinse and repeat but fail.
  EXPECT_CALL(*mount_, AreSameUser(_))
      .WillOnce(Return(true));
  EXPECT_CALL(*mount_, AreValid(_))
      .WillOnce(Return(false));
  EXPECT_CALL(homedirs_, Exists(_))
      .WillRepeatedly(Return(true));
  EXPECT_CALL(homedirs_, AreCredentialsValid(_))
      .WillOnce(Return(false));

  // event_source_ will delete reply on cleanup.
  reply = new MockDBusReply();
  EXPECT_CALL(reply_factory_, NewReply(NULL, _))
    .WillOnce(DoAll(SaveArg<1>(&base_reply_ptr), Return(reply)));

  service_.DoCheckKeyEx(id.get(), auth.get(), req.get(), NULL);

  // Expect an empty reply as success.
  expected_reply.Clear();
  expected_reply.set_error(CRYPTOHOME_ERROR_AUTHORIZATION_KEY_FAILED);
  expected_reply.SerializeToString(&expected_reply_str);
  ASSERT_TRUE(base_reply_ptr);
  EXPECT_EQ(expected_reply_str, *base_reply_ptr);
  delete base_reply_ptr;
  base_reply_ptr = NULL;
}

TEST_F(CheckKeyExInterfaceTest, CheckKeyExHomedirsTest) {
  static const char kUser[] = "chromeos-user";
  static const char kKey[] = "274146c6e8886a843ddfea373e2dc71b";
  scoped_ptr<AccountIdentifier> id(new AccountIdentifier);
  scoped_ptr<AuthorizationRequest> auth(new AuthorizationRequest);
  scoped_ptr<CheckKeyRequest> req(new CheckKeyRequest);
  // Expect an error about missing email.
  // |error| will be cleaned up by event_source_
  MockDBusReply* reply = new MockDBusReply();
  std::string* base_reply_ptr = NULL;
  id->set_email(kUser);
  auth->mutable_key()->set_secret(kKey);

  EXPECT_CALL(*mount_, AreSameUser(_))
      .WillRepeatedly(Return(false));
  EXPECT_CALL(homedirs_, Exists(_))
      .WillRepeatedly(Return(true));
  EXPECT_CALL(homedirs_, AreCredentialsValid(_))
      .WillOnce(Return(true));

  // Run will never be called because we aren't running the event loop.
  EXPECT_CALL(reply_factory_, NewReply(NULL, _))
    .WillOnce(DoAll(SaveArg<1>(&base_reply_ptr), Return(reply)));
  service_.DoCheckKeyEx(id.get(), auth.get(), req.get(), NULL);

  // Expect an empty reply as success.
  BaseReply expected_reply;
  std::string expected_reply_str;
  expected_reply.SerializeToString(&expected_reply_str);
  ASSERT_TRUE(base_reply_ptr);
  EXPECT_EQ(expected_reply_str, *base_reply_ptr);
  delete base_reply_ptr;
  base_reply_ptr = NULL;

  // Ensure failure
  EXPECT_CALL(homedirs_, AreCredentialsValid(_))
      .WillOnce(Return(false));

  // event_source_ will delete reply on cleanup.
  reply = new MockDBusReply();
  EXPECT_CALL(reply_factory_, NewReply(NULL, _))
    .WillOnce(DoAll(SaveArg<1>(&base_reply_ptr), Return(reply)));

  service_.DoCheckKeyEx(id.get(), auth.get(), req.get(), NULL);

  // Expect an empty reply as success.
  expected_reply.Clear();
  expected_reply.set_error(CRYPTOHOME_ERROR_AUTHORIZATION_KEY_FAILED);
  expected_reply.SerializeToString(&expected_reply_str);
  ASSERT_TRUE(base_reply_ptr);
  EXPECT_EQ(expected_reply_str, *base_reply_ptr);
  delete base_reply_ptr;
  base_reply_ptr = NULL;
}

TEST_F(ServiceInterfaceTest, CheckAsyncTestCredentials) {
  NiceMock<MockTpm> tpm;
  NiceMock<MockPlatform> platform;

  test_helper_.InjectSystemSalt(&platform, kSaltFile);
  test_helper_.InitTestData(kImageDir, kDefaultUsers, kDefaultUserCount);
  TestUser* user = &test_helper_.users[7];
  user->InjectKeyset(&platform);

  HomeDirs homedirs;
  homedirs.set_shadow_root(kImageDir);
  homedirs.set_platform(&platform);
  scoped_ptr<policy::PolicyProvider> policy_provider(
      new policy::PolicyProvider(new NiceMock<policy::MockDevicePolicy>));
  homedirs.set_policy_provider(policy_provider.get());

  ServiceSubclass service;
  service.set_platform(&platform);
  service.set_homedirs(&homedirs);
  service.crypto()->set_platform(&platform);
  NiceMock<MockInstallAttributes> attrs;
  service.set_install_attrs(&attrs);
  service.set_initialize_tpm(false);
  NiceMock<MockAttestation> attest;
  service.set_attestation(&attest);
  NiceMock<chaps::TokenManagerClientMock> chaps;
  service.set_chaps_client(&chaps);
  service.Initialize();

  SecureBlob passkey;
  cryptohome::Crypto::PasswordToPasskey(user->password,
                                        test_helper_.system_salt, &passkey);
  std::string passkey_string(static_cast<const char*>(passkey.const_data()),
                             passkey.size());

  gboolean out = FALSE;
  GError *error = NULL;
  gint async_id = -1;
  EXPECT_TRUE(service.AsyncCheckKey(
      const_cast<gchar*>(static_cast<const gchar*>(user->username)),
      const_cast<gchar*>(static_cast<const gchar*>(passkey_string.c_str())),
      &async_id,
      &error));
  EXPECT_NE(-1, async_id);
  for (unsigned int i = 0; i < 64; i++) {
    bool found = false;
    service.Dispatch();
    for (unsigned int j = 0; j < service.completed_tasks_.size(); j++) {
      if (service.completed_tasks_[j].sequence_id() == async_id) {
        out = service.completed_tasks_[j].return_status();
        found = true;
      }
    }
    if (found) {
      break;
    }
    PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
  }
  EXPECT_TRUE(out);
}

TEST_F(ServiceInterfaceTest, GetPublicMountPassKey) {
  NiceMock<MockPlatform> platform;

  const char kPublicMountSaltPath[] = "/var/lib/public_mount_salt";
  chromeos::Blob public_mount_salt(CRYPTOHOME_DEFAULT_SALT_LENGTH, 'P');
  EXPECT_CALL(platform, FileExists(kPublicMountSaltPath))
    .WillRepeatedly(Return(true));
  EXPECT_CALL(platform, GetFileSize(kPublicMountSaltPath, _))
    .WillRepeatedly(DoAll(SetArgumentPointee<1>(public_mount_salt.size()),
                          Return(true)));
  EXPECT_CALL(platform, ReadFile(kPublicMountSaltPath, _))
    .WillRepeatedly(DoAll(SetArgumentPointee<1>(public_mount_salt),
                          Return(true)));

  MockHomeDirs homedirs;
  ServiceSubclass service;
  service.set_platform(&platform);
  service.set_homedirs(&homedirs);
  service.crypto()->set_platform(&platform);
  NiceMock<MockInstallAttributes> attrs;
  service.set_install_attrs(&attrs);
  service.set_initialize_tpm(false);
  NiceMock<MockAttestation> attest;
  service.set_attestation(&attest);
  NiceMock<chaps::TokenManagerClientMock> chaps;
  service.set_chaps_client(&chaps);
  service.Initialize();

  const char kPublicUser1[] = "public_user_1";
  const char kPublicUser2[] = "public_user_2";

  std::string public_user1_passkey;
  service.GetPublicMountPassKey(kPublicUser1, &public_user1_passkey);

  std::string public_user2_passkey;
  service.GetPublicMountPassKey(kPublicUser2, &public_user2_passkey);
  // The passkey should be different for different user.
  EXPECT_NE(public_user1_passkey, public_user2_passkey);

  std::string public_user1_passkey2;
  service.GetPublicMountPassKey(kPublicUser1, &public_user1_passkey2);
  // The passkey should be the same for the same user.
  EXPECT_EQ(public_user1_passkey, public_user1_passkey2);
}

TEST_F(ServiceInterfaceTest, GetSanitizedUsername) {
  Service service;
  char username[] = "chromeos-user";
  gchar *sanitized = NULL;
  GError *error = NULL;
  EXPECT_TRUE(service.GetSanitizedUsername(username, &sanitized, &error));
  EXPECT_TRUE(error == NULL);
  ASSERT_TRUE(sanitized);

  const std::string expected(
      chromeos::cryptohome::home::SanitizeUserName(username));
  EXPECT_FALSE(expected.empty());

  EXPECT_EQ(expected, sanitized);
  g_free(sanitized);
}

TEST(Standalone, CheckAutoCleanupCallback) {
  // Checks that AutoCleanupCallback() is called periodically.
  MockHomeDirs homedirs;
  Service service;
  service.set_homedirs(&homedirs);
  NiceMock<MockPlatform> platform;
  service.set_platform(&platform);
  NiceMock<MockInstallAttributes> attrs;
  service.set_install_attrs(&attrs);
  service.set_initialize_tpm(false);

  // Service will schedule periodic clean-ups. Wait a bit and make
  // sure that we had at least 3 executed.
  EXPECT_CALL(homedirs, Init(&platform, service.crypto()))
      .WillOnce(Return(true));
  EXPECT_CALL(homedirs, FreeDiskSpace())
      .Times(::testing::AtLeast(3));

  scoped_refptr<MockMount> mount = new MockMount();
  EXPECT_CALL(*mount, UpdateCurrentUserActivityTimestamp(0))
      .Times(::testing::AtLeast(3));
  service.set_mount_for_user("some-user-to-clean-up", mount.get());

  service.set_auto_cleanup_period(2);  // 2ms = 500HZ
  service.set_update_user_activity_period(2);  // 2 x 5ms = 25HZ
  NiceMock<MockAttestation> attest;
  service.set_attestation(&attest);
  NiceMock<chaps::TokenManagerClientMock> chaps;
  service.set_chaps_client(&chaps);
  service.Initialize();
  PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
}

TEST(Standalone, CheckAutoCleanupCallbackFirst) {
  // Checks that AutoCleanupCallback() is called first right after init.
  MockHomeDirs homedirs;
  Service service;
  service.set_homedirs(&homedirs);
  NiceMock<MockInstallAttributes> attrs;
  service.set_install_attrs(&attrs);
  service.set_initialize_tpm(false);
  NiceMock<MockAttestation> attest;
  service.set_attestation(&attest);
  NiceMock<MockPlatform> platform;
  service.set_platform(&platform);

  // Service will schedule first cleanup right after its init.
  EXPECT_CALL(homedirs, Init(&platform, service.crypto()))
      .WillOnce(Return(true));
  EXPECT_CALL(homedirs, FreeDiskSpace())
      .Times(1);
  service.set_auto_cleanup_period(1000);  // 1s - long enough
  service.Initialize();
  // short delay to see the first invocation
  PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10));
}

struct Mounts {
  const char* src;
  const char* dst;
};

const struct Mounts kShadowMounts[] = {
  { "/home/.shadow/a", "/home/user/0" },
  { "/home/.shadow/a", "/home/root/0" },
  { "/home/.shadow/b", "/home/user/1" },
  { "/home/.shadow/a", "/home/chronos/user" },
  { "/home/.shadow/b", "/home/root/1" },
};
const int kShadowMountsCount = 5;

bool StaleShadowMounts(const std::string& from_prefix,
                 std::multimap<const std::string, const std::string>* mounts) {
  LOG(INFO) << "StaleShadowMounts(" << from_prefix << "): called";
  if (from_prefix == "/home/.shadow/") {
    if (!mounts)
      return true;
    const struct Mounts* m = &kShadowMounts[0];
    for (int i = 0; i < kShadowMountsCount; ++i, ++m) {
      mounts->insert(
          std::pair<const std::string, const std::string>(m->src, m->dst));
      LOG(INFO) << "Inserting " << m->src << ":" << m->dst;
    }
    return true;
  }
  return false;
}

class CleanUpStaleTest : public ::testing::Test {
 public:
  CleanUpStaleTest() { }
  virtual ~CleanUpStaleTest() { }

  void SetUp() {
    service_.set_homedirs(&homedirs_);
    service_.set_install_attrs(&attrs_);
    service_.set_initialize_tpm(false);
    service_.set_platform(&platform_);
    service_.set_chaps_client(&chaps_client_);
    // Empty token list by default.  The effect is that there are no attempts
    // to unload tokens unless a test explicitly sets up the token list.
    EXPECT_CALL(chaps_client_, GetTokenList(_, _))
        .WillRepeatedly(Return(true));
  }

  void TearDown() { }

 protected:
  NiceMock<MockHomeDirs> homedirs_;
  NiceMock<MockInstallAttributes> attrs_;
  MockPlatform platform_;
  chaps::TokenManagerClientMock chaps_client_;
  Service service_;

 private:
  DISALLOW_COPY_AND_ASSIGN(CleanUpStaleTest);
};

TEST_F(CleanUpStaleTest, EmptyMap_NoOpenFiles_ShadowOnly) {
  // Check that when we have a bunch of stale shadow mounts, no active mounts,
  // and no open filehandles, all stale mounts are unmounted.

  EXPECT_CALL(platform_, GetMountsBySourcePrefix(_, _))
    .Times(3)
    .WillRepeatedly(Invoke(StaleShadowMounts));
  EXPECT_CALL(platform_, GetProcessesWithOpenFiles(_, _))
    .Times(kShadowMountsCount);
  EXPECT_CALL(platform_, Unmount(_, true, _))
    .Times(kShadowMountsCount)
    .WillRepeatedly(Return(true));
  EXPECT_FALSE(service_.CleanUpStaleMounts(false));
}

TEST_F(CleanUpStaleTest, EmptyMap_OpenLegacy_ShadowOnly) {
  // Check that when we have a bunch of stale shadow mounts, no active mounts,
  // and some open filehandles to the legacy homedir, all mounts without
  // filehandles are unmounted.
  EXPECT_CALL(platform_, GetMountsBySourcePrefix(_, _))
    .Times(3)
    .WillRepeatedly(Invoke(StaleShadowMounts));
  std::vector<ProcessInformation> processes(1);
  processes[0].set_process_id(1);
  EXPECT_CALL(platform_, GetProcessesWithOpenFiles(_, _))
    .Times(kShadowMountsCount - 1);
  EXPECT_CALL(platform_, GetProcessesWithOpenFiles(
      "/home/chronos/user", _))
    .Times(1)
    .WillRepeatedly(SetArgumentPointee<1>(processes));
  EXPECT_CALL(platform_, Unmount(EndsWith("/1"), true, _))
    .Times(2)
    .WillRepeatedly(Return(true));
  EXPECT_TRUE(service_.CleanUpStaleMounts(false));
}

TEST_F(CleanUpStaleTest, FilledMap_NoOpenFiles_ShadowOnly) {
  // Checks that when we have a bunch of stale shadow mounts, some active
  // mounts, and no open filehandles, all inactive mounts are unmounted.

  // ownership handed off to the Service MountMap
  MockMountFactory f;
  MockMount *m = new MockMount();

  EXPECT_CALL(f, New())
    .WillOnce(Return(m));

  service_.set_mount_factory(&f);

  EXPECT_CALL(homedirs_, Init(&platform_, service_.crypto()))
    .WillOnce(Return(true));

  EXPECT_CALL(platform_, GetMountsBySourcePrefix(_, _))
    .Times(3)
    .WillRepeatedly(Return(false));

  ASSERT_TRUE(service_.Initialize());

  EXPECT_CALL(*m, Init(&platform_, service_.crypto()))
    .WillOnce(Return(true));
  EXPECT_CALL(*m, MountCryptohome(_, _, _))
    .WillOnce(Return(true));
  EXPECT_CALL(*m, UpdateCurrentUserActivityTimestamp(_))
    .WillOnce(Return(true));

  EXPECT_CALL(platform_, GetMountsBySourcePrefix(_, _))
    .Times(3)
    .WillRepeatedly(Return(false));

  gint error_code = 0;
  gboolean result = FALSE;
  ASSERT_TRUE(service_.Mount("foo@bar.net", "key", true, false,
                             &error_code, &result, NULL));
  ASSERT_EQ(TRUE, result);
  EXPECT_CALL(platform_, GetMountsBySourcePrefix(_, _))
    .Times(3)
    .WillRepeatedly(Invoke(StaleShadowMounts));
  EXPECT_CALL(platform_, GetProcessesWithOpenFiles(_, _))
    .Times(kShadowMountsCount);

  EXPECT_CALL(*m, OwnsMountPoint(_))
    .WillRepeatedly(Return(false));
  EXPECT_CALL(*m, OwnsMountPoint("/home/user/1"))
    .WillOnce(Return(true));
  EXPECT_CALL(*m, OwnsMountPoint("/home/root/1"))
    .WillOnce(Return(true));

  EXPECT_CALL(platform_, Unmount(EndsWith("/0"), true, _))
    .Times(2)
    .WillRepeatedly(Return(true));
  EXPECT_CALL(platform_, Unmount("/home/chronos/user", true, _))
    .WillOnce(Return(true));

  std::vector<std::string> fake_token_list;
  fake_token_list.push_back("/home/chronos/user/token");
  fake_token_list.push_back("/home/user/1/token");
  fake_token_list.push_back("/home/root/1/token");
  EXPECT_CALL(chaps_client_, GetTokenList(_, _))
      .WillRepeatedly(DoAll(SetArgumentPointee<1>(fake_token_list),
                            Return(true)));

  EXPECT_CALL(chaps_client_,
              UnloadToken(_, base::FilePath("/home/chronos/user/token")))
      .Times(1);

  // Expect that CleanUpStaleMounts() tells us it skipped no mounts.
  EXPECT_FALSE(service_.CleanUpStaleMounts(false));
}

TEST(Standalone, StoreEnrollmentState) {
  NiceMock<MockInstallAttributes> attrs;
  MockPlatform platform;
  MockCrypto crypto;
  Service service;
  service.set_crypto(&crypto);
  service.set_install_attrs(&attrs);
  service.set_platform(&platform);

  chromeos::glib::ScopedArray test_array(g_array_new(FALSE, FALSE, 1));
  std::string data = "123456";
  g_array_append_vals(test_array.get(), data.data(), data.length());

  // Helper strings for setting install attributes.
  static const char true_str[] = "true";
  const chromeos::Blob true_value(true_str, true_str + arraysize(true_str));

  static const char false_str[] = "false";
  const chromeos::Blob false_value(false_str, false_str + arraysize(false_str));

  gboolean success;
  GError* error = NULL;

  // Set us as non-enterprise enrolled.
  EXPECT_CALL(attrs, Get("enterprise.owned", _)).WillOnce(
      DoAll(SetArgumentPointee<1>(false_value), Return(true)));
  service.DetectEnterpriseOwnership();

  // Should not enterprise-enroll this device.
  EXPECT_TRUE(service.StoreEnrollmentState(test_array.get(), &success, &error));
  EXPECT_FALSE(success);

  // Set us as enterprise enrolled.
  EXPECT_CALL(attrs, Get("enterprise.owned", _)).WillOnce(
      DoAll(SetArgumentPointee<1>(true_value), Return(true)));
  service.DetectEnterpriseOwnership();

  std::string encrypted_data = "so_encrypted";

  // Test successful encryption.
  EXPECT_CALL(crypto, EncryptWithTpm(_,_)).WillOnce(DoAll(
      SetArgumentPointee<1>(encrypted_data), Return(true)));

  // Should write file as this device is enterprise enrolled.
  EXPECT_CALL(platform, WriteStringToFile(
      "/mnt/stateful_partition/unencrypted/preserve/enrollment_state.epb",
      encrypted_data)).WillOnce(Return(true));
  EXPECT_TRUE(service.StoreEnrollmentState(test_array.get(), &success, &error));
  EXPECT_TRUE(success);

  EXPECT_TRUE(service.homedirs()->enterprise_owned());
}

TEST(Standalone, LoadEnrollmentState) {
  MockPlatform platform;
  MockCrypto crypto;
  Service service;
  service.set_crypto(&crypto);
  service.set_platform(&platform);

  gboolean success;
  GError* error = NULL;
  chromeos::glib::ScopedArray output;

  // Convert to blob -- this is what we're reading from the file.
  std::string data = "123456";
  const chromeos::Blob data_blob(data.c_str(), data.c_str() + data.length());
  std::string decrypted_data = "decrypted";
  SecureBlob decrypted_blob(decrypted_data.data(), decrypted_data.size());

  // Assume the data is there, we should return the value and success.
  EXPECT_CALL(platform, ReadFile(
      "/mnt/stateful_partition/unencrypted/preserve/enrollment_state.epb",
      _)).WillOnce(DoAll(SetArgumentPointee<1>(data_blob), Return(true)));

  EXPECT_CALL(crypto, DecryptWithTpm(_, _)).WillOnce(DoAll(
      SetArgumentPointee<1>(decrypted_blob), Return(TRUE)));

  EXPECT_TRUE(service.LoadEnrollmentState(
      &(chromeos::Resetter(&output).lvalue()), &success, &error));
  EXPECT_TRUE(success);

  // Convert output array to a blob for comparison.
  SecureBlob output_blob(output->data, output->len);
  EXPECT_EQ(decrypted_blob, output_blob);

  // Assume we fail to read the data, we should not return success.
  EXPECT_CALL(platform, ReadFile(
      "/mnt/stateful_partition/unencrypted/preserve/enrollment_state.epb",
      _)).WillOnce(Return(false));

  EXPECT_TRUE(service.LoadEnrollmentState(
      &(chromeos::Resetter(&output).lvalue()), &success, &error));
  EXPECT_FALSE(success);
}

class ExTest : public ::testing::Test {
 public:
  ExTest() { }
  virtual ~ExTest() { }

  void SetUp() {
    service_.set_attestation(&attest_);
    service_.set_homedirs(&homedirs_);
    service_.set_install_attrs(&attrs_);
    service_.set_initialize_tpm(false);
    service_.set_use_tpm(false);
    service_.set_platform(&platform_);
    service_.set_chaps_client(&chaps_client_);
    service_.set_boot_lockbox(&lockbox_);
    service_.set_reply_factory(&reply_factory_);
    // Empty token list by default.  The effect is that there are no attempts
    // to unload tokens unless a test explicitly sets up the token list.
    EXPECT_CALL(chaps_client_, GetTokenList(_, _))
        .WillRepeatedly(Return(true));
    EXPECT_CALL(platform_, ReadFileToString(EndsWith("decrypt_stateful"), _))
        .WillRepeatedly(Return(false));

    g_error_ = NULL;
    // Fast path through Initialize()
    EXPECT_CALL(homedirs_, Init(&platform_, service_.crypto()))
        .WillOnce(Return(true));
    // Skip the CleanUpStaleMounts bit.
    EXPECT_CALL(platform_, GetMountsBySourcePrefix(_, _))
        .WillRepeatedly(Return(false));
    ASSERT_TRUE(service_.Initialize());
  }

  void TearDown() {
    if (g_error_) {
      g_error_free(g_error_);
      g_error_ = NULL;
    }
  }

  void SetupErrorReply() {
    g_error_ = NULL;
    // |error| will be cleaned up by event_source_
    MockDBusErrorReply *error = new MockDBusErrorReply();
    EXPECT_CALL(reply_factory_, NewErrorReply(NULL, _))
        .WillOnce(DoAll(SaveArg<1>(&g_error_), Return(error)));
  }

  void SetupReply() {
    EXPECT_CALL(reply_factory_, NewReply(NULL, _))
        .WillOnce(DoAll(SaveArg<1>(&reply_), Return(new MockDBusReply())));
  }

  BaseReply GetLastReply() {
    BaseReply reply;
    CHECK(reply_);
    CHECK(reply.ParseFromString(*reply_));
    delete reply_;
    reply_ = NULL;
    return reply;
  }

  void PrepareArguments() {
    id_.reset(new AccountIdentifier);
    auth_.reset(new AuthorizationRequest);
    add_req_.reset(new AddKeyRequest);
    check_req_.reset(new CheckKeyRequest);
    mount_req_.reset(new MountRequest);
    remove_req_.reset(new RemoveKeyRequest);
  }

  template<class ProtoBuf>
  GArray* GArrayFromProtoBuf(const ProtoBuf& pb) {
    guint len = pb.ByteSize();
    GArray* ary = g_array_sized_new(FALSE, FALSE, 1, len);
    g_array_set_size(ary, len);
    if (!pb.SerializeToArray(ary->data, len)) {
      printf("Failed to serialize protocol buffer.\n");
      return NULL;
    }
    return ary;
  }

  template<class ProtoBuf>
  chromeos::SecureBlob BlobFromProtobuf(const ProtoBuf& pb) {
    std::string serialized;
    CHECK(pb.SerializeToString(&serialized));
    return chromeos::SecureBlob(serialized);
  }

 protected:
  NiceMock<MockAttestation> attest_;
  NiceMock<MockHomeDirs> homedirs_;
  NiceMock<MockInstallAttributes> attrs_;
  NiceMock<MockBootLockbox> lockbox_;
  MockDBusReplyFactory reply_factory_;

  scoped_ptr<AccountIdentifier> id_;
  scoped_ptr<AuthorizationRequest> auth_;
  scoped_ptr<AddKeyRequest> add_req_;
  scoped_ptr<CheckKeyRequest> check_req_;
  scoped_ptr<MountRequest> mount_req_;
  scoped_ptr<RemoveKeyRequest> remove_req_;

  GError* g_error_;
  std::string* reply_;
  MockPlatform platform_;
  chaps::TokenManagerClientMock chaps_client_;
  Service service_;

 private:
  DISALLOW_COPY_AND_ASSIGN(ExTest);
};

TEST_F(ExTest, MountInvalidArgsNoEmail) {
  SetupErrorReply();
  PrepareArguments();
  // Run will never be called because we aren't running the event loop.
  // For the same reason, DoMountEx is called directly.
  // TODO(wad) Look at using the ServiceSubclass.
  service_.DoMountEx(id_.get(), auth_.get(), mount_req_.get(), NULL);
  ASSERT_NE(g_error_, reinterpret_cast<void *>(0));
  EXPECT_STREQ("No email supplied", g_error_->message);
}

TEST_F(ExTest, MountInvalidArgsNoSecret) {
  SetupErrorReply();
  PrepareArguments();
  id_->set_email("foo@gmail.com");
  service_.DoMountEx(id_.get(), auth_.get(), mount_req_.get(), NULL);
  ASSERT_NE(g_error_, reinterpret_cast<void *>(0));
  EXPECT_STREQ("No key secret supplied", g_error_->message);
}

TEST_F(ExTest, MountInvalidArgsEmptySecret) {
  SetupErrorReply();
  PrepareArguments();
  id_->set_email("foo@gmail.com");
  auth_->mutable_key()->set_secret("");
  service_.DoMountEx(id_.get(), auth_.get(), mount_req_.get(), NULL);
  ASSERT_NE(g_error_, reinterpret_cast<void *>(0));
  EXPECT_STREQ("No key secret supplied", g_error_->message);
}

TEST_F(ExTest, MountInvalidArgsCreateWithNoKey) {
  SetupErrorReply();
  PrepareArguments();
  id_->set_email("foo@gmail.com");
  auth_->mutable_key()->set_secret("blerg");
  mount_req_->mutable_create();
  service_.DoMountEx(id_.get(), auth_.get(), mount_req_.get(), NULL);
  ASSERT_NE(g_error_, reinterpret_cast<void *>(0));
  EXPECT_STREQ("CreateRequest supplied with no keys", g_error_->message);
}

TEST_F(ExTest, MountInvalidArgsCreateWithEmptyKey) {
  SetupErrorReply();
  PrepareArguments();
  id_->set_email("foo@gmail.com");
  auth_->mutable_key()->set_secret("blerg");
  mount_req_->mutable_create()->add_keys();
  // TODO(wad) Add remaining missing field tests and NULL tests
  service_.DoMountEx(id_.get(), auth_.get(), mount_req_.get(), NULL);
  ASSERT_NE(g_error_, reinterpret_cast<void *>(0));
  EXPECT_STREQ("CreateRequest Keys are not fully specified",
               g_error_->message);
}

TEST_F(ExTest, AddKeyInvalidArgsNoEmail) {
  SetupErrorReply();
  PrepareArguments();
  // Run will never be called because we aren't running the event loop.
  // For the same reason, DoMountEx is called directly.
  service_.DoAddKeyEx(id_.get(), auth_.get(), add_req_.get(), NULL);
  ASSERT_NE(g_error_, reinterpret_cast<void *>(0));
  EXPECT_STREQ("No email supplied", g_error_->message);
}

TEST_F(ExTest, AddKeyInvalidArgsNoSecret) {
  SetupErrorReply();
  PrepareArguments();
  id_->set_email("foo@gmail.com");
  service_.DoAddKeyEx(id_.get(), auth_.get(), add_req_.get(), NULL);
  ASSERT_NE(g_error_, reinterpret_cast<void *>(0));
  EXPECT_STREQ("No key secret supplied", g_error_->message);
}

TEST_F(ExTest, AddKeyInvalidArgsNoNewKeySet) {
  SetupErrorReply();
  PrepareArguments();
  id_->set_email("foo@gmail.com");
  auth_->mutable_key()->set_secret("blerg");
  add_req_->clear_key();
  service_.DoAddKeyEx(id_.get(), auth_.get(), add_req_.get(), NULL);
  ASSERT_NE(g_error_, reinterpret_cast<void *>(0));
  EXPECT_STREQ("No new key supplied", g_error_->message);
}

TEST_F(ExTest, AddKeyInvalidArgsNoKeyFilled) {
  SetupErrorReply();
  PrepareArguments();
  id_->set_email("foo@gmail.com");
  auth_->mutable_key()->set_secret("blerg");
  add_req_->mutable_key();
  service_.DoAddKeyEx(id_.get(), auth_.get(), add_req_.get(), NULL);
  ASSERT_NE(g_error_, reinterpret_cast<void *>(0));
  EXPECT_STREQ("No new key supplied", g_error_->message);
}

TEST_F(ExTest, AddKeyInvalidArgsNoNewKeyLabel) {
  SetupErrorReply();
  PrepareArguments();
  id_->set_email("foo@gmail.com");
  auth_->mutable_key()->set_secret("blerg");
  add_req_->mutable_key();
  // No label
  add_req_->mutable_key()->set_secret("some secret");
  service_.DoAddKeyEx(id_.get(), auth_.get(), add_req_.get(), NULL);
  ASSERT_NE(g_error_, reinterpret_cast<void *>(0));
  EXPECT_STREQ("No new key label supplied", g_error_->message);
}

TEST_F(ExTest, CheckKeyInvalidArgsNoEmail) {
  SetupErrorReply();
  PrepareArguments();
  // Run will never be called because we aren't running the event loop.
  // For the same reason, DoMountEx is called directly.
  service_.DoCheckKeyEx(id_.get(), auth_.get(), check_req_.get(), NULL);
  ASSERT_NE(g_error_, reinterpret_cast<void *>(0));
  EXPECT_STREQ("No email supplied", g_error_->message);
}

TEST_F(ExTest, CheckKeyInvalidArgsNoSecret) {
  SetupErrorReply();
  PrepareArguments();
  id_->set_email("foo@gmail.com");
  service_.DoCheckKeyEx(id_.get(), auth_.get(), check_req_.get(), NULL);
  ASSERT_NE(g_error_, reinterpret_cast<void *>(0));
  EXPECT_STREQ("No key secret supplied", g_error_->message);
}

TEST_F(ExTest, CheckKeyInvalidArgsEmptySecret) {
  SetupErrorReply();
  PrepareArguments();
  id_->set_email("foo@gmail.com");
  auth_->mutable_key()->set_secret("");
  service_.DoCheckKeyEx(id_.get(), auth_.get(), check_req_.get(), NULL);
  ASSERT_NE(g_error_, reinterpret_cast<void *>(0));
  EXPECT_STREQ("No key secret supplied", g_error_->message);
}

TEST_F(ExTest, RemoveKeyInvalidArgsNoEmail) {
  SetupErrorReply();
  PrepareArguments();
  // Run will never be called because we aren't running the event loop.
  // For the same reason, DoMountEx is called directly.
  service_.DoRemoveKeyEx(id_.get(), auth_.get(), remove_req_.get(), NULL);
  ASSERT_NE(g_error_, reinterpret_cast<void *>(0));
  EXPECT_STREQ("No email supplied", g_error_->message);
}

TEST_F(ExTest, RemoveKeyInvalidArgsNoSecret) {
  SetupErrorReply();
  PrepareArguments();
  id_->set_email("foo@gmail.com");
  service_.DoRemoveKeyEx(id_.get(), auth_.get(), remove_req_.get(), NULL);
  ASSERT_NE(g_error_, reinterpret_cast<void *>(0));
  EXPECT_STREQ("No key secret supplied", g_error_->message);
}

TEST_F(ExTest, RemoveKeyInvalidArgsEmptySecret) {
  SetupErrorReply();
  PrepareArguments();
  id_->set_email("foo@gmail.com");
  auth_->mutable_key()->set_secret("");
  service_.DoRemoveKeyEx(id_.get(), auth_.get(), remove_req_.get(), NULL);
  ASSERT_NE(g_error_, reinterpret_cast<void *>(0));
  EXPECT_STREQ("No key secret supplied", g_error_->message);
}

TEST_F(ExTest, RemoveKeyInvalidArgsEmptyRemoveLabel) {
  SetupErrorReply();
  PrepareArguments();
  id_->set_email("foo@gmail.com");
  auth_->mutable_key()->set_secret("some secret");
  remove_req_->mutable_key()->mutable_data();
  service_.DoRemoveKeyEx(id_.get(), auth_.get(), remove_req_.get(), NULL);
  ASSERT_NE(g_error_, reinterpret_cast<void *>(0));
  EXPECT_STREQ("No label provided for target key", g_error_->message);
}

TEST_F(ExTest, BootLockboxSignSuccess) {
  SetupReply();
  SecureBlob test_signature("test");
  EXPECT_CALL(lockbox_, Sign(_, _))
      .WillRepeatedly(DoAll(SetArgumentPointee<1>(test_signature),
                            Return(true)));

  SignBootLockboxRequest request;
  request.set_data("test_data");
  service_.DoSignBootLockbox(BlobFromProtobuf(request), NULL);
  BaseReply reply = GetLastReply();
  EXPECT_FALSE(reply.has_error());
  EXPECT_TRUE(reply.HasExtension(SignBootLockboxReply::reply));
  EXPECT_EQ("test",
            reply.GetExtension(SignBootLockboxReply::reply).signature());
}

TEST_F(ExTest, BootLockboxSignBadArgs) {
  // Try with bad proto data.
  SetupErrorReply();
  service_.DoSignBootLockbox(SecureBlob("not_a_protobuf"), NULL);
  ASSERT_NE(g_error_, reinterpret_cast<void *>(0));
  EXPECT_STRNE("", g_error_->message);
  // Try with |data| not set.
  SetupErrorReply();
  SignBootLockboxRequest request;
  service_.DoSignBootLockbox(BlobFromProtobuf(request), NULL);
  ASSERT_NE(g_error_, reinterpret_cast<void *>(0));
  EXPECT_STRNE("", g_error_->message);
}

TEST_F(ExTest, BootLockboxSignError) {
  SetupReply();
  EXPECT_CALL(lockbox_, Sign(_, _))
      .WillRepeatedly(Return(false));

  SignBootLockboxRequest request;
  request.set_data("test_data");
  service_.DoSignBootLockbox(BlobFromProtobuf(request), NULL);
  BaseReply reply = GetLastReply();
  EXPECT_TRUE(reply.has_error());
  EXPECT_EQ(CRYPTOHOME_ERROR_LOCKBOX_CANNOT_SIGN, reply.error());
  EXPECT_FALSE(reply.HasExtension(SignBootLockboxReply::reply));
}

TEST_F(ExTest, BootLockboxVerifySuccess) {
  SetupReply();
  EXPECT_CALL(lockbox_, Verify(_, _))
      .WillRepeatedly(Return(true));

  VerifyBootLockboxRequest request;
  request.set_data("test_data");
  request.set_signature("test_signature");
  service_.DoVerifyBootLockbox(BlobFromProtobuf(request), NULL);
  BaseReply reply = GetLastReply();
  EXPECT_FALSE(reply.has_error());
  EXPECT_FALSE(reply.HasExtension(SignBootLockboxReply::reply));
}

TEST_F(ExTest, BootLockboxVerifyBadArgs) {
  // Try with bad proto data.
  SetupErrorReply();
  service_.DoVerifyBootLockbox(SecureBlob("not_a_protobuf"), NULL);
  ASSERT_NE(g_error_, reinterpret_cast<void *>(0));
  EXPECT_STRNE("", g_error_->message);
  // Try with |signature| not set.
  SetupErrorReply();
  VerifyBootLockboxRequest request;
  request.set_data("test_data");
  service_.DoVerifyBootLockbox(BlobFromProtobuf(request), NULL);
  ASSERT_NE(g_error_, reinterpret_cast<void *>(0));
  EXPECT_STRNE("", g_error_->message);
  // Try with |data| not set.
  SetupErrorReply();
  VerifyBootLockboxRequest request2;
  request2.set_signature("test_data");
  service_.DoVerifyBootLockbox(BlobFromProtobuf(request2), NULL);
  ASSERT_NE(g_error_, reinterpret_cast<void *>(0));
  EXPECT_STRNE("", g_error_->message);
}

TEST_F(ExTest, BootLockboxVerifyError) {
  SetupReply();
  EXPECT_CALL(lockbox_, Verify(_, _))
      .WillRepeatedly(Return(false));

  VerifyBootLockboxRequest request;
  request.set_data("test_data");
  request.set_signature("test_signature");
  service_.DoVerifyBootLockbox(BlobFromProtobuf(request), NULL);
  BaseReply reply = GetLastReply();
  EXPECT_TRUE(reply.has_error());
  EXPECT_EQ(CRYPTOHOME_ERROR_LOCKBOX_SIGNATURE_INVALID, reply.error());
}

TEST_F(ExTest, BootLockboxFinalizeSuccess) {
  SetupReply();
  EXPECT_CALL(lockbox_, FinalizeBoot())
      .WillRepeatedly(Return(true));

  FinalizeBootLockboxRequest request;
  service_.DoFinalizeBootLockbox(BlobFromProtobuf(request), NULL);
  BaseReply reply = GetLastReply();
  EXPECT_FALSE(reply.has_error());
  EXPECT_FALSE(reply.HasExtension(SignBootLockboxReply::reply));
}

TEST_F(ExTest, BootLockboxFinalizeBadArgs) {
  // Try with bad proto data.
  SetupErrorReply();
  service_.DoFinalizeBootLockbox(SecureBlob("not_a_protobuf"), NULL);
  ASSERT_NE(g_error_, reinterpret_cast<void *>(0));
  EXPECT_STRNE("", g_error_->message);
}

TEST_F(ExTest, BootLockboxFinalizeError) {
  SetupReply();
  EXPECT_CALL(lockbox_, FinalizeBoot())
      .WillRepeatedly(Return(false));

  FinalizeBootLockboxRequest request;
  service_.DoFinalizeBootLockbox(BlobFromProtobuf(request), NULL);
  BaseReply reply = GetLastReply();
  EXPECT_TRUE(reply.has_error());
  EXPECT_EQ(CRYPTOHOME_ERROR_TPM_COMM_ERROR, reply.error());
}

}  // namespace cryptohome
