proxygen
ProtocolTest.h
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 #pragma once
10 
11 #include <gmock/gmock.h>
12 #include <gtest/gtest.h>
13 
14 #include <fizz/protocol/Actions.h>
17 #include <fizz/record/test/Mocks.h>
18 
19 namespace fizz {
20 namespace test {
21 
23 
24 template <typename SM, typename Actions>
25 class ProtocolTest : public testing::Test {
26  protected:
28 
29  template <typename... Args>
30  void expectActions(const Actions& actions) {
31  EXPECT_EQ(getNumActions<Args...>(actions, true), actions.size());
32  }
33 
34  template <typename T>
36  for (auto& action : actions) {
37  try {
38  return std::move(boost::get<T>(action));
39  } catch (const boost::bad_get&) {
40  }
41  }
42  throw std::runtime_error("did not find expected action");
43  }
44 
45  template <typename T>
47  EXPECT_EQ(actions.size(), 1);
48  return expectAction<T>(actions);
49  }
50 
52  for (auto& action : actions) {
53  try {
54  boost::get<MutateState>(action)(state_);
55  } catch (const boost::bad_get&) {
56  }
57  }
58  }
59 
60  template <typename T>
61  uint32_t getNumActions(const Actions& actions, bool expectNonZero) {
62  uint32_t count = 0;
63  for (const auto& action : actions) {
64  try {
65  boost::get<T>(action);
66  count++;
67  } catch (const boost::bad_get&) {
68  }
69  }
70  if (expectNonZero) {
71  EXPECT_NE(count, 0);
72  }
73  return count;
74  }
75 
76  template <typename T1, typename T2, typename... Args>
77  uint32_t getNumActions(const Actions& actions, bool expectNonZero) {
78  return getNumActions<T1>(actions, expectNonZero) +
79  getNumActions<T2, Args...>(actions, expectNonZero);
80  }
81 
83  auto error = expectAction<ReportError>(actions);
84  }
85 
86  template <typename ExceptionType>
90  std::string msg = "") {
91  if (alert) {
92  expectActions<MutateState, ReportError, WriteToSocket>(actions);
93  auto write = expectAction<WriteToSocket>(actions);
94  Alert a;
95  a.description = *alert;
96  auto buf = folly::IOBuf::copyBuffer("alert");
97  buf->prependChain(encode(std::move(a)));
98  EXPECT_TRUE(folly::IOBufEqualTo()(write.contents[0].data, buf));
99  } else {
100  expectActions<MutateState, ReportError>(actions);
101  }
102  auto error = expectAction<ReportError>(actions);
103  auto ex = error.error.template get_exception<ExceptionType>();
104  EXPECT_NE(ex, nullptr);
105  EXPECT_THAT(error.error.what().toStdString(), HasSubstr(msg));
106  processStateMutations(actions);
108  EXPECT_EQ(state_.readRecordLayer(), nullptr);
109  EXPECT_EQ(state_.writeRecordLayer(), nullptr);
110  }
111 
112  void expectAeadCreation(std::map<std::string, MockAead**> keys) {
113  EXPECT_CALL(*factory_, makeAead(_)).WillRepeatedly(InvokeWithoutArgs([=]() {
114  auto ret = std::make_unique<MockAead>();
115  EXPECT_CALL(*ret, _setKey(_))
116  .WillOnce(Invoke([keys, ptr = ret.get()](TrafficKey& key) {
117  *keys.at(key.key->clone()->moveToFbString().toStdString()) = ptr;
118  }));
119  return ret;
120  }));
121  }
122 
123  void expectAeadCreation(MockAead** clientAead, MockAead** serverAead) {
124  return expectAeadCreation(
125  {{"clientkey", clientAead}, {"serverkey", serverAead}});
126  }
127 
129  MockEncryptedReadRecordLayer** recordLayer,
130  MockAead** readAead,
131  folly::ByteRange expectedBaseSecret,
132  folly::Optional<bool> skipFailedDecryption = folly::none,
133  Sequence* s = nullptr) {
134  EXPECT_CALL(*factory_, makeEncryptedReadRecordLayer(_))
135  .InSequence(s ? *s : Sequence())
136  .WillOnce(Invoke([=](EncryptionLevel encryptionLevel) {
137  auto ret =
138  std::make_unique<MockEncryptedReadRecordLayer>(encryptionLevel);
139  *recordLayer = ret.get();
140  EXPECT_CALL(*ret, _setAead(_, _))
141  .WillOnce(Invoke([=](folly::ByteRange baseSecret, Aead* aead) {
142  EXPECT_TRUE(baseSecret == expectedBaseSecret);
143  EXPECT_EQ(aead, *readAead);
144  }));
145  if (skipFailedDecryption.hasValue()) {
146  EXPECT_CALL(
147  *ret, setSkipFailedDecryption(skipFailedDecryption.value()));
148  }
149  return ret;
150  }));
151  }
152 
154  MockEncryptedWriteRecordLayer** recordLayer,
155  MockAead** writeAead,
156  folly::ByteRange expectedBaseSecret,
158  expectedWrite = nullptr,
159  Sequence* s = nullptr) {
160  EXPECT_CALL(*factory_, makeEncryptedWriteRecordLayer(_))
161  .InSequence(s ? *s : Sequence())
162  .WillOnce(Invoke([=](EncryptionLevel encryptionLevel) {
163  auto ret =
164  std::make_unique<MockEncryptedWriteRecordLayer>(encryptionLevel);
165  ret->setDefaults();
166  *recordLayer = ret.get();
167  EXPECT_CALL(*ret, _setAead(_, _))
168  .WillOnce(Invoke([=](folly::ByteRange baseSecret, Aead* aead) {
169  EXPECT_TRUE(baseSecret == expectedBaseSecret);
170  EXPECT_EQ(aead, *writeAead);
171  }));
172  if (expectedWrite) {
173  EXPECT_CALL(*ret, _write(_))
174  .WillOnce(
175  Invoke([writeFunc = std::move(expectedWrite),
176  writeRecord = *recordLayer](auto& msg) mutable {
177  return writeFunc(msg, writeRecord);
178  }));
179  }
180  return ret;
181  }));
182  }
183 
184  typename SM::State state_;
186 };
187 } // namespace test
188 } // namespace fizz
void * ptr
#define T(v)
Definition: http_parser.c:233
void write(const T &in, folly::io::Appender &appender)
Definition: Types-inl.h:112
void expectAeadCreation(std::map< std::string, MockAead ** > keys)
Definition: ProtocolTest.h:112
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
internal::ArgsMatcher< InnerMatcher > Args(const InnerMatcher &matcher)
void expectAeadCreation(MockAead **clientAead, MockAead **serverAead)
Definition: ProtocolTest.h:123
requires And< SemiMovable< VN >... > &&SemiMovable< E > auto error(E e)
Definition: error.h:48
PolymorphicAction< internal::InvokeWithoutArgsAction< FunctionImpl > > InvokeWithoutArgs(FunctionImpl function_impl)
ProtocolVersion
Definition: Types.h:24
EncryptionLevel
Definition: Types.h:29
State
See Core for details.
Definition: Core.h:43
void expectExceptionType(Actions &actions)
Definition: ProtocolTest.h:82
PolymorphicMatcher< internal::HasSubstrMatcher< internal::string > > HasSubstr(const internal::string &substring)
PolymorphicAction< internal::InvokeAction< FunctionImpl > > Invoke(FunctionImpl function_impl)
Definition: Actions.h:16
char a
error_stage Error
Actions actions(Args &&...act)
Definition: Actions.h:86
int * count
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
#define EXPECT_THAT(value, matcher)
void expectEncryptedWriteRecordLayerCreation(MockEncryptedWriteRecordLayer **recordLayer, MockAead **writeAead, folly::ByteRange expectedBaseSecret, std::function< TLSContent(TLSMessage &, MockEncryptedWriteRecordLayer *)> expectedWrite=nullptr, Sequence *s=nullptr)
Definition: ProtocolTest.h:153
std::vector< Action > Actions
Buf encode(TokenBindingMessage &&message)
Definition: Types.cpp:124
const char * string
Definition: Conv.cpp:212
uint32_t getNumActions(const Actions &actions, bool expectNonZero)
Definition: ProtocolTest.h:77
#define EXPECT_NE(val1, val2)
Definition: gtest.h:1926
static set< string > s
void expectError(Actions &actions, folly::Optional< AlertDescription > alert, std::string msg="")
Definition: ProtocolTest.h:87
void expectEncryptedReadRecordLayerCreation(MockEncryptedReadRecordLayer **recordLayer, MockAead **readAead, folly::ByteRange expectedBaseSecret, folly::Optional< bool > skipFailedDecryption=folly::none, Sequence *s=nullptr)
Definition: ProtocolTest.h:128
#define EXPECT_CALL(obj, call)
const internal::AnythingMatcher _
T expectSingleAction(Actions actions)
Definition: ProtocolTest.h:46
void expectActions(const Actions &actions)
Definition: ProtocolTest.h:30
T expectAction(Actions &actions)
Definition: ProtocolTest.h:35
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
void processStateMutations(Actions &actions)
Definition: ProtocolTest.h:51
constexpr ProtocolVersion TestProtocolVersion
Definition: ProtocolTest.h:22
constexpr None none
Definition: Optional.h:87
uint32_t getNumActions(const Actions &actions, bool expectNonZero)
Definition: ProtocolTest.h:61
action
Definition: upload.py:393