// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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
//
//   http://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 <cstdint>
#include <memory>
#include <ostream>
#include <string>
#include <utility>
#include <vector>

#include <gflags/gflags.h>
#include <glog/logging.h>
#include <gtest/gtest.h>

#include "kudu/client/shared_ptr.h" // IWYU pragma: keep
#include "kudu/integration-tests/linked_list-test-util.h"
#include "kudu/integration-tests/log_verifier.h"
#include "kudu/mini-cluster/external_mini_cluster.h"
#include "kudu/util/monotime.h"
#include "kudu/util/test_macros.h"
#include "kudu/util/test_util.h"

DEFINE_string(test_version_a_bin, "", "Directory to find the binaries for \"Version A\"");
DEFINE_string(test_version_b_bin, "", "Directory to find the binaries for \"Version B\"");

// For linked list testing
DEFINE_int32(seconds_to_run, 5, "Number of seconds for which to run the test");
DEFINE_int32(num_chains, 50, "Number of parallel chains to generate");
DEFINE_int32(num_tablets, 3, "Number of tablets over which to split the data");
DEFINE_bool(enable_mutation, true, "Enable periodic mutation of inserted rows");
DEFINE_int32(num_snapshots, 3, "Number of snapshots to verify across replicas and reboots.");
DEFINE_int32(num_replicas, 3, "Number of replicas per tablet");

using std::string;
using std::unique_ptr;
using std::vector;

const char* kTableName = "test_table";
const int kNumTabletServers = 3;

namespace kudu {

using cluster::ExternalMiniCluster;
using cluster::ExternalMiniClusterOptions;

namespace client {
class KuduClient;
}

namespace itest {

// A test suite designed to test the ability to migrate between two (or more)
// versions of Kudu. Not invoked by "ctest".
class VersionMigrationTest : public KuduTest {
 protected:
  void SetUp() override {
    if (FLAGS_test_version_a_bin.empty() || FLAGS_test_version_b_bin.empty()) {
      FAIL() << "Must specify --test_version_a_bin and --test_version_b_bin flags";
    }
    KuduTest::SetUp();
  }

  void StartCluster(const vector<string>& extra_ts_flags = {},
                    const vector<string>& extra_master_flags = {},
                    int num_tablet_servers = 3,
                    const string& bin_path = "");

  unique_ptr<ExternalMiniCluster> cluster_;
  client::sp::shared_ptr<client::KuduClient> client_;
  unique_ptr<LinkedListTester> tester_;
  unique_ptr<LogVerifier> verifier_;
};

void VersionMigrationTest::StartCluster(const vector<string>& extra_ts_flags,
                                        const vector<string>& extra_master_flags,
                                        int num_tablet_servers,
                                        const string& bin_path) {
  ExternalMiniClusterOptions opts;
  if (!bin_path.empty()) opts.daemon_bin_path = bin_path;
  opts.num_tablet_servers = num_tablet_servers;
  opts.extra_master_flags = extra_master_flags;
  opts.extra_master_flags.emplace_back("--undefok=unlock_experimental_flags,unlock_unsafe_flags");
  opts.extra_tserver_flags = extra_ts_flags;
  opts.extra_tserver_flags.emplace_back("--undefok=unlock_experimental_flags,unlock_unsafe_flags");
  cluster_.reset(new ExternalMiniCluster(std::move(opts)));
  verifier_.reset(new LogVerifier(cluster_.get()));
  ASSERT_OK(cluster_->Start());
  ASSERT_OK(cluster_->CreateClient(nullptr, &client_));
  tester_.reset(new LinkedListTester(client_, kTableName,
                                     FLAGS_num_chains,
                                     FLAGS_num_tablets,
                                     FLAGS_num_replicas,
                                     FLAGS_enable_mutation));
}

// Test that a tablet created with "Version A" does not lose data and can be
// read after upgrading to "Version B" of the software.
TEST_F(VersionMigrationTest, TestLinkedListSimpleMigration) {

  LOG(INFO) << "Starting cluster using binaries at " << FLAGS_test_version_a_bin;
  NO_FATALS(StartCluster({}, {}, kNumTabletServers, FLAGS_test_version_a_bin));

  // Create the linked list and verify it with Version A.
  int64_t written = 0;
  ASSERT_OK(tester_->CreateLinkedListTable());
  ASSERT_OK(tester_->LoadLinkedList(MonoDelta::FromSeconds(FLAGS_seconds_to_run),
                                    FLAGS_num_snapshots,
                                    &written));
  ASSERT_OK(tester_->WaitAndVerify(FLAGS_seconds_to_run, written));
  ASSERT_OK(verifier_->VerifyCommittedOpIdsMatch());
  NO_FATALS(cluster_->AssertNoCrashes());

  // Now switch from Version A to Version B.
  cluster_->Shutdown();
  LOG(INFO) << "Restarting cluster using binaries at " << FLAGS_test_version_b_bin;
  cluster_->SetDaemonBinPath(FLAGS_test_version_b_bin);

  // Verify the linked list with Version B.
  // We loop this twice, in case we've introduced a bug where tablet bootstrap
  // might fail on the second restart after migrating between versions of Kudu.
  for (int i = 0; i < 2; i++) {
    cluster_->Restart();
    ASSERT_OK(tester_->WaitAndVerify(FLAGS_seconds_to_run, written));
    ASSERT_OK(verifier_->VerifyCommittedOpIdsMatch());
    NO_FATALS(cluster_->AssertNoCrashes());
    cluster_->Shutdown();
  }
}

} // namespace itest
} // namespace kudu
