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