Home | History | Annotate | Download | only in serial
      1 // Copyright (c) 2012 The Chromium 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 #include <deque>
      6 #include <string>
      7 #include <vector>
      8 
      9 #include "base/memory/scoped_ptr.h"
     10 #include "chrome/browser/extensions/api/serial/serial_api.h"
     11 #include "chrome/browser/extensions/api/serial/serial_connection.h"
     12 #include "chrome/browser/extensions/extension_apitest.h"
     13 #include "chrome/browser/extensions/extension_function.h"
     14 #include "chrome/browser/extensions/extension_function_test_utils.h"
     15 #include "chrome/browser/extensions/extension_test_message_listener.h"
     16 #include "chrome/browser/ui/browser.h"
     17 #include "content/public/browser/browser_thread.h"
     18 #include "testing/gmock/include/gmock/gmock.h"
     19 
     20 using testing::_;
     21 using testing::Return;
     22 
     23 using content::BrowserThread;
     24 
     25 namespace {
     26 
     27 class SerialApiTest : public ExtensionApiTest {
     28  public:
     29   SerialApiTest() {}
     30 };
     31 
     32 }  // namespace
     33 
     34 namespace extensions {
     35 
     36 class FakeSerialGetPortsFunction : public AsyncExtensionFunction {
     37  public:
     38   virtual bool RunImpl() OVERRIDE {
     39     base::ListValue* ports = new base::ListValue();
     40     ports->Append(Value::CreateStringValue("/dev/fakeserial"));
     41     ports->Append(Value::CreateStringValue("\\\\COM800\\"));
     42     SetResult(ports);
     43     SendResponse(true);
     44     return true;
     45   }
     46  protected:
     47   virtual ~FakeSerialGetPortsFunction() {}
     48 };
     49 
     50 class FakeEchoSerialConnection : public SerialConnection {
     51  public:
     52   explicit FakeEchoSerialConnection(
     53       const std::string& port,
     54       int bitrate,
     55       const std::string& owner_extension_id)
     56       : SerialConnection(port, bitrate, owner_extension_id),
     57         opened_(true) {
     58     Flush();
     59     opened_ = false;
     60   }
     61 
     62   virtual ~FakeEchoSerialConnection() {
     63   }
     64 
     65   virtual bool Open() {
     66     DCHECK(!opened_);
     67     opened_ = true;
     68     return true;
     69   }
     70 
     71   virtual void Close() {
     72     DCHECK(opened_);
     73   }
     74 
     75   virtual void Flush() {
     76     DCHECK(opened_);
     77     buffer_.clear();
     78   }
     79 
     80   virtual int Read(scoped_refptr<net::IOBufferWithSize> io_buffer) {
     81     DCHECK(io_buffer->data());
     82 
     83     if (buffer_.empty()) {
     84       return 0;
     85     }
     86     char *data = io_buffer->data();
     87     int bytes_to_copy = io_buffer->size();
     88     while (bytes_to_copy-- && !buffer_.empty()) {
     89       *data++ = buffer_.front();
     90       buffer_.pop_front();
     91     }
     92     return io_buffer->size();
     93   }
     94 
     95   virtual int Write(scoped_refptr<net::IOBuffer> io_buffer, int byte_count) {
     96     DCHECK(io_buffer.get());
     97     DCHECK_GE(byte_count, 0);
     98 
     99     char *data = io_buffer->data();
    100     int count = byte_count;
    101     while (count--)
    102       buffer_.push_back(*data++);
    103     return byte_count;
    104   }
    105 
    106   MOCK_METHOD1(GetControlSignals, bool(ControlSignals &));
    107   MOCK_METHOD1(SetControlSignals, bool(const ControlSignals &));
    108 
    109  private:
    110   bool opened_;
    111   std::deque<char> buffer_;
    112 
    113   DISALLOW_COPY_AND_ASSIGN(FakeEchoSerialConnection);
    114 };
    115 
    116 class FakeSerialOpenFunction : public SerialOpenFunction {
    117  protected:
    118   virtual SerialConnection* CreateSerialConnection(
    119       const std::string& port,
    120       int bitrate,
    121       const std::string& owner_extension_id) OVERRIDE {
    122     FakeEchoSerialConnection* serial_connection =
    123         new FakeEchoSerialConnection(port, bitrate, owner_extension_id);
    124     EXPECT_CALL(*serial_connection, GetControlSignals(_)).
    125         Times(1).WillOnce(Return(true));
    126     EXPECT_CALL(*serial_connection, SetControlSignals(_)).
    127         Times(1).WillOnce(Return(true));
    128     return serial_connection;
    129   }
    130   virtual bool DoesPortExist(const std::string& port) OVERRIDE {
    131     return true;
    132   }
    133 
    134  protected:
    135   virtual ~FakeSerialOpenFunction() {}
    136 };
    137 
    138 }  // namespace extensions
    139 
    140 ExtensionFunction* FakeSerialGetPortsFunctionFactory() {
    141   return new extensions::FakeSerialGetPortsFunction();
    142 }
    143 
    144 ExtensionFunction* FakeSerialOpenFunctionFactory() {
    145   return new extensions::FakeSerialOpenFunction();
    146 }
    147 
    148 // Disable SIMULATE_SERIAL_PORTS only if all the following are true:
    149 //
    150 // 1. You have an Arduino or compatible board attached to your machine and
    151 // properly appearing as the first virtual serial port ("first" is very loosely
    152 // defined as whichever port shows up in serial.getPorts). We've tested only
    153 // the Atmega32u4 Breakout Board and Arduino Leonardo; note that both these
    154 // boards are based on the Atmel ATmega32u4, rather than the more common
    155 // Arduino '328p with either FTDI or '8/16u2 USB interfaces. TODO: test more
    156 // widely.
    157 //
    158 // 2. Your user has permission to read/write the port. For example, this might
    159 // mean that your user is in the "tty" or "uucp" group on Ubuntu flavors of
    160 // Linux, or else that the port's path (e.g., /dev/ttyACM0) has global
    161 // read/write permissions.
    162 //
    163 // 3. You have uploaded a program to the board that does a byte-for-byte echo
    164 // on the virtual serial port at 57600 bps. An example is at
    165 // chrome/test/data/extensions/api_test/serial/api/serial_arduino_test.ino.
    166 //
    167 #define SIMULATE_SERIAL_PORTS (1)
    168 IN_PROC_BROWSER_TEST_F(SerialApiTest, SerialFakeHardware) {
    169   ResultCatcher catcher;
    170   catcher.RestrictToProfile(browser()->profile());
    171 
    172 #if SIMULATE_SERIAL_PORTS
    173   ASSERT_TRUE(ExtensionFunctionDispatcher::OverrideFunction(
    174       "serial.getPorts",
    175       FakeSerialGetPortsFunctionFactory));
    176   ASSERT_TRUE(ExtensionFunctionDispatcher::OverrideFunction(
    177       "serial.open",
    178       FakeSerialOpenFunctionFactory));
    179 #endif
    180 
    181   ASSERT_TRUE(RunExtensionTest("serial/api")) << message_;
    182 }
    183 
    184 IN_PROC_BROWSER_TEST_F(SerialApiTest, SerialRealHardware) {
    185   ResultCatcher catcher;
    186   catcher.RestrictToProfile(browser()->profile());
    187 
    188   ASSERT_TRUE(RunExtensionTest("serial/real_hardware")) << message_;
    189 }
    190