blob: c616b41a42516928778524362a32917a863d1554 [file] [log] [blame]
Gilad Arnold6eccc532012-05-17 15:44:22 -07001// Copyright (c) 2012 The Chromium OS 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#ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_GPIO_MOCK_FILE_DESCRIPTOR_H__
6#define CHROMEOS_PLATFORM_UPDATE_ENGINE_GPIO_MOCK_FILE_DESCRIPTOR_H__
7
8#include <base/rand_util.h>
9#include <base/time.h>
10
11#include "update_engine/file_descriptor.h"
12#include "update_engine/gpio_handler_unittest.h"
13
14// A set of mock file descriptors used for unit-testing. All classes here
15// inherit the FileDescriptor interface.
16
17namespace chromeos_update_engine {
18
19// An abstract classs implementing a common mock infrastructure for GPIO
20// reading/writing. This includes all the inherited interface methods, and basic
21// logic to manage the opening, reading, writing and closing of GPIO files. It
22// is up to concrete implementations to manage their internal state machine and
23// update the values to be read by clients. In most cases, this amounts to
24// adding internal state and overloading the UpdateState() method to change to
25// various GPIO "registers" accordingly.
26class GpioMockFileDescriptor : public FileDescriptor {
27 public:
28 GpioMockFileDescriptor();
29
30 // Interface methods.
31 virtual bool Open(const char* path, int flags, mode_t mode);
32 virtual bool Open(const char* path, int flags);
33 virtual ssize_t Read(void* buf, size_t count);
34 virtual ssize_t Write(const void* buf, size_t count);
35 virtual bool Close();
36 virtual void Reset();
37 virtual bool IsSettingErrno();
38 virtual bool IsOpen() {
39 return (gpio_id_ < kMockGpioIdMax && gpio_subdev_ < kMockGpioSubdevMax);
40 }
41
42
43 // Returns true iff all file resources were freed; otherwise, will fail the
44 // current test.
45 virtual bool ExpectAllResourcesDeallocated();
46
47 // Returns true iff all GPIOs have been restored to their default state;
48 // otherwise, will fail the current test.
49 virtual bool ExpectAllGpiosRestoredToDefault();
50
Gilad Arnold95931b82013-01-09 10:37:17 -080051 // Returns true iff the number of open attempts equals the argument;
52 // otherwise, will fail the current test.
53 virtual bool ExpectNumOpenAttempted(unsigned count);
54
Gilad Arnold6eccc532012-05-17 15:44:22 -070055 protected:
56 // A pair of write value and time at which it was written.
57 struct MockGpioWriteEvent {
58 MockGpioVal val;
59 base::Time time;
60 };
61
62 // Sets the last written value and timestamp of GPIO |gpio_id|.
63 inline MockGpioVal SetGpioLastWrite(MockGpioId gpio_id, MockGpioVal val,
64 base::Time time) {
65 gpio_last_writes_[gpio_id].time = time;
66 return (gpio_last_writes_[gpio_id].val = val);
67 }
68
69 inline MockGpioVal SetGpioLastWrite(MockGpioId gpio_id, MockGpioVal val) {
70 return SetGpioLastWrite(gpio_id, val, base::Time::Now());
71 }
72
73
74 // The current direction of each GPIO device. These are generally handled by
75 // Write(), but can be modified by concrete implementations of this class to
76 // simulate race conditions on GPIO devices.
77 MockGpioDir gpio_dirs_[kMockGpioIdMax];
78
79 // The current values to be read by the DUT. These can be modified by concrete
80 // implementations of this class, to reflect current GPIO values.
81 MockGpioVal gpio_read_vals_[kMockGpioIdMax];
82
83 // The last values and time they were written by the DUT to each GPIO device.
84 // These are generally handled by Write(), but can be modified by concrete
85 // implementations of this class to simulate race conditions on GPIO devices.
86 MockGpioWriteEvent gpio_last_writes_[kMockGpioIdMax];
87
88 // Override strings for GPIO value / direction readings. Initialized to null
89 // pointers by default, which means the default values will not be overridden.
90 const char* override_read_gpio_val_strings_[kMockGpioValMax];
91 const char* override_read_gpio_dir_strings_[kMockGpioDirMax];
92
93 private:
94 // GPIO subdevice identifiers.
95 enum MockGpioSubdev {
96 kMockGpioSubdevValue,
97 kMockGpioSubdevDirection,
98 kMockGpioSubdevMax // marker, do not remove!
99 };
100
101 // Device name prefixes of the different GPIOs.
102 static const char* gpio_devname_prefixes_[kMockGpioIdMax];
103
104 // Strings to be written as GPIO values, corresponding to the abstract GPIO
105 // value.
106 static const char* gpio_val_strings_[kMockGpioValMax];
107
108 // Strings to be written as GPIO directions, corresponding to the abstract
109 // GPIO direction.
110 static const char* gpio_dir_strings_[kMockGpioDirMax];
111
112
113 // Compare a string |buf| of length |count| that is written to a GPIO device
114 // with an array of strings |strs| of length |num_strs|. Returns the index of
115 // the string entry that is the same as the written string, or |num_strs| if
116 // none was found. Requires that the the last character in |buf| is a newline.
117 size_t DecodeGpioString(const char* buf, size_t count, const char** strs,
118 size_t num_strs) const;
119
120 // Decode a written GPIO value.
121 inline MockGpioVal DecodeGpioVal(const char* buf, size_t count) const {
122 return static_cast<MockGpioVal>(
123 DecodeGpioString(buf, count, gpio_val_strings_, kMockGpioValMax));
124 }
125
126 // Decodes a written GPIO direction.
127 inline MockGpioDir DecodeGpioDir(const char* buf, size_t count) const {
128 return static_cast<MockGpioDir>(
129 DecodeGpioString(buf, count, gpio_dir_strings_, kMockGpioDirMax));
130 }
131
132 // Simulate the Servo state transition, based on the last recorded state, the
133 // time it was recorded, and the current GPIO values. This is a pure virtual
134 // function that must be implemented by concrete subclasses.
135 virtual void UpdateState() = 0;
136
137 // The identifier of the currently accessed GPIO device.
138 MockGpioId gpio_id_;
139
140 // The identifier of the currently accessed GPIO sub-device.
141 MockGpioSubdev gpio_subdev_;
Gilad Arnold95931b82013-01-09 10:37:17 -0800142
143 // Counter for the number of files that were opened with this interface.
144 unsigned num_open_attempted_;
Gilad Arnold6eccc532012-05-17 15:44:22 -0700145};
146
147
148// A mock file descriptor that implements the GPIO test signaling protocol. In
149// doing so, it simulates the asynchronous behavior of a properly implemented
150// Servo test controller.
151class TestModeGpioMockFileDescriptor : public GpioMockFileDescriptor {
152 public:
153 TestModeGpioMockFileDescriptor(base::TimeDelta servo_poll_interval);
154 virtual ~TestModeGpioMockFileDescriptor() {};
155
156 protected:
157 // The state of the Servo-side GPIO signaling protocol. These do not include
158 // sub-state changes on the DUT side, which can be approximated by tracking
159 // read operations but otherwise cannot be observed by an ordinary Servo.
160 enum ServoState {
161 kServoStateInit,
162 kServoStateTriggerSent,
163 kServoStateChallengeUpReceived,
164 kServoStateChallengeDownReceived,
165 kServoStateMax // marker, do not remove!
166 };
167
168 // Simulate the Servo state transition, based on the last recorded state, the
169 // time it was recorded, and the current GPIO values.
170 virtual void UpdateState();
171
172 // The last recorded state in the GPIO protocol.
173 ServoState last_state_;
174
175 private:
176 // Return a uniformly distributed random time delta within the Servo poll
177 // interval.
178 inline base::TimeDelta RandomServoPollFuzz() {
179 return base::TimeDelta::FromMicroseconds(
180 base::RandInt(0, servo_poll_interval_.InMicroseconds()));
181 }
182
183 // The Servo poll interval.
184 base::TimeDelta servo_poll_interval_;
185
186 // The current Servo poll fuzz, used for deciding when signals are (simulated
187 // to be) sensed within the poll interval. Must be between zero and
188 // servo_poll_interval_.
189 base::TimeDelta curr_servo_poll_fuzz_;
190};
191
192
193// A mock file descriptor that implements GPIO feedback when not conneced to a
194// Servo, on boards that include a pull-up resistor wiring for GPIOs. This is
195// the typical mode of operations for Chromebooks out in the field, and we need
196// to make sure that the client is not made to believe that it is in test mode.
197class NormalModeGpioMockFileDescriptor : public GpioMockFileDescriptor {
198 private:
199 // This is a no-op, as there's no Servo connected.
200 virtual void UpdateState() {};
201};
202
203// A mock file descriptor that implements GPIOs that are not pulled-up by
204// default, and whose idle reading might be zero. We've seen this problem on
205// Lumpy/Stumpy and need to make sure that the protocol doesn't allow these
206// boards to go into test mode without actually being told so by a Servo.
207class NonPulledUpNormalModeGpioMockFileDescriptor
208 : public GpioMockFileDescriptor {
209 private:
210 // Set the default value of dut_flaga to "down".
211 virtual void UpdateState() {
212 gpio_read_vals_[kMockGpioIdDutflaga] = kMockGpioValDown;
213 }
214};
215
216// A mock file descriptor that implements a bogus GPIO feedback. This includes
217// flipping GPIO directions, invalid value readings, and I/O errors on various
218// file operations. All of these instances must be ruled out by the protocol,
219// resulting in normal mode operation.
220class ErrorNormalModeGpioMockFileDescriptor :
221 public TestModeGpioMockFileDescriptor {
222 public:
223 enum GpioError {
224 kGpioErrorFlipInputDir,
225 kGpioErrorReadInvalidVal,
226 kGpioErrorReadInvalidDir,
227 kGpioErrorFailFileOpen,
228 kGpioErrorFailFileRead,
229 kGpioErrorFailFileWrite,
230 kGpioErrorFailFileClose,
231 };
232
233 ErrorNormalModeGpioMockFileDescriptor(base::TimeDelta servo_poll_interval,
234 GpioError error);
235 virtual ~ErrorNormalModeGpioMockFileDescriptor() {};
236
237 // Wrapper methods for the respectively inherited ones, which can fail the
238 // call as part of a test.
239 virtual bool Open(const char* path, int flags, mode_t mode);
240 virtual ssize_t Read(void* buf, size_t count);
241 virtual ssize_t Write(const void* buf, size_t count);
242 virtual bool Close();
243
244 // Wrapper which restores all state we might have tampered with.
245 virtual bool ExpectAllGpiosRestoredToDefault();
246
247 private:
248 // Wraps the ordinary test mode servo simulation with an error injecting
249 // behavior, which corresponds to the requested type of error.
250 virtual void UpdateState();
251
252 // The GPIO error to be injected into the protocol.
253 GpioError error_;
254
255 // A flag denoting whether the direction of dut_flaga was already maliciously
256 // flipped.
257 bool is_dutflaga_dir_flipped_;
258};
259
260} // namespace chromeos_update_engine
261
262#endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_GPIO_MOCK_FILE_DESCRIPTOR_H__