/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * 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
 *
 *      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.
 */

/*
 * End-to-end test to ensure that mapping of vsoc regions works on the host.
 */

#include <gtest/gtest.h>
#include "common/vsoc/lib/e2e_test_region_view.h"
#include "host/libs/config/cuttlefish_config.h"

// Here is a summary of the two regions interrupt and write test:
// 1. Write our strings to the first region
// 2. Ensure that our peer hasn't signalled the second region. That would
//    indicate that it didn't wait for our interrupt.
// 3. Send the interrupt on the first region
// 4. Wait for our peer's interrupt on the first region
// 5. Confirm that we can see our peer's writes in the first region
// 6. Initialize our strings in the second region
// 7. Send an interrupt on the second region to our peer
// 8. Wait for our peer's interrupt on the second region
// 9. Confirm that we can see our peer's writes in the second region
// 10. Repeat the process for signaling.
// 11. Confirm that no interrupt is pending in the first region
// 12. Confirm that no interrupt is pending in the second region

template <typename View>
void SetHostStrings(View* in) {
  size_t num_data = in->string_size();
  EXPECT_LE(static_cast<size_t>(2), num_data);
  for (size_t i = 0; i < num_data; ++i) {
    EXPECT_TRUE(!in->host_string(i)[0] ||
                !strcmp(in->host_string(i), View::Layout::host_pattern));
    in->set_host_string(i, View::Layout::host_pattern);
    EXPECT_STREQ(in->host_string(i), View::Layout::host_pattern);
  }
}

template <typename View>
void CheckPeerStrings(View* in) {
  size_t num_data = in->string_size();
  EXPECT_LE(static_cast<size_t>(2), num_data);
  for (size_t i = 0; i < num_data; ++i) {
    EXPECT_STREQ(View::Layout::guest_pattern, in->guest_string(i));
  }
}

TEST(RegionTest, PeerTests) {
  auto primary =
      vsoc::E2EPrimaryRegionView::GetInstance(vsoc::GetDomain().c_str());
  ASSERT_TRUE(!!primary);
  auto secondary =
      vsoc::E2ESecondaryRegionView::GetInstance(vsoc::GetDomain().c_str());
  ASSERT_TRUE(!!secondary);
  LOG(INFO) << "Regions are open";
  SetHostStrings(primary);
  EXPECT_FALSE(secondary->HasIncomingInterrupt());
  EXPECT_TRUE(primary->MaybeInterruptPeer());
  LOG(INFO) << "Waiting for first interrupt from peer";
  primary->WaitForInterrupt();
  LOG(INFO) << "First interrupt received";
  CheckPeerStrings(primary);
  SetHostStrings(secondary);
  EXPECT_TRUE(secondary->MaybeInterruptPeer());
  LOG(INFO) << "Waiting for second interrupt from peer";
  secondary->WaitForInterrupt();
  LOG(INFO) << "Second interrupt received";
  CheckPeerStrings(secondary);

  // Test signals
  EXPECT_FALSE(secondary->HasIncomingInterrupt());
  LOG(INFO) << "Verified no early second signal";
  primary->SendSignal(vsoc::layout::Sides::Peer,
                      &primary->data()->host_to_guest_signal);
  LOG(INFO) << "Signal sent. Waiting for first signal from peer";
  primary->WaitForInterrupt();
  int count = 0;  // counts the number of signals received.
  primary->ProcessSignalsFromPeer(
      [&primary, &count](uint32_t offset) {
        ++count;
        EXPECT_EQ(primary->guest_to_host_signal_offset(), offset);
      });
  EXPECT_EQ(1, count);
  LOG(INFO) << "Signal received on primary region";
  secondary->SendSignal(vsoc::layout::Sides::Peer,
                        &secondary->data()->host_to_guest_signal);
  LOG(INFO) << "Signal sent. Waiting for second signal from peer";
  secondary->WaitForInterrupt();
  count = 0;
  secondary->ProcessSignalsFromPeer(
      [secondary, &count](uint32_t offset) {
        ++count;
        EXPECT_EQ(secondary->guest_to_host_signal_offset(), offset);
      });
  EXPECT_EQ(1, count);
  LOG(INFO) << "Signal received on secondary region";

  EXPECT_FALSE(primary->HasIncomingInterrupt());
  EXPECT_FALSE(secondary->HasIncomingInterrupt());
}

TEST(RegionTest, MissingRegionCausesDeath) {
  EXPECT_DEATH(
      vsoc::E2EUnfindableRegionView::GetInstance(vsoc::GetDomain().c_str()),
      ".*");
}

int main(int argc, char** argv) {
  testing::InitGoogleTest(&argc, argv);
  int rval = RUN_ALL_TESTS();
  if (!rval) {
    auto region =
        vsoc::E2EPrimaryRegionView::GetInstance(vsoc::GetDomain().c_str());
    region->host_status(vsoc::layout::e2e_test::E2E_MEMORY_FILLED);
  }
  return rval;
}
