proxygen
AsyncFizzServerTest.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018-present, Facebook, Inc.
3  * All rights reserved.
4  *
5  * This source code is licensed under the BSD-style license found in the
6  * LICENSE file in the root directory of this source tree.
7  */
8 
9 #include <gmock/gmock.h>
10 #include <gtest/gtest.h>
11 
13 
15 #include <fizz/server/test/Mocks.h>
17 
18 namespace fizz {
19 namespace server {
20 namespace test {
21 
22 using namespace fizz::extensions;
23 using namespace folly;
24 using namespace folly::test;
25 using namespace testing;
26 
27 template <typename... Args>
29  return fizz::server::detail::actions(std::forward<Args>(act)...);
30 }
31 
33  public:
35  instance = this;
36  }
38 };
40 
41 class AsyncFizzServerTest : public Test {
42  public:
43  void SetUp() override {
44  context_ = std::make_shared<FizzServerContext>();
46  auto transport = AsyncTransportWrapper::UniquePtr(socket_);
48  std::move(transport),
49  context_,
50  std::make_shared<MockServerExtensions>()));
52  ON_CALL(*socket_, good()).WillByDefault(Return(true));
53  ON_CALL(readCallback_, isBufferMovable_()).WillByDefault(Return(true));
54  }
55 
56  protected:
58  EXPECT_CALL(*socket_, setReadCB(_))
59  .WillRepeatedly(SaveArg<0>(&socketReadCallback_));
60  }
61 
62  void expectAppClose() {
63  EXPECT_CALL(*machine_, _processAppClose(_))
64  .WillOnce(InvokeWithoutArgs([]() {
66  TLSContent record;
69  record.data = IOBuf::copyBuffer("closenotify");
70  write.contents.emplace_back(std::move(record));
71  return detail::actions(
72  [](State& newState) { newState.state() = StateEnum::Error; },
73  std::move(write));
74  }));
75  }
76 
77  void accept() {
78  expectTransportReadCallback();
79  EXPECT_CALL(*socket_, getEventBase()).WillOnce(Return(&evb_));
80  EXPECT_CALL(*machine_, _processAccept(_, &evb_, _, _))
81  .WillOnce(InvokeWithoutArgs([]() { return actions(); }));
82  server_->accept(&handshakeCallback_);
83  }
84 
86  std::shared_ptr<const Cert> clientCert = nullptr,
87  std::shared_ptr<const Cert> serverCert = nullptr) {
88  EXPECT_CALL(*machine_, _processSocketData(_, _))
89  .WillOnce(InvokeWithoutArgs([clientCert,
90  serverCert,
91  cipher = negotiatedCipher_,
92  protocolVersion = protocolVersion_]() {
93  auto addExporterToState = [=](State& newState) {
94  auto exporterMaster =
95  folly::IOBuf::copyBuffer("12345678901234567890123456789012");
96  newState.exporterMasterSecret() = std::move(exporterMaster);
97  newState.cipher() = cipher;
98  newState.version() = protocolVersion;
99  newState.clientCert() = clientCert;
100  newState.serverCert() = serverCert;
101  };
102  return actions(
103  std::move(addExporterToState),
105  WaitForData());
106  }));
107  socketReadCallback_->readBufferAvailable(IOBuf::copyBuffer("ClientHello"));
108  }
109 
111  accept();
112  EXPECT_CALL(handshakeCallback_, _fizzHandshakeSuccess());
113  fullHandshakeSuccess();
114  }
115 
117  std::shared_ptr<FizzServerContext> context_;
127 };
128 
129 MATCHER_P(BufMatches, expected, "") {
131  return eq(*arg, *expected);
132 }
133 
135  accept();
136 }
137 
138 TEST_F(AsyncFizzServerTest, TestReadSingle) {
139  accept();
140  EXPECT_CALL(*machine_, _processSocketData(_, _))
141  .WillOnce(InvokeWithoutArgs([]() { return actions(WaitForData()); }));
142  socketReadCallback_->readBufferAvailable(IOBuf::copyBuffer("ClientHello"));
143 }
144 
145 TEST_F(AsyncFizzServerTest, TestReadMulti) {
146  accept();
147  EXPECT_CALL(*machine_, _processSocketData(_, _))
148  .WillOnce(InvokeWithoutArgs([]() { return actions(); }))
149  .WillOnce(InvokeWithoutArgs([]() { return actions(WaitForData()); }));
150  socketReadCallback_->readBufferAvailable(IOBuf::copyBuffer("ClientHello"));
151 }
152 
154  accept();
155  EXPECT_CALL(*machine_, _processAppWrite(_, _))
156  .WillOnce(InvokeWithoutArgs([]() { return actions(); }));
157  server_->writeChain(nullptr, IOBuf::copyBuffer("HTTP GET"));
158 }
159 
160 TEST_F(AsyncFizzServerTest, TestWriteMulti) {
161  accept();
162  EXPECT_CALL(*machine_, _processAppWrite(_, _))
163  .WillOnce(InvokeWithoutArgs([]() { return actions(); }));
164  server_->writeChain(nullptr, IOBuf::copyBuffer("HTTP GET"));
165  EXPECT_CALL(*machine_, _processAppWrite(_, _))
166  .WillOnce(InvokeWithoutArgs([]() { return actions(); }));
167  server_->writeChain(nullptr, IOBuf::copyBuffer("HTTP POST"));
168 }
169 
170 TEST_F(AsyncFizzServerTest, TestWriteErrorState) {
171  accept();
172  ON_CALL(*socket_, error()).WillByDefault(Return(true));
173  EXPECT_CALL(writeCallback_, writeErr_(0, _));
174  server_->writeChain(&writeCallback_, IOBuf::copyBuffer("test"));
175 }
176 
177 TEST_F(AsyncFizzServerTest, TestHandshake) {
178  completeHandshake();
179 }
180 
181 TEST_F(AsyncFizzServerTest, TestExporterAPISimple) {
182  completeHandshake();
183  server_->getEkm(kTokenBindingExporterLabel, nullptr, 32);
184 }
185 
186 TEST_F(AsyncFizzServerTest, TestExporterAPIIncompleteHandshake) {
187  EXPECT_THROW(
188  server_->getEkm(kTokenBindingExporterLabel, nullptr, 32),
189  std::runtime_error);
190 }
191 
192 TEST_F(AsyncFizzServerTest, TestHandshakeError) {
193  accept();
194  EXPECT_CALL(*machine_, _processSocketData(_, _))
195  .WillOnce(InvokeWithoutArgs(
196  []() { return actions(ReportError("unit test"), WaitForData()); }));
197  EXPECT_CALL(handshakeCallback_, _fizzHandshakeError(_));
198  socketReadCallback_->readBufferAvailable(IOBuf::copyBuffer("ClientHello"));
199 }
200 
201 TEST_F(AsyncFizzServerTest, TestDeliverAppData) {
202  completeHandshake();
203  server_->setReadCB(&readCallback_);
204  EXPECT_CALL(*machine_, _processSocketData(_, _))
205  .WillOnce(InvokeWithoutArgs([]() {
207  }));
208  EXPECT_CALL(readCallback_, readBufferAvailable_(_));
209  socketReadCallback_->readBufferAvailable(IOBuf::copyBuffer("ClientHello"));
210 }
211 
212 TEST_F(AsyncFizzServerTest, TestWriteToSocket) {
213  completeHandshake();
214  server_->setReadCB(&readCallback_);
215  EXPECT_CALL(*machine_, _processSocketData(_, _))
216  .WillOnce(InvokeWithoutArgs([]() {
218  TLSContent record;
221  record.data = IOBuf::copyBuffer("XYZ");
222  write.contents.emplace_back(std::move(record));
223  return actions(std::move(write), WaitForData());
224  }));
225  EXPECT_CALL(*socket_, writeChain(_, _, _));
226  socketReadCallback_->readBufferAvailable(IOBuf::copyBuffer("ClientHello"));
227 }
228 
229 TEST_F(AsyncFizzServerTest, TestMutateState) {
230  completeHandshake();
231  server_->setReadCB(&readCallback_);
232  uint32_t numTimesRun = 0;
233  EXPECT_CALL(*machine_, _processSocketData(_, _))
234  .WillOnce(InvokeWithoutArgs([&numTimesRun]() {
235  return actions(
236  [&numTimesRun](State& newState) {
237  numTimesRun++;
238  newState.state() = StateEnum::Error;
239  },
240  WaitForData());
241  }));
242  socketReadCallback_->readBufferAvailable(IOBuf::copyBuffer("ClientHello"));
243  EXPECT_EQ(server_->getState().state(), StateEnum::Error);
244  EXPECT_EQ(numTimesRun, 1);
245 }
246 
247 TEST_F(AsyncFizzServerTest, TestAttemptVersionFallback) {
248  accept();
249  EXPECT_CALL(*machine_, _processSocketData(_, _))
250  .WillOnce(InvokeWithoutArgs([]() {
251  return actions(
252  [](State& newState) { newState.state() = StateEnum::Error; },
253  AttemptVersionFallback{IOBuf::copyBuffer("ClientHello")});
254  }));
255  EXPECT_CALL(handshakeCallback_, _fizzHandshakeAttemptFallback(_))
256  .WillOnce(Invoke([&](std::unique_ptr<IOBuf>& clientHello) {
257  // The mock machine does not move the read buffer so there will be a 2nd
258  // ClientHello.
260  clientHello, IOBuf::copyBuffer("ClientHelloClientHello")));
261  server_.reset();
262  }));
263  socketReadCallback_->readBufferAvailable(IOBuf::copyBuffer("ClientHello"));
264 }
265 
266 TEST_F(AsyncFizzServerTest, TestDeleteAsyncEvent) {
267  accept();
268  Promise<Actions> p1;
269  EXPECT_CALL(*machine_, _processSocketData(_, _))
270  .WillOnce(
271  InvokeWithoutArgs([&p1]() { return AsyncActions(p1.getFuture()); }));
272  socketReadCallback_->readBufferAvailable(IOBuf::copyBuffer("ClientHello"));
273  server_.reset();
274  Promise<Actions> p2;
275  EXPECT_CALL(*machine_, _processSocketData(_, _))
276  .WillOnce(
277  InvokeWithoutArgs([&p2]() { return AsyncActions(p2.getFuture()); }));
280 }
281 
282 TEST_F(AsyncFizzServerTest, TestCloseHandshake) {
283  accept();
284  expectAppClose();
285  EXPECT_CALL(handshakeCallback_, _fizzHandshakeError(_));
286  EXPECT_CALL(*socket_, closeNow()).Times(AtLeast(1));
287  server_->closeNow();
288 }
289 
290 TEST_F(AsyncFizzServerTest, TestCloseNowInFlightAction) {
291  completeHandshake();
292  server_->setReadCB(&readCallback_);
294  EXPECT_CALL(*machine_, _processSocketData(_, _))
295  .WillOnce(
296  InvokeWithoutArgs([&p]() { return AsyncActions(p.getFuture()); }));
297  socketReadCallback_->readBufferAvailable(IOBuf::copyBuffer("Data"));
298  server_->writeChain(&writeCallback_, IOBuf::copyBuffer("queued write"));
299  EXPECT_CALL(writeCallback_, writeErr_(0, _));
300  EXPECT_CALL(readCallback_, readEOF_());
301  EXPECT_CALL(*socket_, closeNow()).Times(AtLeast(1));
302  server_->closeNow();
304 }
305 
306 TEST_F(AsyncFizzServerTest, TestCloseInFlightAction) {
307  completeHandshake();
308  server_->setReadCB(&readCallback_);
310  EXPECT_CALL(*machine_, _processSocketData(_, _))
311  .WillOnce(
312  InvokeWithoutArgs([&p]() { return AsyncActions(p.getFuture()); }));
313  socketReadCallback_->readBufferAvailable(IOBuf::copyBuffer("Data"));
314  server_->writeChain(&writeCallback_, IOBuf::copyBuffer("queued write"));
315  server_->close();
316 
317  EXPECT_CALL(*machine_, _processAppWrite(_, _))
318  .WillOnce(InvokeWithoutArgs([]() { return actions(); }));
319  expectAppClose();
321 }
322 
323 TEST_F(AsyncFizzServerTest, TestIsDetachable) {
324  completeHandshake();
325  AsyncTransportWrapper::ReadCallback* readCb = socketReadCallback_;
326  ON_CALL(*socket_, isDetachable()).WillByDefault(Return(false));
327  EXPECT_FALSE(server_->isDetachable());
328  ON_CALL(*socket_, isDetachable()).WillByDefault(Return(true));
329  EXPECT_TRUE(server_->isDetachable());
331 
332  EXPECT_CALL(*machine_, _processSocketData(_, _))
333  .WillOnce(
334  InvokeWithoutArgs([&p]() { return AsyncActions(p.getFuture()); }));
335  socket_->setReadCB(readCb);
336  socketReadCallback_->readBufferAvailable(IOBuf::copyBuffer("Data"));
337  EXPECT_FALSE(server_->isDetachable());
338  p.setValue(detail::actions(WaitForData()));
339  EXPECT_TRUE(server_->isDetachable());
340 }
341 
342 TEST_F(AsyncFizzServerTest, TestConnecting) {
343  ON_CALL(*socket_, connecting()).WillByDefault(Return(true));
344  EXPECT_TRUE(server_->connecting());
345  ON_CALL(*socket_, connecting()).WillByDefault(Return(false));
346  accept();
347  EXPECT_TRUE(server_->connecting());
348  EXPECT_CALL(*machine_, _processSocketData(_, _))
349  .WillOnce(InvokeWithoutArgs(
350  []() { return actions(ReportHandshakeSuccess(), WaitForData()); }));
351  EXPECT_CALL(handshakeCallback_, _fizzHandshakeSuccess());
352  socketReadCallback_->readBufferAvailable(IOBuf::copyBuffer("ClientHello"));
353  EXPECT_FALSE(server_->connecting());
354 }
355 
356 TEST_F(AsyncFizzServerTest, TestGoodSocket) {
357  accept();
358  ON_CALL(*socket_, good()).WillByDefault(Return(true));
359  EXPECT_TRUE(server_->good());
360  ON_CALL(*socket_, good()).WillByDefault(Return(false));
361  EXPECT_FALSE(server_->good());
362 }
363 
364 TEST_F(AsyncFizzServerTest, TestGoodState) {
365  completeHandshake();
366  ON_CALL(*socket_, good()).WillByDefault(Return(true));
367  EXPECT_TRUE(server_->good());
368  EXPECT_CALL(*machine_, _processSocketData(_, _))
369  .WillOnce(InvokeWithoutArgs([]() {
370  return actions(
371  [](State& newState) { newState.state() = StateEnum::Error; });
372  }));
373  socketReadCallback_->readBufferAvailable(IOBuf::copyBuffer("Data"));
374  EXPECT_FALSE(server_->good());
375 }
376 
377 TEST_F(AsyncFizzServerTest, TestEarlySuccess) {
378  accept();
379  EXPECT_CALL(*machine_, _processSocketData(_, _))
380  .WillOnce(InvokeWithoutArgs([]() {
382  }));
383  EXPECT_CALL(handshakeCallback_, _fizzHandshakeSuccess());
384  socketReadCallback_->readBufferAvailable(IOBuf::copyBuffer("ClientHello"));
385 
386  fullHandshakeSuccess();
387 }
388 
389 TEST_F(AsyncFizzServerTest, TestErrorStopsActions) {
390  completeHandshake();
391  server_->setReadCB(&readCallback_);
392  EXPECT_CALL(*machine_, _processSocketData(_, _))
393  .WillOnce(InvokeWithoutArgs(
394  []() { return actions(ReportError("unit test")); }));
395  EXPECT_FALSE(server_->error());
396  socketReadCallback_->readBufferAvailable(IOBuf::copyBuffer("Data"));
397  EXPECT_TRUE(server_->error());
398 }
399 
400 TEST_F(AsyncFizzServerTest, TestGetCertsNone) {
401  completeHandshake();
402  EXPECT_EQ(server_->getSelfCert(), nullptr);
403  EXPECT_EQ(server_->getPeerCert(), nullptr);
404 }
405 
406 TEST_F(AsyncFizzServerTest, TestGetCerts) {
407  auto clientCert = std::make_shared<MockCert>();
408  auto serverCert = std::make_shared<MockCert>();
409  accept();
410  EXPECT_CALL(handshakeCallback_, _fizzHandshakeSuccess());
411  fullHandshakeSuccess(clientCert, serverCert);
412  EXPECT_CALL(*serverCert, getX509());
413  EXPECT_EQ(server_->getSelfCert(), nullptr);
414  EXPECT_CALL(*clientCert, getX509());
415  EXPECT_EQ(server_->getPeerCert(), nullptr);
416 }
417 } // namespace test
418 } // namespace server
419 } // namespace fizz
constexpr folly::StringPiece kTokenBindingExporterLabel
Definition: Types.h:19
void write(const T &in, folly::io::Appender &appender)
Definition: Types-inl.h:112
GTEST_API_ Cardinality AtLeast(int n)
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:1843
Actions actions(Args &&...act)
Definition: Actions.h:57
StateEnum state() const
Definition: State.h:69
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
MockServerStateMachineInstance * machine_
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
folly::small_vector< TLSContent, 4 > contents
Definition: Actions.h:41
EventBase * getEventBase()
boost::variant< Actions, folly::Future< Actions >> AsyncActions
Definition: Actions.h:52
CipherSuite
Definition: Types.h:153
internal::ArgsMatcher< InnerMatcher > Args(const InnerMatcher &matcher)
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
requires And< SemiMovable< VN >... > &&SemiMovable< E > auto error(E e)
Definition: error.h:48
PolymorphicAction< internal::InvokeWithoutArgsAction< FunctionImpl > > InvokeWithoutArgs(FunctionImpl function_impl)
static MockServerStateMachineInstance * instance
CipherSuite cipher
ProtocolVersion
Definition: Types.h:24
std::unique_ptr< AsyncTransportWrapper, Destructor > UniquePtr
EventBase * evb_
AsyncActions actions(Args &&...act)
PolymorphicAction< internal::InvokeAction< FunctionImpl > > Invoke(FunctionImpl function_impl)
MATCHER_P(BufMatches, expected,"")
std::shared_ptr< FizzServerContext > context_
AsyncServerSocket::UniquePtr socket_
Future< T > getFuture()
Definition: Promise-inl.h:97
EncryptionLevel encryptionLevel
Definition: RecordLayer.h:21
Definition: Actions.h:16
void fullHandshakeSuccess(std::shared_ptr< const Cert > clientCert=nullptr, std::shared_ptr< const Cert > serverCert=nullptr)
MockHandshakeCallbackT< MockServerStateMachineInstance > handshakeCallback_
std::shared_ptr< const Cert > serverCert
AsyncTransportWrapper::ReadCallback * socketReadCallback_
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
std::enable_if< std::is_same< Unit, B >::value, void >::type setValue()
Definition: Promise.h:326
#define ON_CALL(obj, call)
std::unique_ptr< AsyncFizzServerT, folly::DelayedDestruction::Destructor > UniquePtr
AsyncFizzServerT< MockServerStateMachineInstance >::UniquePtr server_
ContentType contentType
Definition: RecordLayer.h:20
std::shared_ptr< const Cert > clientCert
#define EXPECT_CALL(obj, call)
const internal::AnythingMatcher _
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
static std::unique_ptr< IOBuf > copyBuffer(const void *buf, std::size_t size, std::size_t headroom=0, std::size_t minTailroom=0)
Definition: IOBuf.h:1587
TEST_F(AeadCookieCipherTest, TestGetRetry)
internal::ReturnAction< R > Return(R value)
NetworkSocket accept(NetworkSocket s, sockaddr *addr, socklen_t *addrlen)
Definition: NetOps.cpp:71