Home | History | Annotate | Download | only in lib
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /*
     18  * End-to-end test to ensure that mapping of vsoc regions works on the host.
     19  */
     20 
     21 #include <gtest/gtest.h>
     22 #include "common/vsoc/lib/e2e_test_region_view.h"
     23 #include "host/libs/config/cuttlefish_config.h"
     24 
     25 // Here is a summary of the two regions interrupt and write test:
     26 // 1. Write our strings to the first region
     27 // 2. Ensure that our peer hasn't signalled the second region. That would
     28 //    indicate that it didn't wait for our interrupt.
     29 // 3. Send the interrupt on the first region
     30 // 4. Wait for our peer's interrupt on the first region
     31 // 5. Confirm that we can see our peer's writes in the first region
     32 // 6. Initialize our strings in the second region
     33 // 7. Send an interrupt on the second region to our peer
     34 // 8. Wait for our peer's interrupt on the second region
     35 // 9. Confirm that we can see our peer's writes in the second region
     36 // 10. Repeat the process for signaling.
     37 // 11. Confirm that no interrupt is pending in the first region
     38 // 12. Confirm that no interrupt is pending in the second region
     39 
     40 template <typename View>
     41 void SetHostStrings(View* in) {
     42   size_t num_data = in->string_size();
     43   EXPECT_LE(static_cast<size_t>(2), num_data);
     44   for (size_t i = 0; i < num_data; ++i) {
     45     EXPECT_TRUE(!in->host_string(i)[0] ||
     46                 !strcmp(in->host_string(i), View::Layout::host_pattern));
     47     in->set_host_string(i, View::Layout::host_pattern);
     48     EXPECT_STREQ(in->host_string(i), View::Layout::host_pattern);
     49   }
     50 }
     51 
     52 template <typename View>
     53 void CheckPeerStrings(View* in) {
     54   size_t num_data = in->string_size();
     55   EXPECT_LE(static_cast<size_t>(2), num_data);
     56   for (size_t i = 0; i < num_data; ++i) {
     57     EXPECT_STREQ(View::Layout::guest_pattern, in->guest_string(i));
     58   }
     59 }
     60 
     61 TEST(RegionTest, PeerTests) {
     62   auto primary =
     63       vsoc::E2EPrimaryRegionView::GetInstance(vsoc::GetDomain().c_str());
     64   ASSERT_TRUE(!!primary);
     65   auto secondary =
     66       vsoc::E2ESecondaryRegionView::GetInstance(vsoc::GetDomain().c_str());
     67   ASSERT_TRUE(!!secondary);
     68   LOG(INFO) << "Regions are open";
     69   SetHostStrings(primary);
     70   EXPECT_FALSE(secondary->HasIncomingInterrupt());
     71   EXPECT_TRUE(primary->MaybeInterruptPeer());
     72   LOG(INFO) << "Waiting for first interrupt from peer";
     73   primary->WaitForInterrupt();
     74   LOG(INFO) << "First interrupt received";
     75   CheckPeerStrings(primary);
     76   SetHostStrings(secondary);
     77   EXPECT_TRUE(secondary->MaybeInterruptPeer());
     78   LOG(INFO) << "Waiting for second interrupt from peer";
     79   secondary->WaitForInterrupt();
     80   LOG(INFO) << "Second interrupt received";
     81   CheckPeerStrings(secondary);
     82 
     83   // Test signals
     84   EXPECT_FALSE(secondary->HasIncomingInterrupt());
     85   LOG(INFO) << "Verified no early second signal";
     86   primary->SendSignal(vsoc::layout::Sides::Peer,
     87                       &primary->data()->host_to_guest_signal);
     88   LOG(INFO) << "Signal sent. Waiting for first signal from peer";
     89   primary->WaitForInterrupt();
     90   int count = 0;  // counts the number of signals received.
     91   primary->ProcessSignalsFromPeer(
     92       [&primary, &count](uint32_t offset) {
     93         ++count;
     94         EXPECT_EQ(primary->guest_to_host_signal_offset(), offset);
     95       });
     96   EXPECT_EQ(1, count);
     97   LOG(INFO) << "Signal received on primary region";
     98   secondary->SendSignal(vsoc::layout::Sides::Peer,
     99                         &secondary->data()->host_to_guest_signal);
    100   LOG(INFO) << "Signal sent. Waiting for second signal from peer";
    101   secondary->WaitForInterrupt();
    102   count = 0;
    103   secondary->ProcessSignalsFromPeer(
    104       [secondary, &count](uint32_t offset) {
    105         ++count;
    106         EXPECT_EQ(secondary->guest_to_host_signal_offset(), offset);
    107       });
    108   EXPECT_EQ(1, count);
    109   LOG(INFO) << "Signal received on secondary region";
    110 
    111   EXPECT_FALSE(primary->HasIncomingInterrupt());
    112   EXPECT_FALSE(secondary->HasIncomingInterrupt());
    113 }
    114 
    115 TEST(RegionTest, MissingRegionCausesDeath) {
    116   EXPECT_DEATH(
    117       vsoc::E2EUnfindableRegionView::GetInstance(vsoc::GetDomain().c_str()),
    118       ".*");
    119 }
    120 
    121 int main(int argc, char** argv) {
    122   testing::InitGoogleTest(&argc, argv);
    123   int rval = RUN_ALL_TESTS();
    124   if (!rval) {
    125     auto region =
    126         vsoc::E2EPrimaryRegionView::GetInstance(vsoc::GetDomain().c_str());
    127     region->host_status(vsoc::layout::e2e_test::E2E_MEMORY_FILLED);
    128   }
    129   return rval;
    130 }
    131