Home | History | Annotate | Download | only in serial
      1 // Copyright 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_test_utils.h"
     14 #include "chrome/browser/extensions/extension_test_message_listener.h"
     15 #include "chrome/browser/ui/browser.h"
     16 #include "chrome/common/extensions/api/serial.h"
     17 #include "content/public/browser/browser_thread.h"
     18 #include "extensions/browser/extension_function.h"
     19 #include "testing/gmock/include/gmock/gmock.h"
     20 
     21 using testing::_;
     22 using testing::Return;
     23 
     24 using content::BrowserThread;
     25 
     26 namespace {
     27 
     28 class SerialApiTest : public ExtensionApiTest {
     29  public:
     30   SerialApiTest() {}
     31 };
     32 
     33 }  // namespace
     34 
     35 namespace extensions {
     36 
     37 class FakeSerialGetDevicesFunction : public AsyncExtensionFunction {
     38  public:
     39   virtual bool RunAsync() OVERRIDE {
     40     base::ListValue* devices = new base::ListValue();
     41     base::DictionaryValue* device0 = new base::DictionaryValue();
     42     device0->SetString("path", "/dev/fakeserial");
     43     base::DictionaryValue* device1 = new base::DictionaryValue();
     44     device1->SetString("path", "\\\\COM800\\");
     45     devices->Append(device0);
     46     devices->Append(device1);
     47     SetResult(devices);
     48     SendResponse(true);
     49     return true;
     50   }
     51  protected:
     52   virtual ~FakeSerialGetDevicesFunction() {}
     53 };
     54 
     55 class FakeEchoSerialConnection : public SerialConnection {
     56  public:
     57   explicit FakeEchoSerialConnection(
     58       const std::string& port,
     59       const std::string& owner_extension_id)
     60       : SerialConnection(port, owner_extension_id),
     61         opened_(false) {
     62   }
     63 
     64   virtual ~FakeEchoSerialConnection() {
     65   }
     66 
     67   virtual void Open(const OpenCompleteCallback& callback) {
     68     DCHECK(!opened_);
     69     opened_ = true;
     70     callback.Run(true);
     71   }
     72 
     73   virtual bool Configure(const api::serial::ConnectionOptions& options) {
     74     return true;
     75   }
     76 
     77   virtual void Close() {
     78     DCHECK(opened_);
     79   }
     80 
     81   virtual bool Receive(const ReceiveCompleteCallback& callback) {
     82     read_callback_ = callback;
     83     return true;
     84   }
     85 
     86   virtual bool Send(const std::string& data,
     87                     const SendCompleteCallback& callback) {
     88     callback.Run(data.length(), api::serial::SEND_ERROR_NONE);
     89     if (!read_callback_.is_null()) {
     90       read_callback_.Run(data, api::serial::RECEIVE_ERROR_NONE);
     91     }
     92     return true;
     93   }
     94 
     95   virtual bool GetControlSignals(api::serial::DeviceControlSignals* signals)
     96       const {
     97     signals->dcd = true;
     98     signals->cts = true;
     99     signals->ri = true;
    100     signals->dsr = true;
    101     return true;
    102   }
    103 
    104   virtual bool GetInfo(api::serial::ConnectionInfo* info) const {
    105     info->paused = false;
    106     info->persistent = false;
    107     info->buffer_size = 4096;
    108     info->receive_timeout = 0;
    109     info->send_timeout = 0;
    110     info->bitrate.reset(new int(9600));
    111     info->data_bits = api::serial::DATA_BITS_EIGHT;
    112     info->parity_bit = api::serial::PARITY_BIT_NO;
    113     info->stop_bits = api::serial::STOP_BITS_ONE;
    114     info->cts_flow_control.reset(new bool(false));
    115     return true;
    116   }
    117 
    118   MOCK_METHOD1(SetControlSignals, bool(const api::serial::HostControlSignals&));
    119 
    120  private:
    121   bool opened_;
    122   ReceiveCompleteCallback read_callback_;
    123 
    124   DISALLOW_COPY_AND_ASSIGN(FakeEchoSerialConnection);
    125 };
    126 
    127 class FakeSerialConnectFunction : public api::SerialConnectFunction {
    128  protected:
    129   virtual SerialConnection* CreateSerialConnection(
    130       const std::string& port,
    131       const std::string& owner_extension_id) const OVERRIDE {
    132     FakeEchoSerialConnection* serial_connection =
    133         new FakeEchoSerialConnection(port, owner_extension_id);
    134     EXPECT_CALL(*serial_connection, SetControlSignals(_)).
    135         Times(1).WillOnce(Return(true));
    136     return serial_connection;
    137   }
    138 
    139  protected:
    140   virtual ~FakeSerialConnectFunction() {}
    141 };
    142 
    143 }  // namespace extensions
    144 
    145 ExtensionFunction* FakeSerialGetDevicesFunctionFactory() {
    146   return new extensions::FakeSerialGetDevicesFunction();
    147 }
    148 
    149 ExtensionFunction* FakeSerialConnectFunctionFactory() {
    150   return new extensions::FakeSerialConnectFunction();
    151 }
    152 
    153 // Disable SIMULATE_SERIAL_PORTS only if all the following are true:
    154 //
    155 // 1. You have an Arduino or compatible board attached to your machine and
    156 // properly appearing as the first virtual serial port ("first" is very loosely
    157 // defined as whichever port shows up in serial.getPorts). We've tested only
    158 // the Atmega32u4 Breakout Board and Arduino Leonardo; note that both these
    159 // boards are based on the Atmel ATmega32u4, rather than the more common
    160 // Arduino '328p with either FTDI or '8/16u2 USB interfaces. TODO: test more
    161 // widely.
    162 //
    163 // 2. Your user has permission to read/write the port. For example, this might
    164 // mean that your user is in the "tty" or "uucp" group on Ubuntu flavors of
    165 // Linux, or else that the port's path (e.g., /dev/ttyACM0) has global
    166 // read/write permissions.
    167 //
    168 // 3. You have uploaded a program to the board that does a byte-for-byte echo
    169 // on the virtual serial port at 57600 bps. An example is at
    170 // chrome/test/data/extensions/api_test/serial/api/serial_arduino_test.ino.
    171 //
    172 #define SIMULATE_SERIAL_PORTS (1)
    173 IN_PROC_BROWSER_TEST_F(SerialApiTest, SerialFakeHardware) {
    174   ResultCatcher catcher;
    175   catcher.RestrictToProfile(browser()->profile());
    176 
    177 #if SIMULATE_SERIAL_PORTS
    178   ASSERT_TRUE(extensions::ExtensionFunctionDispatcher::OverrideFunction(
    179       "serial.getDevices", FakeSerialGetDevicesFunctionFactory));
    180   ASSERT_TRUE(extensions::ExtensionFunctionDispatcher::OverrideFunction(
    181       "serial.connect", FakeSerialConnectFunctionFactory));
    182 #endif
    183 
    184   ASSERT_TRUE(RunExtensionTest("serial/api")) << message_;
    185 }
    186 
    187 IN_PROC_BROWSER_TEST_F(SerialApiTest, SerialRealHardware) {
    188   ResultCatcher catcher;
    189   catcher.RestrictToProfile(browser()->profile());
    190 
    191   ASSERT_TRUE(RunExtensionTest("serial/real_hardware")) << message_;
    192 }
    193