| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <deque> |
| #include <string> |
| #include <vector> |
| |
| #include "base/memory/scoped_ptr.h" |
| #include "chrome/browser/extensions/api/serial/serial_api.h" |
| #include "chrome/browser/extensions/api/serial/serial_connection.h" |
| #include "chrome/browser/extensions/extension_apitest.h" |
| #include "chrome/browser/extensions/extension_function.h" |
| #include "chrome/browser/extensions/extension_function_test_utils.h" |
| #include "chrome/browser/extensions/extension_test_message_listener.h" |
| #include "chrome/browser/ui/browser.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| |
| using testing::_; |
| using testing::Return; |
| |
| using content::BrowserThread; |
| |
| namespace serial = extensions::api::serial; |
| |
| namespace { |
| |
| class SerialApiTest : public ExtensionApiTest { |
| public: |
| SerialApiTest() {} |
| }; |
| |
| } // namespace |
| |
| namespace extensions { |
| |
| class FakeSerialGetPortsFunction : public AsyncExtensionFunction { |
| public: |
| virtual bool RunImpl() OVERRIDE { |
| base::ListValue* ports = new base::ListValue(); |
| ports->Append(Value::CreateStringValue("/dev/fakeserial")); |
| ports->Append(Value::CreateStringValue("\\\\COM800\\")); |
| SetResult(ports); |
| SendResponse(true); |
| return true; |
| } |
| protected: |
| virtual ~FakeSerialGetPortsFunction() {} |
| }; |
| |
| class FakeEchoSerialConnection : public SerialConnection { |
| public: |
| explicit FakeEchoSerialConnection( |
| const std::string& port, |
| int bitrate, |
| serial::DataBit databit, |
| serial::ParityBit parity, |
| serial::StopBit stopbit, |
| const std::string& owner_extension_id) |
| : SerialConnection(port, bitrate, databit, parity, stopbit, |
| owner_extension_id), |
| opened_(true) { |
| Flush(); |
| opened_ = false; |
| } |
| |
| virtual ~FakeEchoSerialConnection() { |
| } |
| |
| virtual bool Open() { |
| DCHECK(!opened_); |
| opened_ = true; |
| return true; |
| } |
| |
| virtual void Close() { |
| DCHECK(opened_); |
| } |
| |
| virtual void Flush() { |
| DCHECK(opened_); |
| buffer_.clear(); |
| } |
| |
| virtual int Read(scoped_refptr<net::IOBufferWithSize> io_buffer) { |
| DCHECK(io_buffer->data()); |
| |
| if (buffer_.empty()) { |
| return 0; |
| } |
| char *data = io_buffer->data(); |
| int bytes_to_copy = io_buffer->size(); |
| while (bytes_to_copy-- && !buffer_.empty()) { |
| *data++ = buffer_.front(); |
| buffer_.pop_front(); |
| } |
| return io_buffer->size(); |
| } |
| |
| virtual int Write(scoped_refptr<net::IOBuffer> io_buffer, int byte_count) { |
| DCHECK(io_buffer.get()); |
| DCHECK_GE(byte_count, 0); |
| |
| char *data = io_buffer->data(); |
| int count = byte_count; |
| while (count--) |
| buffer_.push_back(*data++); |
| return byte_count; |
| } |
| |
| MOCK_METHOD1(GetControlSignals, bool(ControlSignals &)); |
| MOCK_METHOD1(SetControlSignals, bool(const ControlSignals &)); |
| |
| private: |
| bool opened_; |
| std::deque<char> buffer_; |
| |
| DISALLOW_COPY_AND_ASSIGN(FakeEchoSerialConnection); |
| }; |
| |
| class FakeSerialOpenFunction : public SerialOpenFunction { |
| protected: |
| virtual SerialConnection* CreateSerialConnection( |
| const std::string& port, |
| int bitrate, |
| serial::DataBit databit, |
| serial::ParityBit parity, |
| serial::StopBit stopbit, |
| const std::string& owner_extension_id) OVERRIDE { |
| FakeEchoSerialConnection* serial_connection = |
| new FakeEchoSerialConnection(port, bitrate, databit, parity, stopbit, |
| owner_extension_id); |
| EXPECT_CALL(*serial_connection, GetControlSignals(_)). |
| Times(1).WillOnce(Return(true)); |
| EXPECT_CALL(*serial_connection, SetControlSignals(_)). |
| Times(1).WillOnce(Return(true)); |
| return serial_connection; |
| } |
| virtual bool DoesPortExist(const std::string& port) OVERRIDE { |
| return true; |
| } |
| |
| protected: |
| virtual ~FakeSerialOpenFunction() {} |
| }; |
| |
| } // namespace extensions |
| |
| ExtensionFunction* FakeSerialGetPortsFunctionFactory() { |
| return new extensions::FakeSerialGetPortsFunction(); |
| } |
| |
| ExtensionFunction* FakeSerialOpenFunctionFactory() { |
| return new extensions::FakeSerialOpenFunction(); |
| } |
| |
| // Disable SIMULATE_SERIAL_PORTS only if all the following are true: |
| // |
| // 1. You have an Arduino or compatible board attached to your machine and |
| // properly appearing as the first virtual serial port ("first" is very loosely |
| // defined as whichever port shows up in serial.getPorts). We've tested only |
| // the Atmega32u4 Breakout Board and Arduino Leonardo; note that both these |
| // boards are based on the Atmel ATmega32u4, rather than the more common |
| // Arduino '328p with either FTDI or '8/16u2 USB interfaces. TODO: test more |
| // widely. |
| // |
| // 2. Your user has permission to read/write the port. For example, this might |
| // mean that your user is in the "tty" or "uucp" group on Ubuntu flavors of |
| // Linux, or else that the port's path (e.g., /dev/ttyACM0) has global |
| // read/write permissions. |
| // |
| // 3. You have uploaded a program to the board that does a byte-for-byte echo |
| // on the virtual serial port at 57600 bps. An example is at |
| // chrome/test/data/extensions/api_test/serial/api/serial_arduino_test.ino. |
| // |
| #define SIMULATE_SERIAL_PORTS (1) |
| IN_PROC_BROWSER_TEST_F(SerialApiTest, SerialFakeHardware) { |
| ResultCatcher catcher; |
| catcher.RestrictToProfile(browser()->profile()); |
| |
| #if SIMULATE_SERIAL_PORTS |
| ASSERT_TRUE(ExtensionFunctionDispatcher::OverrideFunction( |
| "serial.getPorts", |
| FakeSerialGetPortsFunctionFactory)); |
| ASSERT_TRUE(ExtensionFunctionDispatcher::OverrideFunction( |
| "serial.open", |
| FakeSerialOpenFunctionFactory)); |
| #endif |
| |
| ASSERT_TRUE(RunExtensionTest("serial/api")) << message_; |
| } |
| |
| IN_PROC_BROWSER_TEST_F(SerialApiTest, SerialRealHardware) { |
| ResultCatcher catcher; |
| catcher.RestrictToProfile(browser()->profile()); |
| |
| ASSERT_TRUE(RunExtensionTest("serial/real_hardware")) << message_; |
| } |