blob: d1bee86112f36fddfb21c999ae160fb32e061b99 [file] [log] [blame]
// Copyright 2015 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cobalt/dom/crypto.h"
#include "cobalt/base/polymorphic_downcast.h"
#include "cobalt/dom/dom_exception.h"
#include "cobalt/dom/dom_settings.h"
#include "cobalt/script/array_buffer_view.h"
#include "cobalt/script/global_environment.h"
#include "cobalt/script/javascript_engine.h"
#include "cobalt/script/script_exception.h"
#include "cobalt/script/testing/mock_exception_state.h"
#include "cobalt/script/typed_arrays.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cobalt {
namespace dom {
using script::testing::MockExceptionState;
using testing::_;
using testing::SaveArg;
using testing::StrictMock;
// TODO: Test arrays in other integer types.
// TODO: Test arrays in float types.
TEST(CryptoTest, GetRandomValues) {
StrictMock<MockExceptionState> exception_state;
scoped_ptr<script::JavaScriptEngine> javascript_engine =
script::JavaScriptEngine::CreateEngine();
scoped_refptr<script::GlobalEnvironment> global_environment =
javascript_engine->CreateGlobalEnvironment();
global_environment->CreateGlobalObject();
script::Handle<script::Uint8Array> array1 =
script::Uint8Array::New(global_environment, 16);
script::Handle<script::Uint8Array> array2 =
script::Uint8Array::New(global_environment, 16);
auto* array1_data = static_cast<uint8*>(array1->RawData());
for (uint32 i = 0; i < array1->Length(); ++i) {
DCHECK_EQ(0, array1_data[i]);
}
auto* array2_data = static_cast<uint8*>(array2->RawData());
for (uint32 i = 0; i < array2->Length(); ++i) {
DCHECK_EQ(0, array2_data[i]);
}
scoped_refptr<Crypto> crypto = new Crypto;
script::Handle<script::ArrayBufferView> casted_array1 =
script::ArrayBufferView::New(global_environment, *array1);
script::Handle<script::ArrayBufferView> result =
crypto->GetRandomValues(casted_array1, &exception_state);
EXPECT_TRUE(
casted_array1.GetScriptValue()->EqualTo(*(result.GetScriptValue())));
script::Handle<script::ArrayBufferView> casted_array2 =
script::ArrayBufferView::New(global_environment, *array2);
result = crypto->GetRandomValues(casted_array2, &exception_state);
EXPECT_TRUE(
casted_array2.GetScriptValue()->EqualTo(*(result.GetScriptValue())));
// This check is theoretically flaky as the two random sequences could be
// the same. But the probability is extremely low and we do want to catch
// the case when the two sequences are the same.
bool all_equal = true;
for (uint32 i = 0; i < array1->Length(); ++i) {
if (array1_data[i] != array2_data[i]) {
all_equal = false;
break;
}
}
EXPECT_FALSE(all_equal);
}
TEST(CryptoTest, NullArray) {
scoped_refptr<Crypto> crypto = new Crypto;
StrictMock<MockExceptionState> exception_state;
scoped_refptr<script::ScriptException> exception;
scoped_ptr<script::JavaScriptEngine> javascript_engine =
script::JavaScriptEngine::CreateEngine();
scoped_refptr<script::GlobalEnvironment> global_environment =
javascript_engine->CreateGlobalEnvironment();
global_environment->CreateGlobalObject();
EXPECT_CALL(exception_state, SetException(_))
.WillOnce(SaveArg<0>(&exception));
script::Handle<script::ArrayBufferView> empty_handle;
script::Handle<script::ArrayBufferView> result =
crypto->GetRandomValues(empty_handle, &exception_state);
EXPECT_TRUE(result.IsEmpty());
ASSERT_TRUE(exception);
EXPECT_EQ(DOMException::kTypeMismatchErr,
base::polymorphic_downcast<DOMException*>(exception.get())->code());
}
TEST(CryptoTest, LargeArray) {
// When array length exceeds 65536 GetRandomValues() should throw
// QuotaExceededErr.
scoped_refptr<Crypto> crypto = new Crypto;
StrictMock<MockExceptionState> exception_state;
scoped_ptr<script::JavaScriptEngine> javascript_engine =
script::JavaScriptEngine::CreateEngine();
scoped_refptr<script::GlobalEnvironment> global_environment =
javascript_engine->CreateGlobalEnvironment();
global_environment->CreateGlobalObject();
script::Handle<script::Uint8Array> array65537 =
script::Uint8Array::New(global_environment, 65537);
scoped_refptr<script::ScriptException> exception;
EXPECT_CALL(exception_state, SetException(_))
.WillOnce(SaveArg<0>(&exception));
script::Handle<script::ArrayBufferView> casted_array65537 =
script::ArrayBufferView::New(global_environment, *array65537);
script::Handle<script::ArrayBufferView> result =
crypto->GetRandomValues(casted_array65537, &exception_state);
EXPECT_TRUE(result.IsEmpty());
ASSERT_TRUE(exception);
EXPECT_EQ(DOMException::kQuotaExceededErr,
base::polymorphic_downcast<DOMException*>(exception.get())->code());
// Also ensure that we can work with array whose length is exactly 65536.
script::Handle<script::Uint8Array> array65536 =
script::Uint8Array::New(global_environment, 65536);
script::Handle<script::ArrayBufferView> casted_array65536 =
script::ArrayBufferView::New(global_environment, *array65536);
result = crypto->GetRandomValues(casted_array65536, &exception_state);
EXPECT_TRUE(
casted_array65536.GetScriptValue()->EqualTo(*(result.GetScriptValue())));
}
} // namespace dom
} // namespace cobalt