xref: /aosp_15_r20/external/cronet/base/containers/vector_buffer_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2017 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/containers/vector_buffer.h"
6 
7 #include "base/compiler_specific.h"
8 #include "base/memory/raw_ptr.h"
9 #include "base/test/copy_only_int.h"
10 #include "base/test/move_only_int.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 
13 namespace base::internal {
14 
15 namespace {
16 
17 class TRIVIAL_ABI TrivialAbiWithCountingOperations {
18  public:
TrivialAbiWithCountingOperations(int * destruction_counter,int * move_counter)19   TrivialAbiWithCountingOperations(int* destruction_counter, int* move_counter)
20       : destruction_counter_(destruction_counter),
21         move_counter_(move_counter) {}
22 
~TrivialAbiWithCountingOperations()23   ~TrivialAbiWithCountingOperations() { ++*destruction_counter_; }
24 
25   // Copy construction and assignment should not be used.
26   TrivialAbiWithCountingOperations(const TrivialAbiWithCountingOperations&) =
27       delete;
28   TrivialAbiWithCountingOperations& operator=(
29       const TrivialAbiWithCountingOperations&) = delete;
30 
31   // Count how many times the move constructor is used.
TrivialAbiWithCountingOperations(TrivialAbiWithCountingOperations && rhs)32   TrivialAbiWithCountingOperations(TrivialAbiWithCountingOperations&& rhs)
33       : destruction_counter_(rhs.destruction_counter_),
34         move_counter_(rhs.move_counter_) {
35     ++*move_counter_;
36   }
37 
38   // Move assignment should not be used.
39   TrivialAbiWithCountingOperations& operator=(
40       TrivialAbiWithCountingOperations&&) = delete;
41 
42  private:
43   raw_ptr<int> destruction_counter_;
44   raw_ptr<int> move_counter_;
45 };
46 
47 }  // namespace
48 
TEST(VectorBuffer,DeletePOD)49 TEST(VectorBuffer, DeletePOD) {
50   constexpr int size = 10;
51   VectorBuffer<int> buffer(size);
52   for (int i = 0; i < size; i++)
53     buffer.begin()[i] = i + 1;
54 
55   buffer.DestructRange(buffer.begin(), buffer.end());
56 
57   // Delete should do nothing.
58   for (int i = 0; i < size; i++)
59     EXPECT_EQ(i + 1, buffer.begin()[i]);
60 }
61 
TEST(VectorBuffer,DeleteMoveOnly)62 TEST(VectorBuffer, DeleteMoveOnly) {
63   constexpr int size = 10;
64   VectorBuffer<MoveOnlyInt> buffer(size);
65   for (int i = 0; i < size; i++)
66     new (buffer.begin() + i) MoveOnlyInt(i + 1);
67 
68   buffer.DestructRange(buffer.begin(), buffer.end());
69 
70   // Delete should have reset all of the values to 0.
71   for (int i = 0; i < size; i++)
72     EXPECT_EQ(0, buffer.begin()[i].data());
73 }
74 
TEST(VectorBuffer,PODMove)75 TEST(VectorBuffer, PODMove) {
76   constexpr int size = 10;
77   VectorBuffer<int> dest(size);
78 
79   VectorBuffer<int> original(size);
80   for (int i = 0; i < size; i++)
81     original.begin()[i] = i + 1;
82 
83   original.MoveRange(original.begin(), original.end(), dest.begin());
84   for (int i = 0; i < size; i++)
85     EXPECT_EQ(i + 1, dest.begin()[i]);
86 }
87 
TEST(VectorBuffer,MovableMove)88 TEST(VectorBuffer, MovableMove) {
89   constexpr int size = 10;
90   VectorBuffer<MoveOnlyInt> dest(size);
91 
92   VectorBuffer<MoveOnlyInt> original(size);
93   for (int i = 0; i < size; i++)
94     new (original.begin() + i) MoveOnlyInt(i + 1);
95 
96   original.MoveRange(original.begin(), original.end(), dest.begin());
97 
98   // Moving from a MoveOnlyInt resets to 0.
99   for (int i = 0; i < size; i++) {
100     EXPECT_EQ(0, original.begin()[i].data());
101     EXPECT_EQ(i + 1, dest.begin()[i].data());
102   }
103 }
104 
TEST(VectorBuffer,CopyToMove)105 TEST(VectorBuffer, CopyToMove) {
106   constexpr int size = 10;
107   VectorBuffer<CopyOnlyInt> dest(size);
108 
109   VectorBuffer<CopyOnlyInt> original(size);
110   for (int i = 0; i < size; i++)
111     new (original.begin() + i) CopyOnlyInt(i + 1);
112 
113   original.MoveRange(original.begin(), original.end(), dest.begin());
114 
115   // The original should have been destructed, which should reset the value to
116   // 0. Technically this dereferences the destructed object.
117   for (int i = 0; i < size; i++) {
118     EXPECT_EQ(0, original.begin()[i].data());
119     EXPECT_EQ(i + 1, dest.begin()[i].data());
120   }
121 }
122 
TEST(VectorBuffer,TrivialAbiMove)123 TEST(VectorBuffer, TrivialAbiMove) {
124   // Currently trivial relocation doesn't work on Windows for some reason, so
125   // the test needs to handle both cases.
126   constexpr bool kHaveTrivialRelocation =
127       IS_TRIVIALLY_RELOCATABLE(TrivialAbiWithCountingOperations);
128   constexpr int size = 10;
129   VectorBuffer<TrivialAbiWithCountingOperations> dest(size);
130 
131   int destruction_count = 0;
132   int move_count = 0;
133   VectorBuffer<TrivialAbiWithCountingOperations> original(size);
134   for (int i = 0; i < size; i++) {
135     new (original.begin() + i)
136         TrivialAbiWithCountingOperations(&destruction_count, &move_count);
137   }
138 
139   original.MoveRange(original.begin(), original.end(), dest.begin());
140 
141   // We expect the move to have been performed via memcpy, without calling move
142   // constructors or destructors.
143   EXPECT_EQ(destruction_count, kHaveTrivialRelocation ? 0 : size);
144   EXPECT_EQ(move_count, kHaveTrivialRelocation ? 0 : size);
145 
146   dest.DestructRange(dest.begin(), dest.end());
147   EXPECT_EQ(destruction_count, kHaveTrivialRelocation ? size : size * 2);
148   EXPECT_EQ(move_count, kHaveTrivialRelocation ? 0 : size);
149 }
150 
151 }  // namespace base::internal
152