• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 #pragma once
15 
16 #include <array>
17 #include <cstddef>
18 #include <optional>
19 
20 #include "pw_bytes/span.h"
21 #include "pw_containers/to_array.h"
22 #include "pw_i2c/initiator.h"
23 
24 namespace pw::i2c {
25 
26 // Represents a complete parameter set for the Initiator::DoWriteReadFor().
27 class Transaction {
28  public:
29   // Same set of parameters as  Initiator::DoWriteReadFor(), with the exception
30   // of optional parameter timeout.
31   constexpr Transaction(
32       Status expected_return_value,
33       Address device_address,
34       ConstByteSpan write_buffer,
35       ConstByteSpan read_buffer,
36       std::optional<chrono::SystemClock::duration> timeout = std::nullopt)
return_value_(expected_return_value)37       : return_value_(expected_return_value),
38         read_buffer_(read_buffer),
39         write_buffer_(write_buffer),
40         address_(device_address),
41         timeout_(timeout) {}
42 
43   // Alternate Transaction constructor for use in ProbeTransaction.
44   constexpr Transaction(
45       Status expected_return_value,
46       Address device_address,
47       std::optional<chrono::SystemClock::duration> timeout = std::nullopt)
Transaction(expected_return_value,device_address,ConstByteSpan (),ignored_buffer_,timeout)48       : Transaction(expected_return_value,
49                     device_address,
50                     ConstByteSpan(),
51                     ignored_buffer_,
52                     timeout) {}
53 
54   // Gets the buffer that is virtually read.
read_buffer()55   ConstByteSpan read_buffer() const { return read_buffer_; }
56 
57   // Gets the buffer that should be written by the driver.
write_buffer()58   ConstByteSpan write_buffer() const { return write_buffer_; }
59 
60   // Gets the min duration for a blocking i2c transaction.
timeout()61   std::optional<chrono::SystemClock::duration> timeout() const {
62     return timeout_;
63   }
64 
65   // Gets the i2c address that the i2c transaction is targetting.
address()66   Address address() const { return address_; }
67 
68   // Gets the expected return value.
return_value()69   Status return_value() const { return return_value_; }
70 
71  private:
72   const Status return_value_;
73   const ConstByteSpan read_buffer_;
74   const ConstByteSpan write_buffer_;
75   static constexpr std::array<std::byte, 1> ignored_buffer_ = {};
76   const Address address_;
77   const std::optional<chrono::SystemClock::duration> timeout_;
78 };
79 
80 // Read transaction is a helper that constructs a read only transaction.
81 constexpr Transaction ReadTransaction(
82     Status expected_return_value,
83     Address device_address,
84     ConstByteSpan read_buffer,
85     std::optional<chrono::SystemClock::duration> timeout = std::nullopt) {
86   return Transaction(expected_return_value,
87                      device_address,
88                      ConstByteSpan(),
89                      read_buffer,
90                      timeout);
91 }
92 
93 // WriteTransaction is a helper that constructs a write only transaction.
94 constexpr Transaction WriteTransaction(
95     Status expected_return_value,
96     Address device_address,
97     ConstByteSpan write_buffer,
98     std::optional<chrono::SystemClock::duration> timeout = std::nullopt) {
99   return Transaction(expected_return_value,
100                      device_address,
101                      write_buffer,
102                      ConstByteSpan(),
103                      timeout);
104 }
105 
106 // ProbeTransaction is a helper that constructs a one-byte read transaction.
107 // For use in testing Probe transactions with the Mock Initiator.
108 constexpr Transaction ProbeTransaction(
109     Status expected_return_value,
110     Address device_address,
111     std::optional<chrono::SystemClock::duration> timeout = std::nullopt) {
112   return Transaction(expected_return_value, device_address, timeout);
113 }
114 
115 // MockInitiator takes a series of read and/or write transactions and
116 // compares them against user/driver input.
117 //
118 // This mock uses Gtest to ensure that the transactions instantiated meet
119 // expectations. This MockedInitiator should be instantiated inside a Gtest test
120 // frame.
121 class MockInitiator : public Initiator {
122  public:
MockInitiator(span<Transaction> transaction_list)123   explicit constexpr MockInitiator(span<Transaction> transaction_list)
124       : expected_transactions_(transaction_list),
125         expected_transaction_index_(0) {}
126 
127   // Should be called at the end of the test to ensure that all expected
128   // transactions have been met.
129   // Returns:
130   // Ok - Success.
131   // OutOfRange - The mocked set of transactions has not been exhausted.
Finalize()132   Status Finalize() const {
133     if (expected_transaction_index_ != expected_transactions_.size()) {
134       return Status::OutOfRange();
135     }
136     return Status();
137   }
138 
139   // Runs Finalize() regardless of whether it was already optionally finalized.
140   ~MockInitiator() override;
141 
142  private:
143   // Implements a mocked backend for the i2c initiator.
144   //
145   // Expects (via Gtest):
146   // tx_buffer == expected_transaction_tx_buffer
147   // tx_buffer.size() == expected_transaction_tx_buffer.size()
148   // rx_buffer.size() == expected_transaction_rx_buffer.size()
149   //
150   // Asserts:
151   // When the number of calls to this method exceed the number of expected
152   //    transactions.
153   //
154   // Returns:
155   // Specified transaction return type
156   Status DoWriteReadFor(Address device_address,
157                         ConstByteSpan tx_buffer,
158                         ByteSpan rx_buffer,
159                         chrono::SystemClock::duration timeout) override;
160 
161   span<Transaction> expected_transactions_;
162   size_t expected_transaction_index_;
163 };
164 
165 // Makes a new i2c transactions list.
166 template <size_t kSize>
MakeExpectedTransactionArray(const Transaction (& transactions)[kSize])167 constexpr std::array<Transaction, kSize> MakeExpectedTransactionArray(
168     const Transaction (&transactions)[kSize]) {
169   return containers::to_array(transactions);
170 }
171 
172 }  // namespace pw::i2c
173