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 #include <thread> 18 19 #include <gtest/gtest.h> 20 21 #include <utils/SystemClock.h> 22 23 #include "vhal_v2_0/VehicleObjectPool.h" 24 25 namespace android { 26 namespace hardware { 27 namespace automotive { 28 namespace vehicle { 29 namespace V2_0 { 30 31 namespace { 32 33 class VehicleObjectPoolTest : public ::testing::Test { 34 protected: 35 void SetUp() override { 36 stats = PoolStats::instance(); 37 resetStats(); 38 valuePool.reset(new VehiclePropValuePool); 39 } 40 41 void TearDown() override { 42 // At the end, all created objects should be either recycled or deleted. 43 // Some objects could be recycled multiple times, that's why it's <= 44 ASSERT_EQ(stats->Obtained, stats->Recycled); 45 ASSERT_LE(stats->Created, stats->Recycled); 46 } 47 private: 48 void resetStats() { 49 stats->Obtained = 0; 50 stats->Created = 0; 51 stats->Recycled = 0; 52 } 53 54 public: 55 PoolStats* stats; 56 std::unique_ptr<VehiclePropValuePool> valuePool; 57 }; 58 59 TEST_F(VehicleObjectPoolTest, valuePoolBasicCorrectness) { 60 void* raw = valuePool->obtain(VehiclePropertyType::INT32).get(); 61 // At this point, v1 should be recycled and the only object in the pool. 62 ASSERT_EQ(raw, valuePool->obtain(VehiclePropertyType::INT32).get()); 63 // Obtaining value of another type - should return a new object 64 ASSERT_NE(raw, valuePool->obtain(VehiclePropertyType::FLOAT).get()); 65 66 ASSERT_EQ(3u, stats->Obtained); 67 ASSERT_EQ(2u, stats->Created); 68 } 69 70 TEST_F(VehicleObjectPoolTest, valuePoolStrings) { 71 valuePool->obtain(VehiclePropertyType::STRING); 72 auto vs = valuePool->obtain(VehiclePropertyType::STRING); 73 vs->value.stringValue = "Hello"; 74 void* raw = vs.get(); 75 vs.reset(); // delete the pointer 76 77 auto vs2 = valuePool->obtain(VehiclePropertyType::STRING); 78 ASSERT_EQ(0u, vs2->value.stringValue.size()); 79 ASSERT_NE(raw, valuePool->obtain(VehiclePropertyType::STRING).get()); 80 81 ASSERT_EQ(0u, stats->Obtained); 82 } 83 84 TEST_F(VehicleObjectPoolTest, valuePoolMultithreadedBenchmark) { 85 // In this test we have T threads that concurrently in C cycles 86 // obtain and release O VehiclePropValue objects of FLOAT / INT32 types. 87 88 const int T = 2; 89 const int C = 500; 90 const int O = 100; 91 92 auto poolPtr = valuePool.get(); 93 94 std::vector<std::thread> threads; 95 auto start = elapsedRealtimeNano(); 96 for (int i = 0; i < T; i++) { 97 threads.push_back(std::thread([&poolPtr] () { 98 for (int j = 0; j < C; j++) { 99 std::vector<recyclable_ptr<VehiclePropValue>> vec; 100 for (int k = 0; k < O; k++) { 101 vec.push_back( 102 poolPtr->obtain(k % 2 == 0 103 ? VehiclePropertyType::FLOAT 104 : VehiclePropertyType::INT32)); 105 } 106 } 107 })); 108 } 109 110 for (auto& t : threads) { 111 t.join(); 112 } 113 auto finish = elapsedRealtimeNano(); 114 115 ASSERT_EQ(static_cast<uint32_t>(T * C * O), stats->Obtained); 116 ASSERT_EQ(static_cast<uint32_t>(T * C * O), stats->Recycled); 117 // Created less than obtained. 118 ASSERT_GE(static_cast<uint32_t>(T * O), stats->Created); 119 120 auto elapsedMs = (finish - start) / 1000000; 121 ASSERT_GE(1000, elapsedMs); // Less a second to access 100K objects. 122 // Typically it takes about 0.1s on Nexus6P. 123 } 124 125 } // namespace anonymous 126 127 } // namespace V2_0 128 } // namespace vehicle 129 } // namespace automotive 130 } // namespace hardware 131 } // namespace android 132