xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/quic_connection_context_test.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2021 The Chromium Authors. All rights reserved.
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 "quiche/quic/core/quic_connection_context.h"
6 
7 #include "quiche/quic/platform/api/quic_test.h"
8 #include "quiche/quic/platform/api/quic_thread.h"
9 
10 using testing::ElementsAre;
11 
12 namespace quic::test {
13 namespace {
14 
15 class TraceCollector : public QuicConnectionTracer {
16  public:
17   ~TraceCollector() override = default;
18 
PrintLiteral(const char * literal)19   void PrintLiteral(const char* literal) override { trace_.push_back(literal); }
20 
PrintString(absl::string_view s)21   void PrintString(absl::string_view s) override {
22     trace_.push_back(std::string(s));
23   }
24 
trace() const25   const std::vector<std::string>& trace() const { return trace_; }
26 
27  private:
28   std::vector<std::string> trace_;
29 };
30 
31 struct FakeConnection {
FakeConnectionquic::test::__anon99a72df40111::FakeConnection32   FakeConnection() { context.tracer = std::make_unique<TraceCollector>(); }
33 
tracequic::test::__anon99a72df40111::FakeConnection34   const std::vector<std::string>& trace() const {
35     return static_cast<const TraceCollector*>(context.tracer.get())->trace();
36   }
37 
38   QuicConnectionContext context;
39 };
40 
SimpleSwitch()41 void SimpleSwitch() {
42   FakeConnection connection;
43 
44   // These should be ignored since current context is nullptr.
45   EXPECT_EQ(QuicConnectionContext::Current(), nullptr);
46   QUIC_TRACELITERAL("before switch: literal");
47   QUIC_TRACESTRING(std::string("before switch: string"));
48   QUIC_TRACEPRINTF("%s: %s", "before switch", "printf");
49 
50   {
51     QuicConnectionContextSwitcher switcher(&connection.context);
52     QUIC_TRACELITERAL("literal");
53     QUIC_TRACESTRING(std::string("string"));
54     QUIC_TRACEPRINTF("%s", "printf");
55   }
56 
57   EXPECT_EQ(QuicConnectionContext::Current(), nullptr);
58   QUIC_TRACELITERAL("after switch: literal");
59   QUIC_TRACESTRING(std::string("after switch: string"));
60   QUIC_TRACEPRINTF("%s: %s", "after switch", "printf");
61 
62   EXPECT_THAT(connection.trace(), ElementsAre("literal", "string", "printf"));
63 }
64 
NestedSwitch()65 void NestedSwitch() {
66   FakeConnection outer, inner;
67 
68   {
69     QuicConnectionContextSwitcher switcher(&outer.context);
70     QUIC_TRACELITERAL("outer literal 0");
71     QUIC_TRACESTRING(std::string("outer string 0"));
72     QUIC_TRACEPRINTF("%s %s %d", "outer", "printf", 0);
73 
74     {
75       QuicConnectionContextSwitcher nested_switcher(&inner.context);
76       QUIC_TRACELITERAL("inner literal");
77       QUIC_TRACESTRING(std::string("inner string"));
78       QUIC_TRACEPRINTF("%s %s", "inner", "printf");
79     }
80 
81     QUIC_TRACELITERAL("outer literal 1");
82     QUIC_TRACESTRING(std::string("outer string 1"));
83     QUIC_TRACEPRINTF("%s %s %d", "outer", "printf", 1);
84   }
85 
86   EXPECT_THAT(outer.trace(), ElementsAre("outer literal 0", "outer string 0",
87                                          "outer printf 0", "outer literal 1",
88                                          "outer string 1", "outer printf 1"));
89 
90   EXPECT_THAT(inner.trace(),
91               ElementsAre("inner literal", "inner string", "inner printf"));
92 }
93 
AlternatingSwitch()94 void AlternatingSwitch() {
95   FakeConnection zero, one, two;
96   for (int i = 0; i < 15; ++i) {
97     FakeConnection* connection =
98         ((i % 3) == 0) ? &zero : (((i % 3) == 1) ? &one : &two);
99 
100     QuicConnectionContextSwitcher switcher(&connection->context);
101     QUIC_TRACEPRINTF("%d", i);
102   }
103 
104   EXPECT_THAT(zero.trace(), ElementsAre("0", "3", "6", "9", "12"));
105   EXPECT_THAT(one.trace(), ElementsAre("1", "4", "7", "10", "13"));
106   EXPECT_THAT(two.trace(), ElementsAre("2", "5", "8", "11", "14"));
107 }
108 
109 typedef void (*ThreadFunction)();
110 
111 template <ThreadFunction func>
112 class TestThread : public QuicThread {
113  public:
TestThread()114   TestThread() : QuicThread("TestThread") {}
115   ~TestThread() override = default;
116 
117  protected:
Run()118   void Run() override { func(); }
119 };
120 
121 template <ThreadFunction func>
RunInThreads(size_t n_threads)122 void RunInThreads(size_t n_threads) {
123   using ThreadType = TestThread<func>;
124   std::vector<ThreadType> threads(n_threads);
125 
126   for (ThreadType& t : threads) {
127     t.Start();
128   }
129 
130   for (ThreadType& t : threads) {
131     t.Join();
132   }
133 }
134 
135 class QuicConnectionContextTest : public QuicTest {
136  protected:
137 };
138 
TEST_F(QuicConnectionContextTest,NullTracerOK)139 TEST_F(QuicConnectionContextTest, NullTracerOK) {
140   FakeConnection connection;
141   std::unique_ptr<QuicConnectionTracer> tracer;
142 
143   {
144     QuicConnectionContextSwitcher switcher(&connection.context);
145     QUIC_TRACELITERAL("msg 1 recorded");
146   }
147 
148   connection.context.tracer.swap(tracer);
149 
150   {
151     QuicConnectionContextSwitcher switcher(&connection.context);
152     // Should be a no-op since connection.context.tracer is nullptr.
153     QUIC_TRACELITERAL("msg 2 ignored");
154   }
155 
156   EXPECT_THAT(static_cast<TraceCollector*>(tracer.get())->trace(),
157               ElementsAre("msg 1 recorded"));
158 }
159 
TEST_F(QuicConnectionContextTest,TestSimpleSwitch)160 TEST_F(QuicConnectionContextTest, TestSimpleSwitch) {
161   RunInThreads<SimpleSwitch>(10);
162 }
163 
TEST_F(QuicConnectionContextTest,TestNestedSwitch)164 TEST_F(QuicConnectionContextTest, TestNestedSwitch) {
165   RunInThreads<NestedSwitch>(10);
166 }
167 
TEST_F(QuicConnectionContextTest,TestAlternatingSwitch)168 TEST_F(QuicConnectionContextTest, TestAlternatingSwitch) {
169   RunInThreads<AlternatingSwitch>(10);
170 }
171 
172 }  // namespace
173 }  // namespace quic::test
174