You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
172 lines
6.7 KiB
172 lines
6.7 KiB
// Copyright 2015 The Chromium OS Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#ifndef LIBBRILLO_BRILLO_STREAMS_FAKE_STREAM_H_
|
|
#define LIBBRILLO_BRILLO_STREAMS_FAKE_STREAM_H_
|
|
|
|
#include <queue>
|
|
#include <string>
|
|
|
|
#include <base/callback_forward.h>
|
|
#include <base/macros.h>
|
|
#include <base/time/clock.h>
|
|
#include <base/time/time.h>
|
|
#include <brillo/secure_blob.h>
|
|
#include <brillo/streams/stream.h>
|
|
|
|
namespace brillo {
|
|
|
|
// Fake stream implementation for testing.
|
|
// This class allows to provide data for the stream in tests that can be later
|
|
// read through the Stream interface. Also, data written into the stream can be
|
|
// later inspected and verified.
|
|
//
|
|
// NOTE: This class provides a fake implementation for streams with separate
|
|
// input and output channels. That is, read and write operations do not affect
|
|
// each other. Also, the stream implementation is sequential only (no seeking).
|
|
// Good examples of a use case for fake stream are:
|
|
// - read-only sequential streams (file, memory, pipe, ...)
|
|
// - write-only sequential streams (same as above)
|
|
// - independent channel read-write streams (sockets, ...)
|
|
//
|
|
// For more complex read/write stream test scenarios using a real MemoryStream
|
|
// or temporary FileStream is probably a better choice.
|
|
class FakeStream : public Stream {
|
|
public:
|
|
// Construct a new instance of the fake stream.
|
|
// mode - expected read/write mode supported by the stream.
|
|
// clock - the clock to use to get the current time.
|
|
FakeStream(Stream::AccessMode mode,
|
|
base::Clock* clock);
|
|
|
|
// Add data packets to the read queue of the stream.
|
|
// Optional |delay| indicates that the data packet should be delayed.
|
|
void AddReadPacketData(base::TimeDelta delay, const void* data, size_t size);
|
|
void AddReadPacketData(base::TimeDelta delay, brillo::Blob data);
|
|
void AddReadPacketString(base::TimeDelta delay, const std::string& data);
|
|
|
|
// Schedule a read error by adding a special error packet to the queue.
|
|
void QueueReadError(base::TimeDelta delay);
|
|
void QueueReadErrorWithMessage(base::TimeDelta delay,
|
|
const std::string& message);
|
|
|
|
// Resets read queue and clears any input data buffers.
|
|
void ClearReadQueue();
|
|
|
|
// Add expectations for output data packets to be written by the stream.
|
|
// Optional |delay| indicates that the initial write operation for the data in
|
|
// the packet should be delayed.
|
|
// ExpectWritePacketSize just limits the size of output packet while
|
|
// ExpectWritePacketData also validates that the data matches that of |data|.
|
|
void ExpectWritePacketSize(base::TimeDelta delay, size_t data_size);
|
|
void ExpectWritePacketData(base::TimeDelta delay,
|
|
const void* data,
|
|
size_t size);
|
|
void ExpectWritePacketData(base::TimeDelta delay, brillo::Blob data);
|
|
void ExpectWritePacketString(base::TimeDelta delay, const std::string& data);
|
|
|
|
// Schedule a write error by adding a special error packet to the queue.
|
|
void QueueWriteError(base::TimeDelta delay);
|
|
void QueueWriteErrorWithMessage(base::TimeDelta delay,
|
|
const std::string& message);
|
|
|
|
// Resets write queue and clears any output data buffers.
|
|
void ClearWriteQueue();
|
|
|
|
// Returns the output data accumulated so far by all complete write packets,
|
|
// or explicitly flushed.
|
|
const brillo::Blob& GetFlushedOutputData() const;
|
|
std::string GetFlushedOutputDataAsString() const;
|
|
|
|
// Overrides from brillo::Stream.
|
|
bool IsOpen() const override { return is_open_; }
|
|
bool CanRead() const override;
|
|
bool CanWrite() const override;
|
|
bool CanSeek() const override { return false; }
|
|
bool CanGetSize() const override { return false; }
|
|
uint64_t GetSize() const override { return 0; }
|
|
bool SetSizeBlocking(uint64_t size, ErrorPtr* error) override;
|
|
uint64_t GetRemainingSize() const override { return 0; }
|
|
uint64_t GetPosition() const override { return 0; }
|
|
bool Seek(int64_t offset,
|
|
Whence whence,
|
|
uint64_t* new_position,
|
|
ErrorPtr* error) override;
|
|
|
|
bool ReadNonBlocking(void* buffer,
|
|
size_t size_to_read,
|
|
size_t* size_read,
|
|
bool* end_of_stream,
|
|
ErrorPtr* error) override;
|
|
bool WriteNonBlocking(const void* buffer,
|
|
size_t size_to_write,
|
|
size_t* size_written,
|
|
ErrorPtr* error) override;
|
|
bool FlushBlocking(ErrorPtr* error) override;
|
|
bool CloseBlocking(ErrorPtr* error) override;
|
|
bool WaitForData(AccessMode mode,
|
|
const base::Callback<void(AccessMode)>& callback,
|
|
ErrorPtr* error) override;
|
|
bool WaitForDataBlocking(AccessMode in_mode,
|
|
base::TimeDelta timeout,
|
|
AccessMode* out_mode,
|
|
ErrorPtr* error) override;
|
|
|
|
private:
|
|
// Input data packet to be placed on the read queue.
|
|
struct InputDataPacket {
|
|
brillo::Blob data; // Data to be read.
|
|
base::TimeDelta delay_before; // Possible delay for the first read.
|
|
bool read_error{false}; // Set to true if this packet generates an error.
|
|
};
|
|
|
|
// Output data packet to be placed on the write queue.
|
|
struct OutputDataPacket {
|
|
size_t expected_size{0}; // Output packet size
|
|
brillo::Blob data; // Possible data to verify the output with.
|
|
base::TimeDelta delay_before; // Possible delay for the first write.
|
|
bool write_error{false}; // Set to true if this packet generates an error.
|
|
};
|
|
|
|
// Check if there is any pending read data in the input buffer.
|
|
bool IsReadBufferEmpty() const;
|
|
// Pops the next read packet from the queue and sets its data into the
|
|
// internal input buffer.
|
|
bool PopReadPacket();
|
|
|
|
// Check if the output buffer is full.
|
|
bool IsWriteBufferFull() const;
|
|
|
|
// Moves the current full output buffer into |all_output_data_|, clears the
|
|
// buffer, and pops the information about the next expected output packet
|
|
// from the write queue.
|
|
bool PopWritePacket();
|
|
|
|
bool is_open_{true};
|
|
Stream::AccessMode mode_;
|
|
base::Clock* clock_;
|
|
|
|
// Internal data for read operations.
|
|
std::queue<InputDataPacket> incoming_queue_;
|
|
base::Time delay_input_until_;
|
|
brillo::Blob input_buffer_;
|
|
size_t input_ptr_{0};
|
|
bool report_read_error_{false};
|
|
|
|
// Internal data for write operations.
|
|
std::queue<OutputDataPacket> outgoing_queue_;
|
|
base::Time delay_output_until_;
|
|
brillo::Blob output_buffer_;
|
|
brillo::Blob expected_output_data_;
|
|
size_t max_output_buffer_size_{0};
|
|
bool report_write_error_{false};
|
|
brillo::Blob all_output_data_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(FakeStream);
|
|
};
|
|
|
|
} // namespace brillo
|
|
|
|
#endif // LIBBRILLO_BRILLO_STREAMS_FAKE_STREAM_H_
|