1// Copyright 2014 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 "base/basictypes.h"
6#include "base/float_util.h"
7#include "base/memory/scoped_ptr.h"
8#include "base/strings/stringprintf.h"
9#include "content/common/android/gin_java_bridge_value.h"
10#include "content/renderer/java/gin_java_bridge_value_converter.h"
11#include "testing/gtest/include/gtest/gtest.h"
12#include "v8/include/v8.h"
13
14namespace content {
15
16class GinJavaBridgeValueConverterTest : public testing::Test {
17 public:
18  GinJavaBridgeValueConverterTest()
19      : isolate_(v8::Isolate::GetCurrent()) {
20  }
21
22 protected:
23  virtual void SetUp() {
24    v8::HandleScope handle_scope(isolate_);
25    v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate_);
26    context_.Reset(isolate_, v8::Context::New(isolate_, NULL, global));
27  }
28
29  virtual void TearDown() {
30    context_.Reset();
31  }
32
33  v8::Isolate* isolate_;
34
35  // Context for the JavaScript in the test.
36  v8::Persistent<v8::Context> context_;
37};
38
39TEST_F(GinJavaBridgeValueConverterTest, BasicValues) {
40  v8::HandleScope handle_scope(isolate_);
41  v8::Local<v8::Context> context =
42      v8::Local<v8::Context>::New(isolate_, context_);
43  v8::Context::Scope context_scope(context);
44
45  scoped_ptr<GinJavaBridgeValueConverter> converter(
46      new GinJavaBridgeValueConverter());
47
48  v8::Handle<v8::Primitive> v8_undefined(v8::Undefined(isolate_));
49  scoped_ptr<base::Value> undefined(
50      converter->FromV8Value(v8_undefined, context));
51  ASSERT_TRUE(undefined.get());
52  EXPECT_TRUE(GinJavaBridgeValue::ContainsGinJavaBridgeValue(undefined.get()));
53  scoped_ptr<const GinJavaBridgeValue> undefined_value(
54      GinJavaBridgeValue::FromValue(undefined.get()));
55  ASSERT_TRUE(undefined_value.get());
56  EXPECT_TRUE(undefined_value->IsType(GinJavaBridgeValue::TYPE_UNDEFINED));
57
58  v8::Handle<v8::Number> v8_infinity(
59      v8::Number::New(isolate_, std::numeric_limits<double>::infinity()));
60  scoped_ptr<base::Value> infinity(
61      converter->FromV8Value(v8_infinity, context));
62  ASSERT_TRUE(infinity.get());
63  EXPECT_TRUE(
64      GinJavaBridgeValue::ContainsGinJavaBridgeValue(infinity.get()));
65  scoped_ptr<const GinJavaBridgeValue> infinity_value(
66      GinJavaBridgeValue::FromValue(infinity.get()));
67  ASSERT_TRUE(infinity_value.get());
68  float native_float;
69  EXPECT_TRUE(
70      infinity_value->IsType(GinJavaBridgeValue::TYPE_NONFINITE));
71  EXPECT_TRUE(infinity_value->GetAsNonFinite(&native_float));
72  EXPECT_FALSE(base::IsFinite(native_float));
73  EXPECT_FALSE(base::IsNaN(native_float));
74}
75
76TEST_F(GinJavaBridgeValueConverterTest, ArrayBuffer) {
77  v8::HandleScope handle_scope(isolate_);
78  v8::Local<v8::Context> context =
79      v8::Local<v8::Context>::New(isolate_, context_);
80  v8::Context::Scope context_scope(context);
81
82  scoped_ptr<GinJavaBridgeValueConverter> converter(
83      new GinJavaBridgeValueConverter());
84
85  v8::Handle<v8::ArrayBuffer> v8_array_buffer(
86      v8::ArrayBuffer::New(isolate_, 0));
87  scoped_ptr<base::Value> undefined(
88      converter->FromV8Value(v8_array_buffer, context));
89  ASSERT_TRUE(undefined.get());
90  EXPECT_TRUE(GinJavaBridgeValue::ContainsGinJavaBridgeValue(undefined.get()));
91  scoped_ptr<const GinJavaBridgeValue> undefined_value(
92      GinJavaBridgeValue::FromValue(undefined.get()));
93  ASSERT_TRUE(undefined_value.get());
94  EXPECT_TRUE(undefined_value->IsType(GinJavaBridgeValue::TYPE_UNDEFINED));
95}
96
97TEST_F(GinJavaBridgeValueConverterTest, TypedArrays) {
98  v8::HandleScope handle_scope(isolate_);
99  v8::Local<v8::Context> context =
100      v8::Local<v8::Context>::New(isolate_, context_);
101  v8::Context::Scope context_scope(context);
102
103  scoped_ptr<GinJavaBridgeValueConverter> converter(
104      new GinJavaBridgeValueConverter());
105
106  const char* source_template = "(function() {"
107      "var array_buffer = new ArrayBuffer(%s);"
108      "var array_view = new %s(array_buffer);"
109      "array_view[0] = 42;"
110      "return array_view;"
111      "})();";
112  const char* array_types[] = {
113    "1", "Int8Array", "1", "Uint8Array", "1", "Uint8ClampedArray",
114    "2", "Int16Array", "2", "Uint16Array",
115    "4", "Int32Array", "4", "Uint32Array",
116    "4", "Float32Array", "8", "Float64Array"
117  };
118  for (size_t i = 0; i < arraysize(array_types); i += 2) {
119    const char* typed_array_type = array_types[i + 1];
120    v8::Handle<v8::Script> script(v8::Script::Compile(v8::String::NewFromUtf8(
121        isolate_,
122        base::StringPrintf(
123            source_template, array_types[i], typed_array_type).c_str())));
124    v8::Handle<v8::Value> v8_typed_array = script->Run();
125    scoped_ptr<base::Value> list_value(
126        converter->FromV8Value(v8_typed_array, context));
127    ASSERT_TRUE(list_value.get()) << typed_array_type;
128    EXPECT_TRUE(list_value->IsType(base::Value::TYPE_LIST)) << typed_array_type;
129    base::ListValue* list;
130    ASSERT_TRUE(list_value->GetAsList(&list)) << typed_array_type;
131    EXPECT_EQ(1u, list->GetSize()) << typed_array_type;
132    double first_element;
133    ASSERT_TRUE(list->GetDouble(0, &first_element)) << typed_array_type;
134    EXPECT_EQ(42.0, first_element) << typed_array_type;
135  }
136}
137
138}  // namespace content
139