1aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang#include "libbroadcastring/broadcast_ring.h"
2aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
3aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang#include <stdlib.h>
4aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang#include <memory>
5aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang#include <thread>  // NOLINT
6aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang#include <sys/mman.h>
7aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
8aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang#include <gtest/gtest.h>
9aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
10aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangnamespace android {
11aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangnamespace dvr {
12aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangnamespace {
13aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
14aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangtemplate <uint32_t N>
15aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangstruct alignas(8) Aligned {
16aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  char v[N];
17aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang};
18aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
19aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangtemplate <uint32_t N>
20aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangstruct alignas(8) Sized {
21aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  Sized() { Clear(); }
22aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  explicit Sized(char c) { Fill(c); }
23aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  char v[sizeof(Aligned<N>)];
24aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  void Clear() { memset(v, 0, sizeof(v)); }
25aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  void Fill(char c) { memset(v, c, sizeof(v)); }
26aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  static Sized Pattern(uint8_t c) {
27aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    Sized sized;
28aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    for (size_t i = 0; i < sizeof(v); ++i) {
29aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      sized.v[i] = static_cast<char>(c + i);
30aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    }
31aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    return sized;
32aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  }
33aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  bool operator==(const Sized& right) const {
34aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    static_assert(sizeof(*this) == sizeof(v), "Size mismatch");
35aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    return !memcmp(v, right.v, sizeof(v));
36aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  }
37aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  template <typename SmallerSized>
38aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  SmallerSized Truncate() const {
39aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    SmallerSized val;
40aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    static_assert(sizeof(val.v) <= sizeof(v), "Cannot truncate to larger size");
41aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    memcpy(val.v, v, sizeof(val.v));
42aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    return val;
43aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  }
44aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang};
45aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
46aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangchar FillChar(int val) { return static_cast<char>(val); }
47aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
48aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangstruct FakeMmap {
49aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  explicit FakeMmap(size_t size) : size(size), data(new char[size]) {}
50aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  size_t size;
51aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  std::unique_ptr<char[]> data;
52aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  void* mmap() { return static_cast<void*>(data.get()); }
53aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang};
54aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
55aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangtemplate <typename Ring>
56aacc1fceefd75e33908fa6feee2cf03688e09374Michael SpangFakeMmap CreateRing(Ring* ring, uint32_t count) {
57aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  FakeMmap mmap(Ring::MemorySize(count));
58aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  *ring = Ring::Create(mmap.mmap(), mmap.size, count);
59aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  return mmap;
60aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang}
61aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
62aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangtemplate <typename RecordType, bool StaticSize = false,
63aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang          uint32_t StaticCount = 0, uint32_t MaxReserved = 1,
64aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang          uint32_t MinAvailable = 0>
65aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangstruct Traits {
66aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using Record = RecordType;
67aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  static constexpr bool kUseStaticRecordSize = StaticSize;
68aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  static constexpr uint32_t kStaticRecordCount = StaticCount;
69aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  static constexpr uint32_t kMaxReservedRecords = MaxReserved;
70aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  static constexpr uint32_t kMinAvailableRecords = MinAvailable;
71aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  static constexpr uint32_t kMinRecordCount = MaxReserved + MinAvailable;
72aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang};
73aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
74aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangtemplate <typename Record, bool StaticSize = false, uint32_t MaxReserved = 1,
75aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang          uint32_t MinAvailable = 7>
76aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangstruct TraitsDynamic
77aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    : public Traits<Record, StaticSize, 0, MaxReserved, MinAvailable> {
78aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using Ring = BroadcastRing<Record, TraitsDynamic>;
79aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  static uint32_t MinCount() { return MaxReserved + MinAvailable; }
80aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang};
81aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
82aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangtemplate <typename Record, uint32_t StaticCount = 1, bool StaticSize = true,
83aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang          uint32_t MaxReserved = 1, uint32_t MinAvailable = 0>
84aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangstruct TraitsStatic
85aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    : public Traits<Record, true, StaticCount, MaxReserved, MinAvailable> {
86aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using Ring = BroadcastRing<Record, TraitsStatic>;
87aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  static uint32_t MinCount() { return StaticCount; }
88aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang};
89aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
90aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangusing Dynamic_8_NxM = TraitsDynamic<Sized<8>>;
91aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangusing Dynamic_16_NxM = TraitsDynamic<Sized<16>>;
92aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangusing Dynamic_32_NxM = TraitsDynamic<Sized<32>>;
93aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangusing Dynamic_32_32xM = TraitsDynamic<Sized<32>, true>;
94aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangusing Dynamic_16_NxM_1plus0 = TraitsDynamic<Sized<16>, false, 1, 0>;
95aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangusing Dynamic_16_NxM_1plus1 = TraitsDynamic<Sized<16>, false, 1, 1>;
96aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangusing Dynamic_16_NxM_5plus11 = TraitsDynamic<Sized<16>, false, 5, 11>;
97aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangusing Dynamic_256_NxM_1plus0 = TraitsDynamic<Sized<256>, false, 1, 0>;
98aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
99aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangusing Static_8_8x1 = TraitsStatic<Sized<8>, 1>;
100aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangusing Static_8_8x16 = TraitsStatic<Sized<8>, 16>;
101aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangusing Static_16_16x8 = TraitsStatic<Sized<16>, 8>;
102aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangusing Static_16_16x16 = TraitsStatic<Sized<16>, 16>;
103aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangusing Static_16_16x32 = TraitsStatic<Sized<16>, 32>;
104aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangusing Static_32_Nx8 = TraitsStatic<Sized<32>, 8, false>;
105aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
106aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangusing TraitsList = ::testing::Types<Dynamic_8_NxM,           //
107aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang                                    Dynamic_16_NxM,          //
108aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang                                    Dynamic_32_NxM,          //
109aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang                                    Dynamic_32_32xM,         //
110aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang                                    Dynamic_16_NxM_1plus0,   //
111aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang                                    Dynamic_16_NxM_1plus1,   //
112aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang                                    Dynamic_16_NxM_5plus11,  //
113aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang                                    Dynamic_256_NxM_1plus0,  //
114aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang                                    Static_8_8x1,            //
115aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang                                    Static_8_8x16,           //
116aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang                                    Static_16_16x8,          //
117aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang                                    Static_16_16x16,         //
118aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang                                    Static_16_16x32,         //
119aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang                                    Static_32_Nx8>;
120aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
121aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang}  // namespace
122aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
123aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangtemplate <typename T>
124aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangclass BroadcastRingTest : public ::testing::Test {};
125aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
126aacc1fceefd75e33908fa6feee2cf03688e09374Michael SpangTYPED_TEST_CASE(BroadcastRingTest, TraitsList);
127aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
128aacc1fceefd75e33908fa6feee2cf03688e09374Michael SpangTYPED_TEST(BroadcastRingTest, Geometry) {
129aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using Record = typename TypeParam::Record;
130aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using Ring = typename TypeParam::Ring;
131aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  Ring ring;
132aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  auto mmap = CreateRing(&ring, Ring::Traits::MinCount());
133aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  EXPECT_EQ(Ring::Traits::MinCount(), ring.record_count());
134aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  EXPECT_EQ(sizeof(Record), ring.record_size());
135aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang}
136aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
137aacc1fceefd75e33908fa6feee2cf03688e09374Michael SpangTYPED_TEST(BroadcastRingTest, PutGet) {
138aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using Record = typename TypeParam::Record;
139aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using Ring = typename TypeParam::Ring;
140aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  Ring ring;
141aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  auto mmap = CreateRing(&ring, Ring::Traits::MinCount());
142aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  const uint32_t oldest_sequence_at_start = ring.GetOldestSequence();
143aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  const uint32_t next_sequence_at_start = ring.GetNextSequence();
144aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  {
145aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    uint32_t sequence = oldest_sequence_at_start;
146aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    Record record;
147aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_FALSE(ring.Get(&sequence, &record));
148aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_EQ(oldest_sequence_at_start, sequence);
149aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_EQ(Record(), record);
150aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  }
151aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  const Record original_record(0x1a);
152aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  ring.Put(original_record);
153aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  {
154aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    uint32_t sequence = next_sequence_at_start;
155aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    Record record;
156aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_TRUE(ring.Get(&sequence, &record));
157aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_EQ(next_sequence_at_start, sequence);
158aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_EQ(original_record, record);
159aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  }
160aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  {
161aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    uint32_t sequence = next_sequence_at_start + 1;
162aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    Record record;
163aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_FALSE(ring.Get(&sequence, &record));
164aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_EQ(next_sequence_at_start + 1, sequence);
165aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_EQ(Record(), record);
166aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  }
167aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang}
168aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
169aacc1fceefd75e33908fa6feee2cf03688e09374Michael SpangTYPED_TEST(BroadcastRingTest, FillOnce) {
170aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using Record = typename TypeParam::Record;
171aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using Ring = typename TypeParam::Ring;
172aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  Ring ring;
173aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  auto mmap = CreateRing(&ring, Ring::Traits::MinCount());
174aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  const uint32_t next_sequence_at_start = ring.GetNextSequence();
175aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  for (uint32_t i = 0; i < ring.record_count(); ++i)
176aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    ring.Put(Record(FillChar(i)));
177aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  for (uint32_t i = 0; i < ring.record_count(); ++i) {
178aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    const uint32_t expected_sequence = next_sequence_at_start + i;
179aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    const Record expected_record(FillChar(i));
180aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    {
181aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      uint32_t sequence = ring.GetOldestSequence() + i;
182aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      Record record;
183aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_TRUE(ring.Get(&sequence, &record));
184aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_EQ(expected_sequence, sequence);
185aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_EQ(expected_record, record);
186aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    }
187aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  }
188aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  {
189aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    uint32_t sequence = ring.GetOldestSequence() + ring.record_count();
190aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    Record record;
191aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_FALSE(ring.Get(&sequence, &record));
192aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  }
193aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang}
194aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
195aacc1fceefd75e33908fa6feee2cf03688e09374Michael SpangTYPED_TEST(BroadcastRingTest, FillTwice) {
196aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using Record = typename TypeParam::Record;
197aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using Ring = typename TypeParam::Ring;
198aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  Ring ring;
199aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  auto mmap = CreateRing(&ring, Ring::Traits::MinCount());
200aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  const uint32_t next_sequence_at_start = ring.GetNextSequence();
201aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  for (uint32_t i = 0; i < 2 * ring.record_count(); ++i) {
202aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    const Record newest_record(FillChar(i));
203aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    ring.Put(newest_record);
204aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
205aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    const uint32_t newest_sequence = next_sequence_at_start + i;
206aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    const uint32_t records_available = std::min(i + 1, ring.record_count());
207aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    const uint32_t oldest_sequence = newest_sequence - records_available + 1;
208aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_EQ(newest_sequence, ring.GetNewestSequence());
209aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_EQ(oldest_sequence, ring.GetOldestSequence());
210aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_EQ(newest_sequence + 1, ring.GetNextSequence());
211aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
212aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    for (uint32_t j = 0; j < records_available; ++j) {
213aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      const uint32_t sequence_jth_newest = newest_sequence - j;
214aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      const Record record_jth_newest(FillChar(i - j));
215aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
216aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      {
217aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        uint32_t sequence = sequence_jth_newest;
218aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        Record record;
219aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        EXPECT_TRUE(ring.Get(&sequence, &record));
220aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        EXPECT_EQ(sequence_jth_newest, sequence);
221aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        EXPECT_EQ(record_jth_newest, record);
222aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      }
223aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
224aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      {
225aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        uint32_t sequence = sequence_jth_newest;
226aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        Record record;
227aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        EXPECT_TRUE(ring.GetNewest(&sequence, &record));
228aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        EXPECT_EQ(newest_sequence, sequence);
229aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        EXPECT_EQ(newest_record, record);
230aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      }
231aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    }
232aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
233aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    const Record oldest_record(
234aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        FillChar(i + (oldest_sequence - newest_sequence)));
235aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    const uint32_t sequence_0th_overwritten = oldest_sequence - 1;
236aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    const uint32_t sequence_0th_future = newest_sequence + 1;
237aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    const uint32_t sequence_1st_future = newest_sequence + 2;
238aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
239aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    {
240aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      uint32_t sequence = sequence_0th_overwritten;
241aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      Record record;
242aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_TRUE(ring.Get(&sequence, &record));
243aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_EQ(oldest_sequence, sequence);
244aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_EQ(oldest_record, record);
245aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    }
246aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
247aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    {
248aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      uint32_t sequence = sequence_0th_overwritten;
249aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      Record record;
250aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_TRUE(ring.GetNewest(&sequence, &record));
251aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_EQ(newest_sequence, sequence);
252aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_EQ(newest_record, record);
253aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    }
254aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
255aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    {
256aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      uint32_t sequence = sequence_0th_future;
257aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      Record record;
258aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_FALSE(ring.Get(&sequence, &record));
259aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_EQ(sequence_0th_future, sequence);
260aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_EQ(Record(), record);
261aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    }
262aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
263aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    {
264aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      uint32_t sequence = sequence_0th_future;
265aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      Record record;
266aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_FALSE(ring.GetNewest(&sequence, &record));
267aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_EQ(sequence_0th_future, sequence);
268aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_EQ(Record(), record);
269aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    }
270aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
271aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    {
272aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      uint32_t sequence = sequence_1st_future;
273aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      Record record;
274aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_TRUE(ring.Get(&sequence, &record));
275aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_EQ(oldest_sequence, sequence);
276aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_EQ(oldest_record, record);
277aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    }
278aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
279aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    {
280aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      uint32_t sequence = sequence_1st_future;
281aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      Record record;
282aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_TRUE(ring.GetNewest(&sequence, &record));
283aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_EQ(newest_sequence, sequence);
284aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_EQ(newest_record, record);
285aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    }
286aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  }
287aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang}
288aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
289aacc1fceefd75e33908fa6feee2cf03688e09374Michael SpangTYPED_TEST(BroadcastRingTest, Import) {
290aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using Record = typename TypeParam::Record;
291aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using Ring = typename TypeParam::Ring;
292aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  Ring ring;
293aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  auto mmap = CreateRing(&ring, Ring::Traits::MinCount());
294aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
295aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  const uint32_t sequence_0 = ring.GetNextSequence();
296aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  const uint32_t sequence_1 = ring.GetNextSequence() + 1;
297aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  const Record record_0 = Record::Pattern(0x00);
298aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  const Record record_1 = Record::Pattern(0x80);
299aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  ring.Put(record_0);
300aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  ring.Put(record_1);
301aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
302aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  {
303aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    Ring imported_ring;
304aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    bool import_ok;
305aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    std::tie(imported_ring, import_ok) = Ring::Import(mmap.mmap(), mmap.size);
306aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_TRUE(import_ok);
307aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_EQ(ring.record_size(), imported_ring.record_size());
308aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_EQ(ring.record_count(), imported_ring.record_count());
309aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
310aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    if (ring.record_count() != 1) {
311aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      uint32_t sequence = sequence_0;
312aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      Record imported_record;
313aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_TRUE(imported_ring.Get(&sequence, &imported_record));
314aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_EQ(sequence_0, sequence);
315aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_EQ(record_0, imported_record);
316aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    }
317aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
318aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    {
319aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      uint32_t sequence = sequence_1;
320aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      Record imported_record;
321aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_TRUE(imported_ring.Get(&sequence, &imported_record));
322aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_EQ(sequence_1, sequence);
323aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_EQ(record_1, imported_record);
324aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    }
325aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  }
326aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang}
327aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
328aacc1fceefd75e33908fa6feee2cf03688e09374Michael SpangTEST(BroadcastRingTest, ShouldFailImportIfStaticSizeMismatch) {
329aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using OriginalRing = typename Static_16_16x16::Ring;
330aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using RecordSizeMismatchRing = typename Static_8_8x16::Ring;
331aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using RecordCountMismatchRing = typename Static_16_16x8::Ring;
332aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
333aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  OriginalRing original_ring;
334aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  auto mmap = CreateRing(&original_ring, OriginalRing::Traits::MinCount());
335aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
336aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  {
337aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    using ImportedRing = RecordSizeMismatchRing;
338aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    ImportedRing imported_ring;
339aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    bool import_ok;
340aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    std::tie(imported_ring, import_ok) =
341aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        ImportedRing::Import(mmap.mmap(), mmap.size);
342aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_FALSE(import_ok);
343aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    auto mmap_imported =
344aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        CreateRing(&imported_ring, ImportedRing::Traits::MinCount());
345aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_NE(original_ring.record_size(), imported_ring.record_size());
346aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_EQ(original_ring.record_count(), imported_ring.record_count());
347aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  }
348aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
349aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  {
350aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    using ImportedRing = RecordCountMismatchRing;
351aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    ImportedRing imported_ring;
352aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    bool import_ok;
353aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    std::tie(imported_ring, import_ok) =
354aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        ImportedRing::Import(mmap.mmap(), mmap.size);
355aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_FALSE(import_ok);
356aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    auto mmap_imported =
357aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        CreateRing(&imported_ring, ImportedRing::Traits::MinCount());
358aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_EQ(original_ring.record_size(), imported_ring.record_size());
359aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_NE(original_ring.record_count(), imported_ring.record_count());
360aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  }
361aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang}
362aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
363aacc1fceefd75e33908fa6feee2cf03688e09374Michael SpangTEST(BroadcastRingTest, ShouldFailImportIfDynamicSizeGrows) {
364aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using OriginalRing = typename Dynamic_8_NxM::Ring;
365aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using RecordSizeGrowsRing = typename Dynamic_16_NxM::Ring;
366aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
367aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  OriginalRing original_ring;
368aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  auto mmap = CreateRing(&original_ring, OriginalRing::Traits::MinCount());
369aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
370aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  {
371aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    using ImportedRing = RecordSizeGrowsRing;
372aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    ImportedRing imported_ring;
373aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    bool import_ok;
374aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    std::tie(imported_ring, import_ok) =
375aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        ImportedRing::Import(mmap.mmap(), mmap.size);
376aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_FALSE(import_ok);
377aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    auto mmap_imported =
378aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        CreateRing(&imported_ring, ImportedRing::Traits::MinCount());
379aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_LT(original_ring.record_size(), imported_ring.record_size());
380aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_EQ(original_ring.record_count(), imported_ring.record_count());
381aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  }
382aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang}
383aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
384aacc1fceefd75e33908fa6feee2cf03688e09374Michael SpangTEST(BroadcastRingTest, ShouldFailImportIfCountTooSmall) {
385aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using OriginalRing = typename Dynamic_16_NxM_1plus0::Ring;
386aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using MinCountRing = typename Dynamic_16_NxM_1plus1::Ring;
387aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
388aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  OriginalRing original_ring;
389aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  auto mmap = CreateRing(&original_ring, OriginalRing::Traits::MinCount());
390aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
391aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  {
392aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    using ImportedRing = MinCountRing;
393aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    ImportedRing imported_ring;
394aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    bool import_ok;
395aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    std::tie(imported_ring, import_ok) =
396aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        ImportedRing::Import(mmap.mmap(), mmap.size);
397aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_FALSE(import_ok);
398aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    auto mmap_imported =
399aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        CreateRing(&imported_ring, ImportedRing::Traits::MinCount());
400aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_EQ(original_ring.record_size(), imported_ring.record_size());
401aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_LT(original_ring.record_count(), imported_ring.record_count());
402aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  }
403aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang}
404aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
405aacc1fceefd75e33908fa6feee2cf03688e09374Michael SpangTEST(BroadcastRingTest, ShouldFailImportIfMmapTooSmall) {
406aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using OriginalRing = typename Dynamic_16_NxM::Ring;
407aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
408aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  OriginalRing original_ring;
409aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  auto mmap = CreateRing(&original_ring, OriginalRing::Traits::MinCount());
410aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
411aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  {
412aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    using ImportedRing = OriginalRing;
413aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    ImportedRing imported_ring;
414aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    bool import_ok;
415aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    const size_t kMinSize =
416aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        ImportedRing::MemorySize(original_ring.record_count());
417aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    std::tie(imported_ring, import_ok) = ImportedRing::Import(mmap.mmap(), 0);
418aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_FALSE(import_ok);
419aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    std::tie(imported_ring, import_ok) =
420aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        ImportedRing::Import(mmap.mmap(), kMinSize - 1);
421aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_FALSE(import_ok);
422aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    std::tie(imported_ring, import_ok) =
423aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        ImportedRing::Import(mmap.mmap(), kMinSize);
424aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_TRUE(import_ok);
425aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_EQ(original_ring.record_size(), imported_ring.record_size());
426aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_EQ(original_ring.record_count(), imported_ring.record_count());
427aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  }
428aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang}
429aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
430aacc1fceefd75e33908fa6feee2cf03688e09374Michael SpangTEST(BroadcastRingTest, ShouldImportIfDynamicSizeShrinks) {
431aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using OriginalRing = typename Dynamic_16_NxM::Ring;
432aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using RecordSizeShrinksRing = typename Dynamic_8_NxM::Ring;
433aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
434aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  OriginalRing original_ring;
435aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  auto mmap = CreateRing(&original_ring, OriginalRing::Traits::MinCount());
436aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
437aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using OriginalRecord = typename OriginalRing::Record;
438aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  const uint32_t original_sequence_0 = original_ring.GetNextSequence();
439aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  const uint32_t original_sequence_1 = original_ring.GetNextSequence() + 1;
440aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  const OriginalRecord original_record_0 = OriginalRecord::Pattern(0x00);
441aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  const OriginalRecord original_record_1 = OriginalRecord::Pattern(0x80);
442aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  original_ring.Put(original_record_0);
443aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  original_ring.Put(original_record_1);
444aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
445aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  {
446aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    using ImportedRing = RecordSizeShrinksRing;
447aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    using ImportedRecord = typename ImportedRing::Record;
448aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    ImportedRing imported_ring;
449aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    bool import_ok;
450aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    std::tie(imported_ring, import_ok) =
451aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        ImportedRing::Import(mmap.mmap(), mmap.size);
452aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_TRUE(import_ok);
453aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_EQ(original_ring.record_size(), imported_ring.record_size());
454aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_EQ(original_ring.record_count(), imported_ring.record_count());
455aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_GT(sizeof(OriginalRecord), sizeof(ImportedRecord));
456aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
457aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    {
458aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      uint32_t sequence = original_sequence_0;
459aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      ImportedRecord shrunk_record;
460aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_TRUE(imported_ring.Get(&sequence, &shrunk_record));
461aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_EQ(original_sequence_0, sequence);
462aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_EQ(original_record_0.Truncate<ImportedRecord>(), shrunk_record);
463aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    }
464aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
465aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    {
466aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      uint32_t sequence = original_sequence_1;
467aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      ImportedRecord shrunk_record;
468aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_TRUE(imported_ring.Get(&sequence, &shrunk_record));
469aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_EQ(original_sequence_1, sequence);
470aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_EQ(original_record_1.Truncate<ImportedRecord>(), shrunk_record);
471aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    }
472aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  }
473aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang}
474aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
475aacc1fceefd75e33908fa6feee2cf03688e09374Michael SpangTEST(BroadcastRingTest, ShouldImportIfCompatibleDynamicToStatic) {
476aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using OriginalRing = typename Dynamic_16_NxM::Ring;
477aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using ImportedRing = typename Static_16_16x16::Ring;
478aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using OriginalRecord = typename OriginalRing::Record;
479aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using ImportedRecord = typename ImportedRing::Record;
480aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using StaticRing = ImportedRing;
481aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
482aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  OriginalRing original_ring;
483aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  auto mmap = CreateRing(&original_ring, StaticRing::Traits::MinCount());
484aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
485aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  const uint32_t original_sequence_0 = original_ring.GetNextSequence();
486aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  const uint32_t original_sequence_1 = original_ring.GetNextSequence() + 1;
487aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  const OriginalRecord original_record_0 = OriginalRecord::Pattern(0x00);
488aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  const OriginalRecord original_record_1 = OriginalRecord::Pattern(0x80);
489aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  original_ring.Put(original_record_0);
490aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  original_ring.Put(original_record_1);
491aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
492aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  {
493aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    ImportedRing imported_ring;
494aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    bool import_ok;
495aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    std::tie(imported_ring, import_ok) =
496aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        ImportedRing::Import(mmap.mmap(), mmap.size);
497aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_TRUE(import_ok);
498aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_EQ(original_ring.record_size(), imported_ring.record_size());
499aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_EQ(original_ring.record_count(), imported_ring.record_count());
500aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
501aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    {
502aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      uint32_t sequence = original_sequence_0;
503aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      ImportedRecord imported_record;
504aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_TRUE(imported_ring.Get(&sequence, &imported_record));
505aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_EQ(original_sequence_0, sequence);
506aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_EQ(original_record_0, imported_record);
507aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    }
508aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
509aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    {
510aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      uint32_t sequence = original_sequence_1;
511aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      ImportedRecord imported_record;
512aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_TRUE(imported_ring.Get(&sequence, &imported_record));
513aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_EQ(original_sequence_1, sequence);
514aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_EQ(original_record_1, imported_record);
515aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    }
516aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  }
517aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang}
518aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
519aacc1fceefd75e33908fa6feee2cf03688e09374Michael SpangTEST(BroadcastRingTest, ShouldImportIfCompatibleStaticToDynamic) {
520aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using OriginalRing = typename Static_16_16x16::Ring;
521aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using ImportedRing = typename Dynamic_16_NxM::Ring;
522aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using OriginalRecord = typename OriginalRing::Record;
523aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using ImportedRecord = typename ImportedRing::Record;
524aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using StaticRing = OriginalRing;
525aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
526aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  OriginalRing original_ring;
527aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  auto mmap = CreateRing(&original_ring, StaticRing::Traits::MinCount());
528aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
529aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  const uint32_t original_sequence_0 = original_ring.GetNextSequence();
530aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  const uint32_t original_sequence_1 = original_ring.GetNextSequence() + 1;
531aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  const OriginalRecord original_record_0 = OriginalRecord::Pattern(0x00);
532aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  const OriginalRecord original_record_1 = OriginalRecord::Pattern(0x80);
533aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  original_ring.Put(original_record_0);
534aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  original_ring.Put(original_record_1);
535aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
536aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  {
537aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    ImportedRing imported_ring;
538aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    bool import_ok;
539aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    std::tie(imported_ring, import_ok) =
540aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        ImportedRing::Import(mmap.mmap(), mmap.size);
541aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_TRUE(import_ok);
542aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_EQ(original_ring.record_size(), imported_ring.record_size());
543aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_EQ(original_ring.record_count(), imported_ring.record_count());
544aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
545aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    {
546aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      uint32_t sequence = original_sequence_0;
547aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      ImportedRecord imported_record;
548aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_TRUE(imported_ring.Get(&sequence, &imported_record));
549aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_EQ(original_sequence_0, sequence);
550aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_EQ(original_record_0, imported_record);
551aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    }
552aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
553aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    {
554aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      uint32_t sequence = original_sequence_1;
555aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      ImportedRecord imported_record;
556aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_TRUE(imported_ring.Get(&sequence, &imported_record));
557aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_EQ(original_sequence_1, sequence);
558aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_EQ(original_record_1, imported_record);
559aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    }
560aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  }
561aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang}
562aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
563aacc1fceefd75e33908fa6feee2cf03688e09374Michael SpangTEST(BroadcastRingTest, ShouldImportIfReadonlyMmap) {
564aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using Ring = Dynamic_32_NxM::Ring;
565aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using Record = Ring::Record;
566aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
567aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  uint32_t record_count = Ring::Traits::MinCount();
568aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  size_t ring_size = Ring::MemorySize(record_count);
569aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
570aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  size_t page_size = sysconf(_SC_PAGESIZE);
571aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  size_t mmap_size = (ring_size + (page_size - 1)) & ~(page_size - 1);
572aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  ASSERT_GE(mmap_size, ring_size);
573aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
574aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  void* mmap_base = mmap(nullptr, mmap_size, PROT_READ | PROT_WRITE,
575aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang                         MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
576aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  ASSERT_NE(MAP_FAILED, mmap_base);
577aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
578aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  Ring ring = Ring::Create(mmap_base, mmap_size, record_count);
579aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  for (uint32_t i = 0; i < record_count; ++i) ring.Put(Record(FillChar(i)));
580aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
581aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  ASSERT_EQ(0, mprotect(mmap_base, mmap_size, PROT_READ));
582aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
583aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  {
584aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    Ring imported_ring;
585aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    bool import_ok;
586aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    std::tie(imported_ring, import_ok) = Ring::Import(mmap_base, mmap_size);
587aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_TRUE(import_ok);
588aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_EQ(ring.record_size(), imported_ring.record_size());
589aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_EQ(ring.record_count(), imported_ring.record_count());
590aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
591aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    uint32_t oldest_sequence = imported_ring.GetOldestSequence();
592aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    for (uint32_t i = 0; i < record_count; ++i) {
593aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      uint32_t sequence = oldest_sequence + i;
594aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      Record record;
595aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_TRUE(imported_ring.Get(&sequence, &record));
596aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_EQ(Record(FillChar(i)), record);
597aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    }
598aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  }
599aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
600aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  ASSERT_EQ(0, munmap(mmap_base, mmap_size));
601aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang}
602aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
603aacc1fceefd75e33908fa6feee2cf03688e09374Michael SpangTEST(BroadcastRingTest, ShouldDieIfPutReadonlyMmap) {
604aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using Ring = Dynamic_32_NxM::Ring;
605aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using Record = Ring::Record;
606aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
607aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  uint32_t record_count = Ring::Traits::MinCount();
608aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  size_t ring_size = Ring::MemorySize(record_count);
609aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
610aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  size_t page_size = sysconf(_SC_PAGESIZE);
611aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  size_t mmap_size = (ring_size + (page_size - 1)) & ~(page_size - 1);
612aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  ASSERT_GE(mmap_size, ring_size);
613aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
614aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  void* mmap_base = mmap(nullptr, mmap_size, PROT_READ | PROT_WRITE,
615aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang                         MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
616aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  ASSERT_NE(MAP_FAILED, mmap_base);
617aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
618aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  Ring ring = Ring::Create(mmap_base, mmap_size, record_count);
619aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  for (uint32_t i = 0; i < record_count; ++i) ring.Put(Record(FillChar(i)));
620aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
621aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  ASSERT_EQ(0, mprotect(mmap_base, mmap_size, PROT_READ));
622aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
623aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  EXPECT_DEATH_IF_SUPPORTED({ ring.Put(Record(7)); }, "");
624aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
625aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  ASSERT_EQ(0, munmap(mmap_base, mmap_size));
626aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang}
627aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
628aacc1fceefd75e33908fa6feee2cf03688e09374Michael SpangTEST(BroadcastRingTest, ShouldDieIfCreationMmapTooSmall) {
629aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using Ring = Dynamic_32_NxM::Ring;
630aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using Record = Ring::Record;
631aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
632aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  uint32_t record_count = Ring::Traits::MinCount();
633aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  size_t ring_size = Ring::MemorySize(record_count);
634aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  FakeMmap mmap(ring_size);
635aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
636aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  EXPECT_DEATH_IF_SUPPORTED({
637aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    Ring ring = Ring::Create(mmap.mmap(), ring_size - 1, record_count);
638aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  }, "");
639aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
640aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  Ring ring = Ring::Create(mmap.mmap(), ring_size, record_count);
641aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
642aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  ring.Put(Record(3));
643aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
644aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  {
645aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    uint32_t sequence = ring.GetNewestSequence();
646aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    Record record;
647aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_TRUE(ring.Get(&sequence, &record));
648aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_EQ(Record(3), record);
649aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  }
650aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang}
651aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
652aacc1fceefd75e33908fa6feee2cf03688e09374Michael SpangTEST(BroadcastRingTest, ShouldDieIfCreationMmapMisaligned) {
653aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using Ring = Static_8_8x1::Ring;
654aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using Record = Ring::Record;
655aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
656aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  constexpr int kAlign = Ring::mmap_alignment();
657aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  constexpr int kMisalign = kAlign / 2;
658aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  size_t ring_size = Ring::MemorySize();
659aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  std::unique_ptr<char[]> buf(new char[ring_size + kMisalign]);
660aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
661aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  EXPECT_DEATH_IF_SUPPORTED(
662aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      { Ring ring = Ring::Create(buf.get() + kMisalign, ring_size); }, "");
663aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
664aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  Ring ring = Ring::Create(buf.get(), ring_size);
665aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
666aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  ring.Put(Record(3));
667aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
668aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  {
669aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    uint32_t sequence = ring.GetNewestSequence();
670aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    Record record;
671aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_TRUE(ring.Get(&sequence, &record));
672aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    EXPECT_EQ(Record(3), record);
673aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  }
674aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang}
675aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
676aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangtemplate <typename Ring>
677aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangstd::unique_ptr<std::thread> CopyTask(std::atomic<bool>* quit, void* in_base,
678aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang                                      size_t in_size, void* out_base,
679aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang                                      size_t out_size) {
680aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  return std::unique_ptr<std::thread>(
681aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      new std::thread([quit, in_base, in_size, out_base, out_size]() {
682aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        using Record = typename Ring::Record;
683aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
684aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        bool import_ok;
685aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        Ring in_ring;
686aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        Ring out_ring;
687aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        std::tie(in_ring, import_ok) = Ring::Import(in_base, in_size);
688aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        ASSERT_TRUE(import_ok);
689aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        std::tie(out_ring, import_ok) = Ring::Import(out_base, out_size);
690aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        ASSERT_TRUE(import_ok);
691aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
692aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        uint32_t sequence = in_ring.GetOldestSequence();
693aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        while (!std::atomic_load_explicit(quit, std::memory_order_relaxed)) {
694aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang          Record record;
695aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang          if (in_ring.Get(&sequence, &record)) {
696aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang            out_ring.Put(record);
697aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang            sequence++;
698aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang          }
699aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        }
700aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      }));
701aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang}
702aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
703aacc1fceefd75e33908fa6feee2cf03688e09374Michael SpangTEST(BroadcastRingTest, ThreadedCopySingle) {
704aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using Ring = Dynamic_32_NxM::Ring;
705aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using Record = Ring::Record;
706aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  Ring in_ring;
707aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  auto in_mmap = CreateRing(&in_ring, Ring::Traits::MinCount());
708aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
709aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  Ring out_ring;
710aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  auto out_mmap = CreateRing(&out_ring, Ring::Traits::MinCount());
711aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
712aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  std::atomic<bool> quit(false);
713aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  std::unique_ptr<std::thread> copy_task = CopyTask<Ring>(
714aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      &quit, out_mmap.mmap(), out_mmap.size, in_mmap.mmap(), in_mmap.size);
715aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
716aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  const Record out_record(0x1c);
717aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  out_ring.Put(out_record);
718aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
719aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  uint32_t in_sequence = in_ring.GetOldestSequence();
720aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  Record in_record;
721aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  while (!in_ring.Get(&in_sequence, &in_record)) {
722aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    // Do nothing.
723aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  }
724aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
725aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  EXPECT_EQ(out_record, in_record);
726aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  std::atomic_store_explicit(&quit, true, std::memory_order_relaxed);
727aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  copy_task->join();
728aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang}
729aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
730aacc1fceefd75e33908fa6feee2cf03688e09374Michael SpangTEST(BroadcastRingTest, ThreadedCopyLossless) {
731aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using Ring = Dynamic_32_NxM::Ring;
732aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using Record = Ring::Record;
733aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  Ring in_ring;
734aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  auto in_mmap = CreateRing(&in_ring, Ring::Traits::MinCount());
735aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
736aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  Ring out_ring;
737aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  auto out_mmap = CreateRing(&out_ring, Ring::Traits::MinCount());
738aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
739aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  std::atomic<bool> quit(false);
740aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  std::unique_ptr<std::thread> copy_task = CopyTask<Ring>(
741aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      &quit, out_mmap.mmap(), out_mmap.size, in_mmap.mmap(), in_mmap.size);
742aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
743aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  constexpr uint32_t kRecordsToProcess = 10000;
744aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  uint32_t out_records = 0;
745aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  uint32_t in_records = 0;
746aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  uint32_t in_sequence = in_ring.GetNextSequence();
747aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  while (out_records < kRecordsToProcess || in_records < kRecordsToProcess) {
748aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    if (out_records < kRecordsToProcess &&
749aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        out_records - in_records < out_ring.record_count()) {
750aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      const Record out_record(FillChar(out_records));
751aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      out_ring.Put(out_record);
752aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      out_records++;
753aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    }
754aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
755aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    Record in_record;
756aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    while (in_ring.Get(&in_sequence, &in_record)) {
757aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_EQ(Record(FillChar(in_records)), in_record);
758aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      in_records++;
759aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      in_sequence++;
760aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    }
761aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  }
762aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
763aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  EXPECT_EQ(kRecordsToProcess, out_records);
764aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  EXPECT_EQ(kRecordsToProcess, in_records);
765aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
766aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  std::atomic_store_explicit(&quit, true, std::memory_order_relaxed);
767aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  copy_task->join();
768aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang}
769aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
770aacc1fceefd75e33908fa6feee2cf03688e09374Michael SpangTEST(BroadcastRingTest, ThreadedCopyLossy) {
771aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using Ring = Dynamic_32_NxM::Ring;
772aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using Record = Ring::Record;
773aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  Ring in_ring;
774aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  auto in_mmap = CreateRing(&in_ring, Ring::Traits::MinCount());
775aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
776aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  Ring out_ring;
777aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  auto out_mmap = CreateRing(&out_ring, Ring::Traits::MinCount());
778aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
779aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  std::atomic<bool> quit(false);
780aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  std::unique_ptr<std::thread> copy_task = CopyTask<Ring>(
781aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      &quit, out_mmap.mmap(), out_mmap.size, in_mmap.mmap(), in_mmap.size);
782aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
783aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  constexpr uint32_t kRecordsToProcess = 100000;
784aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  uint32_t out_records = 0;
785aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  uint32_t in_records = 0;
786aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  uint32_t in_sequence = in_ring.GetNextSequence();
787aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  while (out_records < kRecordsToProcess) {
788aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    const Record out_record(FillChar(out_records));
789aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    out_ring.Put(out_record);
790aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    out_records++;
791aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
792aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    Record in_record;
793aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    if (in_ring.GetNewest(&in_sequence, &in_record)) {
794aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      EXPECT_EQ(Record(in_record.v[0]), in_record);
795aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      in_records++;
796aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      in_sequence++;
797aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    }
798aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  }
799aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
800aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  EXPECT_EQ(kRecordsToProcess, out_records);
801aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  EXPECT_GE(kRecordsToProcess, in_records);
802aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
803aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  std::atomic_store_explicit(&quit, true, std::memory_order_relaxed);
804aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  copy_task->join();
805aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang}
806aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
807aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangtemplate <typename Ring>
808aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangstd::unique_ptr<std::thread> CheckFillTask(std::atomic<bool>* quit,
809aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang                                           void* in_base, size_t in_size) {
810aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  return std::unique_ptr<std::thread>(
811aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      new std::thread([quit, in_base, in_size]() {
812aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        using Record = typename Ring::Record;
813aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
814aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        bool import_ok;
815aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        Ring in_ring;
816aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        std::tie(in_ring, import_ok) = Ring::Import(in_base, in_size);
817aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        ASSERT_TRUE(import_ok);
818aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
819aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        uint32_t sequence = in_ring.GetOldestSequence();
820aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        while (!std::atomic_load_explicit(quit, std::memory_order_relaxed)) {
821aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang          Record record;
822aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang          if (in_ring.Get(&sequence, &record)) {
823aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang            ASSERT_EQ(Record(record.v[0]), record);
824aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang            sequence++;
825aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang          }
826aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        }
827aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      }));
828aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang}
829aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
830aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangtemplate <typename Ring>
831aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spangvoid ThreadedOverwriteTorture() {
832aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  using Record = typename Ring::Record;
833aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
834aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  // Maximize overwrites by having few records.
835aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  const int kMinRecordCount = 1;
836aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  const int kMaxRecordCount = 4;
837aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
838aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  for (int count = kMinRecordCount; count <= kMaxRecordCount; count *= 2) {
839aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    Ring out_ring;
840aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    auto out_mmap = CreateRing(&out_ring, count);
841aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
842aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    std::atomic<bool> quit(false);
843aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    std::unique_ptr<std::thread> check_task =
844aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang        CheckFillTask<Ring>(&quit, out_mmap.mmap(), out_mmap.size);
845aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
846aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    constexpr int kIterations = 10000;
847aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    for (int i = 0; i < kIterations; ++i) {
848aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      const Record record(FillChar(i));
849aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang      out_ring.Put(record);
850aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    }
851aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
852aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    std::atomic_store_explicit(&quit, true, std::memory_order_relaxed);
853aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang    check_task->join();
854aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  }
855aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang}
856aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
857aacc1fceefd75e33908fa6feee2cf03688e09374Michael SpangTEST(BroadcastRingTest, ThreadedOverwriteTortureSmall) {
858aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  ThreadedOverwriteTorture<Dynamic_16_NxM_1plus0::Ring>();
859aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang}
860aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
861aacc1fceefd75e33908fa6feee2cf03688e09374Michael SpangTEST(BroadcastRingTest, ThreadedOverwriteTortureLarge) {
862aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang  ThreadedOverwriteTorture<Dynamic_256_NxM_1plus0::Ring>();
863aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang}
864aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang
865aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang} // namespace dvr
866aacc1fceefd75e33908fa6feee2cf03688e09374Michael Spang} // namespace android
867