// Copyright 2020 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 "accounting/accountant.h"

#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/status/status.h"
#include "base/statusor.h"
#include "accounting/common/common.h"
#include "accounting/privacy_loss_distribution.h"
#include "base/testing/status_matchers.h"

namespace differential_privacy {
namespace accounting {

namespace {

constexpr double kMaxError = 1e-1;
using ::testing::Values;
using ::differential_privacy::base::testing::StatusIs;

struct TestCaseParam {
  EpsilonDelta epsilon_delta;
  int num_queries;
  double sensitivity = 1;
  NoiseFunction noise_function;
  double expected_parameter;
};

class AccountantTest : public testing::TestWithParam<TestCaseParam> {};

std::unique_ptr<AdditiveNoisePrivacyLoss> LaplaceNoiseFunction(
    double parameter, double sensitivity) {
  return LaplacePrivacyLoss::Create(parameter, sensitivity).value();
}

INSTANTIATE_TEST_SUITE_P(
    AccountantSuite, AccountantTest,
    Values(
        TestCaseParam{
            .epsilon_delta = EpsilonDelta{.epsilon = 3, .delta = 0},
            .num_queries = 5,
            .sensitivity = 2.1,
            .noise_function = LaplaceNoiseFunction,
            .expected_parameter = 3.5,
        },
        TestCaseParam{
            .epsilon_delta = EpsilonDelta{.epsilon = 1, .delta = 0.0001},
            .num_queries = 20,
            .sensitivity = 1,
            .noise_function = LaplaceNoiseFunction,
            .expected_parameter = 13.6},
        TestCaseParam{
            .epsilon_delta = EpsilonDelta{.epsilon = 1, .delta = 0.0001},
            .num_queries = 20,
            .sensitivity = 0.5,
            .noise_function = LaplaceNoiseFunction,
            .expected_parameter = 6.8}));

TEST_P(AccountantTest, Basic) {
  TestCaseParam param = GetParam();

  auto result = GetSmallestParameter(param.epsilon_delta, param.num_queries,
                                     param.sensitivity, param.noise_function,
                                     absl::optional<double>());
  EXPECT_OK(result.status());
  EXPECT_NEAR(result.value(), param.expected_parameter, kMaxError);
}

struct AdvancedCompositionParam {
  double epsilon;
  double delta;
  double total_delta;
  int num_queries;
  double expected_total_epsilon;
};

class AdvancedCompositionTest
    : public testing::TestWithParam<AdvancedCompositionParam> {};

INSTANTIATE_TEST_SUITE_P(
    AdvancedCompositionSuite, AdvancedCompositionTest,
    Values(
        // Basic Composition
        AdvancedCompositionParam{.epsilon = 1,
                                 .delta = 0,
                                 .total_delta = 0,
                                 .num_queries = 30,
                                 .expected_total_epsilon = 30},
        // Advantage over basic #1
        AdvancedCompositionParam{.epsilon = 1,
                                 .delta = 0.001,
                                 .total_delta = 0.06,
                                 .num_queries = 30,
                                 .expected_total_epsilon = 22},
        // Advantage over basic #2
        AdvancedCompositionParam{.epsilon = 1,
                                 .delta = 0.001,
                                 .total_delta = 0.1,
                                 .num_queries = 30,
                                 .expected_total_epsilon = 20}));

TEST_P(AdvancedCompositionTest, Basic) {
  AdvancedCompositionParam param = GetParam();

  auto result = AdvancedComposition(
      EpsilonDelta{.epsilon = param.epsilon, .delta = param.delta},
      param.num_queries, param.total_delta);
  EXPECT_OK(result.status());
  EXPECT_NEAR(result.value(), param.expected_total_epsilon, kMaxError);
}

TEST(AdvancedCompositionNotFoundTest, TotalDeltaTooSmall) {
  int num_queries = 30;
  double total_delta = 0.26;
  auto result = AdvancedComposition(EpsilonDelta{.epsilon = 0.1, .delta = 0.2},
                                    num_queries, total_delta);
  EXPECT_THAT(result, StatusIs(absl::StatusCode::kNotFound));
}
}  // namespace
}  // namespace accounting
}  // namespace differential_privacy
