/*
 * Copyright 2018 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "fcp/secagg/shared/compute_session_id.h"

#include "gmock/gmock.h"
#include "gtest/gtest.h"

namespace fcp {
namespace secagg {
namespace {

using ::testing::Eq;
using ::testing::Ne;

TEST(ComputeSessionIdTest, OutputIsCorrectLength) {
  ShareKeysRequest request;
  PairOfPublicKeys* keys = request.add_pairs_of_public_keys();
  keys->set_noise_pk("abcdefghijklmnopqrstuvwxyz7890123");
  keys->set_enc_pk("1234567abcdefghijklmnopqrstuvwxyz");

  SessionId session_id = ComputeSessionId(request);
  EXPECT_THAT(session_id.data.size(), Eq(32));
}

TEST(ComputeSessionIdTest, OutputIsDeterministic) {
  ShareKeysRequest request1;
  PairOfPublicKeys* keys1 = request1.add_pairs_of_public_keys();
  keys1->set_noise_pk("abcdefghijklmnopqrstuvwxyz7890123");
  keys1->set_enc_pk("1234567abcdefghijklmnopqrstuvwxyz");
  ShareKeysRequest request2;
  PairOfPublicKeys* keys2 = request2.add_pairs_of_public_keys();
  keys2->set_noise_pk("abcdefghijklmnopqrstuvwxyz7890123");
  keys2->set_enc_pk("1234567abcdefghijklmnopqrstuvwxyz");

  SessionId session_id_1 = ComputeSessionId(request1);
  SessionId session_id_2 = ComputeSessionId(request2);
  EXPECT_THAT(session_id_2.data, Eq(session_id_1.data));
}

TEST(ComputeSessionIdTest, OutputChangesOnDifferentInputs) {
  ShareKeysRequest request1;
  PairOfPublicKeys* keys1 = request1.add_pairs_of_public_keys();
  keys1->set_noise_pk("abcdefghijklmnopqrstuvwxyz7890123");
  keys1->set_enc_pk("1234567abcdefghijklmnopqrstuvwxyz");
  ShareKeysRequest request2;
  PairOfPublicKeys* keys2 = request2.add_pairs_of_public_keys();
  keys2->set_noise_pk("123456789012345678901234567890123");
  keys2->set_enc_pk("ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFG");

  SessionId session_id_1 = ComputeSessionId(request1);
  SessionId session_id_2 = ComputeSessionId(request2);
  EXPECT_THAT(session_id_2.data, Ne(session_id_1.data));
}

// Hard coded keys and output generated by Java
TEST(ComputeSessionIdTest, OutputMatchesHardCodedValues) {
  ShareKeysRequest request1;
  PairOfPublicKeys* keys1 = request1.add_pairs_of_public_keys();
  keys1->set_noise_pk(
      "\002Y\256\332c\202\214\367\234F\f\370M;\301P}\b\220)\267\206C*"
      "\253f\363\375Z\262\300\214(");
  keys1->set_enc_pk(
      "\002m\003C\234\217\"\037\025{\354~\345G\233\277~"
      "\222\220\036Tkl\334C\241Ln\256\023\315k]");
  PairOfPublicKeys* keys2 = request1.add_pairs_of_public_keys();
  keys2->set_noise_pk(
      "\002\023\313\267\331\211\031\332fn8\035Qx\241\217\002K\345\"\260\377:"
      "\231~\222\246,\232?\030m\032");
  keys2->set_enc_pk(
      "\003\204\243\326["
      "I\273\326\301\336\254X\300\332\201\334\371\023\351\021\022\323\371\234`"
      "\301\352p\251\vR\217I");

  SessionId expected;
  uint8_t precomputed[32] = {120, 175, 110, 210, 30,  111, 197, 231,
                             253, 35,  163, 25,  159, 204, 80,  79,
                             173, 180, 27,  166, 83,  53,  85,  161,
                             228, 232, 97,  20,  242, 62,  142, 114};
  expected.data = std::string(reinterpret_cast<const char*>(precomputed), 32);
  SessionId session_id = ComputeSessionId(request1);
  EXPECT_THAT(session_id.data, Eq(expected.data));
}

}  // namespace
}  // namespace secagg
}  // namespace fcp
