Home | History | Annotate | Download | only in streams
      1 // Copyright 2015 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 LIBBRILLO_BRILLO_STREAMS_FAKE_STREAM_H_
      6 #define LIBBRILLO_BRILLO_STREAMS_FAKE_STREAM_H_
      7 
      8 #include <queue>
      9 #include <string>
     10 
     11 #include <base/callback_forward.h>
     12 #include <base/macros.h>
     13 #include <base/time/clock.h>
     14 #include <base/time/time.h>
     15 #include <brillo/secure_blob.h>
     16 #include <brillo/streams/stream.h>
     17 
     18 namespace brillo {
     19 
     20 // Fake stream implementation for testing.
     21 // This class allows to provide data for the stream in tests that can be later
     22 // read through the Stream interface. Also, data written into the stream can be
     23 // later inspected and verified.
     24 //
     25 // NOTE: This class provides a fake implementation for streams with separate
     26 // input and output channels. That is, read and write operations do not affect
     27 // each other. Also, the stream implementation is sequential only (no seeking).
     28 // Good examples of a use case for fake stream are:
     29 //  - read-only sequential streams (file, memory, pipe, ...)
     30 //  - write-only sequential streams (same as above)
     31 //  - independent channel read-write streams (sockets, ...)
     32 //
     33 // For more complex read/write stream test scenarios using a real MemoryStream
     34 // or temporary FileStream is probably a better choice.
     35 class FakeStream : public Stream {
     36  public:
     37   // Construct a new instance of the fake stream.
     38   //   mode        - expected read/write mode supported by the stream.
     39   //   clock       - the clock to use to get the current time.
     40   FakeStream(Stream::AccessMode mode,
     41              base::Clock* clock);
     42 
     43   // Add data packets to the read queue of the stream.
     44   // Optional |delay| indicates that the data packet should be delayed.
     45   void AddReadPacketData(base::TimeDelta delay, const void* data, size_t size);
     46   void AddReadPacketData(base::TimeDelta delay, brillo::Blob data);
     47   void AddReadPacketString(base::TimeDelta delay, const std::string& data);
     48 
     49   // Schedule a read error by adding a special error packet to the queue.
     50   void QueueReadError(base::TimeDelta delay);
     51   void QueueReadErrorWithMessage(base::TimeDelta delay,
     52                                  const std::string& message);
     53 
     54   // Resets read queue and clears any input data buffers.
     55   void ClearReadQueue();
     56 
     57   // Add expectations for output data packets to be written by the stream.
     58   // Optional |delay| indicates that the initial write operation for the data in
     59   // the packet should be delayed.
     60   // ExpectWritePacketSize just limits the size of output packet while
     61   // ExpectWritePacketData also validates that the data matches that of |data|.
     62   void ExpectWritePacketSize(base::TimeDelta delay, size_t data_size);
     63   void ExpectWritePacketData(base::TimeDelta delay,
     64                              const void* data,
     65                              size_t size);
     66   void ExpectWritePacketData(base::TimeDelta delay, brillo::Blob data);
     67   void ExpectWritePacketString(base::TimeDelta delay, const std::string& data);
     68 
     69   // Schedule a write error by adding a special error packet to the queue.
     70   void QueueWriteError(base::TimeDelta delay);
     71   void QueueWriteErrorWithMessage(base::TimeDelta delay,
     72                                   const std::string& message);
     73 
     74   // Resets write queue and clears any output data buffers.
     75   void ClearWriteQueue();
     76 
     77   // Returns the output data accumulated so far by all complete write packets,
     78   // or explicitly flushed.
     79   const brillo::Blob& GetFlushedOutputData() const;
     80   std::string GetFlushedOutputDataAsString() const;
     81 
     82   // Overrides from brillo::Stream.
     83   bool IsOpen() const override { return is_open_; }
     84   bool CanRead() const override;
     85   bool CanWrite() const override;
     86   bool CanSeek() const override { return false; }
     87   bool CanGetSize() const override { return false; }
     88   uint64_t GetSize() const override { return 0; }
     89   bool SetSizeBlocking(uint64_t size, ErrorPtr* error) override;
     90   uint64_t GetRemainingSize() const override { return 0; }
     91   uint64_t GetPosition() const override { return 0; }
     92   bool Seek(int64_t offset,
     93             Whence whence,
     94             uint64_t* new_position,
     95             ErrorPtr* error) override;
     96 
     97   bool ReadNonBlocking(void* buffer,
     98                        size_t size_to_read,
     99                        size_t* size_read,
    100                        bool* end_of_stream,
    101                        ErrorPtr* error) override;
    102   bool WriteNonBlocking(const void* buffer,
    103                         size_t size_to_write,
    104                         size_t* size_written,
    105                         ErrorPtr* error) override;
    106   bool FlushBlocking(ErrorPtr* error) override;
    107   bool CloseBlocking(ErrorPtr* error) override;
    108   bool WaitForData(AccessMode mode,
    109                    const base::Callback<void(AccessMode)>& callback,
    110                    ErrorPtr* error) override;
    111   bool WaitForDataBlocking(AccessMode in_mode,
    112                            base::TimeDelta timeout,
    113                            AccessMode* out_mode,
    114                            ErrorPtr* error) override;
    115 
    116  private:
    117   // Input data packet to be placed on the read queue.
    118   struct InputDataPacket {
    119     brillo::Blob data;  // Data to be read.
    120     base::TimeDelta delay_before;  // Possible delay for the first read.
    121     bool read_error{false};  // Set to true if this packet generates an error.
    122   };
    123 
    124   // Output data packet to be placed on the write queue.
    125   struct OutputDataPacket {
    126     size_t expected_size{0};  // Output packet size
    127     brillo::Blob data;  // Possible data to verify the output with.
    128     base::TimeDelta delay_before;  // Possible delay for the first write.
    129     bool write_error{false};  // Set to true if this packet generates an error.
    130   };
    131 
    132   // Check if there is any pending read data in the input buffer.
    133   bool IsReadBufferEmpty() const;
    134   // Pops the next read packet from the queue and sets its data into the
    135   // internal input buffer.
    136   bool PopReadPacket();
    137 
    138   // Check if the output buffer is full.
    139   bool IsWriteBufferFull() const;
    140 
    141   // Moves the current full output buffer into |all_output_data_|, clears the
    142   // buffer, and pops the information about the next expected output packet
    143   // from the write queue.
    144   bool PopWritePacket();
    145 
    146   bool is_open_{true};
    147   Stream::AccessMode mode_;
    148   base::Clock* clock_;
    149 
    150   // Internal data for read operations.
    151   std::queue<InputDataPacket> incoming_queue_;
    152   base::Time delay_input_until_;
    153   brillo::Blob input_buffer_;
    154   size_t input_ptr_{0};
    155   bool report_read_error_{false};
    156 
    157   // Internal data for write operations.
    158   std::queue<OutputDataPacket> outgoing_queue_;
    159   base::Time delay_output_until_;
    160   brillo::Blob output_buffer_;
    161   brillo::Blob expected_output_data_;
    162   size_t max_output_buffer_size_{0};
    163   bool report_write_error_{false};
    164   brillo::Blob all_output_data_;
    165 
    166   DISALLOW_COPY_AND_ASSIGN(FakeStream);
    167 };
    168 
    169 }  // namespace brillo
    170 
    171 #endif  // LIBBRILLO_BRILLO_STREAMS_FAKE_STREAM_H_
    172