// Copyright 2019 The Fuchsia 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 <gtest/gtest.h>

#include "proto/tink.pb.h"
#include "src/lib/util/encrypted_message_util.h"
#include "src/lib/util/file_util.h"
#include "src/logging.h"
#include "src/pb/encrypted_message.pb.h"
#include "src/pb/observation.pb.h"

// Does some sanity-checking on the tink keys.

namespace {
using cobalt::lib::statusor::StatusOr;
using cobalt::util::EncryptedMessageMaker;
using cobalt::util::NotNullUniquePtr;

// Directory in which the keys can be found.
const char* kKeysDir;

// Read the key from disk.
void ReadKey(const std::string& filename, std::string* key_bytes) {
  cobalt::util::Path path(kKeysDir + filename);
  StatusOr<std::string> key_bytes_result = cobalt::util::ReadNonEmptyTextFile(path);
  ASSERT_TRUE(key_bytes_result.ok());

  *key_bytes = key_bytes_result.value();
}

// Encrypt some non-empty proto using the supplied EncryptedMessageMaker.
void EncryptSomething(cobalt::util::EncryptedMessageMaker& maker,
                      cobalt::EncryptedMessage* encrypted_message) {
  cobalt::Observation observation;
  observation.set_random_id("random id");

  ASSERT_TRUE(maker.Encrypt(observation, encrypted_message));
}

TEST(KeysTests, TestShufflerCobaltEncryptionDevKey) {
  std::string key_bytes;
  ReadKey("shuffler_public.cobalt_key", &key_bytes);

  StatusOr<NotNullUniquePtr<EncryptedMessageMaker>> maker_result =
      EncryptedMessageMaker::MakeForEnvelopes(key_bytes);
  ASSERT_TRUE(maker_result.ok());

  cobalt::EncryptedMessage encrypted_message;
  EncryptSomething(*std::move(maker_result.value()).Unwrap(), &encrypted_message);

  EXPECT_EQ(encrypted_message.key_index(), 9u);
}

TEST(KeysTests, TestAnalyzerCobaltEncryptionDevKey) {
  std::string key_bytes;
  ReadKey("analyzer_public.cobalt_key", &key_bytes);

  StatusOr<NotNullUniquePtr<EncryptedMessageMaker>> maker_result =
      EncryptedMessageMaker::MakeForObservations(key_bytes);
  ASSERT_TRUE(maker_result.ok());

  cobalt::EncryptedMessage encrypted_message;
  EncryptSomething(*std::move(maker_result.value()).Unwrap(), &encrypted_message);

  EXPECT_EQ(encrypted_message.key_index(), 10u);
}
TEST(KeysTests, TestShufflerCobaltEncryptionProdKey) {
  std::string key_bytes;
  ReadKey("shuffler_prod_public.cobalt_key", &key_bytes);

  StatusOr<NotNullUniquePtr<EncryptedMessageMaker>> maker_result =
      EncryptedMessageMaker::MakeForEnvelopes(key_bytes);
  ASSERT_TRUE(maker_result.ok());

  cobalt::EncryptedMessage encrypted_message;
  EncryptSomething(*std::move(maker_result.value()).Unwrap(), &encrypted_message);

  EXPECT_EQ(encrypted_message.key_index(), 11u);
}

TEST(KeysTests, TestAnalyzerCobaltEncryptionProdKey) {
  std::string key_bytes;
  ReadKey("analyzer_prod_public.cobalt_key", &key_bytes);

  StatusOr<NotNullUniquePtr<EncryptedMessageMaker>> maker_result =
      EncryptedMessageMaker::MakeForObservations(key_bytes);
  ASSERT_TRUE(maker_result.ok());

  cobalt::EncryptedMessage encrypted_message;
  EncryptSomething(*std::move(maker_result.value()).Unwrap(), &encrypted_message);

  EXPECT_EQ(encrypted_message.key_index(), 12u);
}

}  // namespace

int main(int argc, char* argv[]) {
  // Compute the path where keys are stored in the output directory.
  try {
    std::string path(argv[0]);
    auto slash = path.find_last_of('/');
    CHECK(slash != std::string::npos);
    path = path.substr(0, slash) + "/keys/";
    kKeysDir = path.c_str();

    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
  } catch (...) {
    LOG(FATAL) << "Exception caught.";
    return 1;
  }
}
