blob: c6508663db4b747d1a4817114107de2ed968fe6f [file] [log] [blame]
// Copyright 2014 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 <queue>
#include <utility>
#include "device/serial/data_source_sender.h"
#include "device/serial/data_stream.mojom.h"
#include "extensions/renderer/api_test_base.h"
#include "gin/dictionary.h"
#include "gin/wrappable.h"
#include "grit/extensions_renderer_resources.h"
namespace extensions {
class DataReceiverFactory : public gin::Wrappable<DataReceiverFactory> {
public:
using Callback = base::Callback<void(
mojo::InterfaceRequest<device::serial::DataSource>,
mojo::InterfacePtr<device::serial::DataSourceClient>)>;
static gin::Handle<DataReceiverFactory> Create(v8::Isolate* isolate,
const Callback& callback) {
return gin::CreateHandle(isolate,
new DataReceiverFactory(callback, isolate));
}
gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
v8::Isolate* isolate) override {
return Wrappable<DataReceiverFactory>::GetObjectTemplateBuilder(isolate)
.SetMethod("create", &DataReceiverFactory::CreateReceiver);
}
gin::Dictionary CreateReceiver() {
mojo::InterfacePtr<device::serial::DataSource> sink;
mojo::InterfacePtr<device::serial::DataSourceClient> client;
mojo::InterfaceRequest<device::serial::DataSourceClient> client_request =
mojo::GetProxy(&client);
callback_.Run(mojo::GetProxy(&sink), std::move(client));
gin::Dictionary result = gin::Dictionary::CreateEmpty(isolate_);
result.Set("source", sink.PassInterface().PassHandle().release());
result.Set("client", client_request.PassMessagePipe().release());
return result;
}
static gin::WrapperInfo kWrapperInfo;
private:
DataReceiverFactory(const Callback& callback, v8::Isolate* isolate)
: callback_(callback), isolate_(isolate) {}
base::Callback<void(mojo::InterfaceRequest<device::serial::DataSource>,
mojo::InterfacePtr<device::serial::DataSourceClient>)>
callback_;
v8::Isolate* isolate_;
};
gin::WrapperInfo DataReceiverFactory::kWrapperInfo = {gin::kEmbedderNativeGin};
// Runs tests defined in extensions/test/data/data_receiver_unittest.js
class DataReceiverTest : public ApiTestBase {
public:
DataReceiverTest() {}
void SetUp() override {
ApiTestBase::SetUp();
gin::ModuleRegistry::From(env()->context()->v8_context())
->AddBuiltinModule(env()->isolate(),
"device/serial/data_receiver_test_factory",
DataReceiverFactory::Create(
env()->isolate(),
base::Bind(&DataReceiverTest::CreateDataSource,
base::Unretained(this))).ToV8());
}
void TearDown() override {
if (sender_.get()) {
sender_->ShutDown();
sender_ = NULL;
}
ApiTestBase::TearDown();
}
std::queue<int32_t> error_to_send_;
std::queue<std::string> data_to_send_;
private:
void CreateDataSource(
mojo::InterfaceRequest<device::serial::DataSource> request,
mojo::InterfacePtr<device::serial::DataSourceClient> client) {
sender_ = new device::DataSourceSender(
std::move(request), std::move(client),
base::Bind(&DataReceiverTest::ReadyToSend, base::Unretained(this)),
base::Bind(base::DoNothing));
}
void ReadyToSend(scoped_ptr<device::WritableBuffer> buffer) {
if (data_to_send_.empty() && error_to_send_.empty())
return;
std::string data;
int32_t error = 0;
if (!data_to_send_.empty()) {
data = data_to_send_.front();
data_to_send_.pop();
}
if (!error_to_send_.empty()) {
error = error_to_send_.front();
error_to_send_.pop();
}
DCHECK(buffer->GetSize() >= static_cast<uint32_t>(data.size()));
memcpy(buffer->GetData(), data.c_str(), data.size());
if (error)
buffer->DoneWithError(data.size(), error);
else
buffer->Done(data.size());
}
scoped_refptr<device::DataSourceSender> sender_;
DISALLOW_COPY_AND_ASSIGN(DataReceiverTest);
};
TEST_F(DataReceiverTest, Receive) {
data_to_send_.push("a");
RunTest("data_receiver_unittest.js", "testReceive");
}
TEST_F(DataReceiverTest, ReceiveError) {
error_to_send_.push(1);
RunTest("data_receiver_unittest.js", "testReceiveError");
}
TEST_F(DataReceiverTest, ReceiveDataAndError) {
data_to_send_.push("a");
data_to_send_.push("b");
error_to_send_.push(1);
RunTest("data_receiver_unittest.js", "testReceiveDataAndError");
}
TEST_F(DataReceiverTest, ReceiveErrorThenData) {
data_to_send_.push("");
data_to_send_.push("a");
error_to_send_.push(1);
RunTest("data_receiver_unittest.js", "testReceiveErrorThenData");
}
TEST_F(DataReceiverTest, ReceiveBeforeAndAfterSerialization) {
data_to_send_.push("a");
data_to_send_.push("b");
RunTest("data_receiver_unittest.js",
"testReceiveBeforeAndAfterSerialization");
}
TEST_F(DataReceiverTest, ReceiveErrorSerialization) {
error_to_send_.push(1);
error_to_send_.push(3);
RunTest("data_receiver_unittest.js", "testReceiveErrorSerialization");
}
TEST_F(DataReceiverTest, ReceiveDataAndErrorSerialization) {
data_to_send_.push("a");
data_to_send_.push("b");
error_to_send_.push(1);
error_to_send_.push(3);
RunTest("data_receiver_unittest.js", "testReceiveDataAndErrorSerialization");
}
TEST_F(DataReceiverTest, SerializeDuringReceive) {
data_to_send_.push("a");
RunTest("data_receiver_unittest.js", "testSerializeDuringReceive");
}
TEST_F(DataReceiverTest, SerializeAfterClose) {
data_to_send_.push("a");
RunTest("data_receiver_unittest.js", "testSerializeAfterClose");
}
} // namespace extensions