blob: a12889e3d04c3d79e2e420712074732ff65bfd2c [file] [log] [blame]
// Copyright 2019 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 "third_party/blink/renderer/core/css/cssom/cross_thread_style_value.h"
#include <memory>
#include <utility>
#include "base/single_thread_task_runner.h"
#include "base/synchronization/waitable_event.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/css/cssom/cross_thread_color_value.h"
#include "third_party/blink/renderer/core/css/cssom/cross_thread_keyword_value.h"
#include "third_party/blink/renderer/core/css/cssom/cross_thread_unit_value.h"
#include "third_party/blink/renderer/core/css/cssom/cross_thread_unparsed_value.h"
#include "third_party/blink/renderer/core/css/cssom/cross_thread_unsupported_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_keyword_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_style_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_unit_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_unparsed_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_unsupported_color_value.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
namespace blink {
class CrossThreadStyleValueTest : public testing::Test {
public:
void ShutDown(base::WaitableEvent* waitable_event) {
DCHECK(!IsMainThread());
waitable_event->Signal();
}
void ShutDownThread() {
base::WaitableEvent waitable_event;
PostCrossThreadTask(
*thread_->GetTaskRunner(), FROM_HERE,
CrossThreadBindOnce(&CrossThreadStyleValueTest::ShutDown,
CrossThreadUnretained(this),
CrossThreadUnretained(&waitable_event)));
waitable_event.Wait();
}
void CheckUnsupportedValue(
base::WaitableEvent* waitable_event,
std::unique_ptr<CrossThreadUnsupportedValue> value) {
DCHECK(!IsMainThread());
EXPECT_EQ(value->value_, "Unsupported");
waitable_event->Signal();
}
void CheckKeywordValue(base::WaitableEvent* waitable_event,
std::unique_ptr<CrossThreadKeywordValue> value) {
DCHECK(!IsMainThread());
EXPECT_EQ(value->keyword_value_, "Keyword");
waitable_event->Signal();
}
void CheckUnparsedValue(base::WaitableEvent* waitable_event,
std::unique_ptr<CrossThreadUnparsedValue> value) {
DCHECK(!IsMainThread());
EXPECT_EQ(value->value_, "Unparsed");
waitable_event->Signal();
}
void CheckUnitValue(base::WaitableEvent* waitable_event,
std::unique_ptr<CrossThreadUnitValue> value) {
DCHECK(!IsMainThread());
EXPECT_EQ(value->value_, 1);
EXPECT_EQ(value->unit_, CSSPrimitiveValue::UnitType::kDegrees);
waitable_event->Signal();
}
void CheckColorValue(base::WaitableEvent* waitable_event,
std::unique_ptr<CrossThreadColorValue> value) {
DCHECK(!IsMainThread());
EXPECT_EQ(value->value_, Color(0, 255, 0));
waitable_event->Signal();
}
protected:
std::unique_ptr<blink::Thread> thread_;
};
// Ensure that a CrossThreadUnsupportedValue can be safely passed cross
// threads.
TEST_F(CrossThreadStyleValueTest, PassUnsupportedValueCrossThread) {
std::unique_ptr<CrossThreadUnsupportedValue> value =
std::make_unique<CrossThreadUnsupportedValue>("Unsupported");
DCHECK(value);
// Use a Thread to emulate worklet thread.
thread_ = blink::Thread::CreateThread(
ThreadCreationParams(ThreadType::kTestThread).SetSupportsGC(true));
base::WaitableEvent waitable_event;
PostCrossThreadTask(
*thread_->GetTaskRunner(), FROM_HERE,
CrossThreadBindOnce(&CrossThreadStyleValueTest::CheckUnsupportedValue,
CrossThreadUnretained(this),
CrossThreadUnretained(&waitable_event),
std::move(value)));
waitable_event.Wait();
ShutDownThread();
}
TEST_F(CrossThreadStyleValueTest, CrossThreadUnsupportedValueToCSSStyleValue) {
std::unique_ptr<CrossThreadUnsupportedValue> value =
std::make_unique<CrossThreadUnsupportedValue>("Unsupported");
DCHECK(value);
const CSSStyleValue* const style_value = value->ToCSSStyleValue();
EXPECT_EQ(style_value->GetType(),
CSSStyleValue::StyleValueType::kUnknownType);
EXPECT_EQ(style_value->CSSText(), "Unsupported");
}
TEST_F(CrossThreadStyleValueTest, PassUnparsedValueCrossThread) {
std::unique_ptr<CrossThreadUnparsedValue> value =
std::make_unique<CrossThreadUnparsedValue>("Unparsed");
DCHECK(value);
// Use a Thread to emulate worklet thread.
thread_ = blink::Thread::CreateThread(
ThreadCreationParams(ThreadType::kTestThread).SetSupportsGC(true));
base::WaitableEvent waitable_event;
PostCrossThreadTask(
*thread_->GetTaskRunner(), FROM_HERE,
CrossThreadBindOnce(&CrossThreadStyleValueTest::CheckUnparsedValue,
CrossThreadUnretained(this),
CrossThreadUnretained(&waitable_event),
std::move(value)));
waitable_event.Wait();
ShutDownThread();
}
TEST_F(CrossThreadStyleValueTest, CrossThreadUnparsedValueToCSSStyleValue) {
std::unique_ptr<CrossThreadUnparsedValue> value =
std::make_unique<CrossThreadUnparsedValue>("Unparsed");
DCHECK(value);
CSSStyleValue* style_value = value->ToCSSStyleValue();
EXPECT_EQ(style_value->GetType(),
CSSStyleValue::StyleValueType::kUnparsedType);
EXPECT_EQ(static_cast<CSSUnparsedValue*>(style_value)->ToString(),
"Unparsed");
}
TEST_F(CrossThreadStyleValueTest, PassKeywordValueCrossThread) {
std::unique_ptr<CrossThreadKeywordValue> value =
std::make_unique<CrossThreadKeywordValue>("Keyword");
DCHECK(value);
// Use a Thread to emulate worklet thread.
thread_ = blink::Thread::CreateThread(
ThreadCreationParams(ThreadType::kTestThread).SetSupportsGC(true));
base::WaitableEvent waitable_event;
PostCrossThreadTask(
*thread_->GetTaskRunner(), FROM_HERE,
CrossThreadBindOnce(&CrossThreadStyleValueTest::CheckKeywordValue,
CrossThreadUnretained(this),
CrossThreadUnretained(&waitable_event),
std::move(value)));
waitable_event.Wait();
ShutDownThread();
}
TEST_F(CrossThreadStyleValueTest, CrossThreadKeywordValueToCSSStyleValue) {
std::unique_ptr<CrossThreadKeywordValue> value =
std::make_unique<CrossThreadKeywordValue>("Keyword");
DCHECK(value);
CSSStyleValue* style_value = value->ToCSSStyleValue();
EXPECT_EQ(style_value->GetType(),
CSSStyleValue::StyleValueType::kKeywordType);
EXPECT_EQ(static_cast<CSSKeywordValue*>(style_value)->value(), "Keyword");
}
TEST_F(CrossThreadStyleValueTest, PassUnitValueCrossThread) {
std::unique_ptr<CrossThreadUnitValue> value =
std::make_unique<CrossThreadUnitValue>(
1, CSSPrimitiveValue::UnitType::kDegrees);
DCHECK(value);
// Use a Thread to emulate worklet thread.
thread_ = blink::Thread::CreateThread(
ThreadCreationParams(ThreadType::kTestThread).SetSupportsGC(true));
base::WaitableEvent waitable_event;
PostCrossThreadTask(
*thread_->GetTaskRunner(), FROM_HERE,
CrossThreadBindOnce(&CrossThreadStyleValueTest::CheckUnitValue,
CrossThreadUnretained(this),
CrossThreadUnretained(&waitable_event),
std::move(value)));
waitable_event.Wait();
ShutDownThread();
}
TEST_F(CrossThreadStyleValueTest, CrossThreadUnitValueToCSSStyleValue) {
std::unique_ptr<CrossThreadUnitValue> value =
std::make_unique<CrossThreadUnitValue>(
1, CSSPrimitiveValue::UnitType::kDegrees);
DCHECK(value);
CSSStyleValue* style_value = value->ToCSSStyleValue();
EXPECT_EQ(style_value->GetType(), CSSStyleValue::StyleValueType::kUnitType);
EXPECT_EQ(static_cast<CSSUnitValue*>(style_value)->value(), 1);
EXPECT_EQ(static_cast<CSSUnitValue*>(style_value)->unit(), "deg");
}
TEST_F(CrossThreadStyleValueTest, PassColorValueCrossThread) {
std::unique_ptr<CrossThreadColorValue> value =
std::make_unique<CrossThreadColorValue>(Color(0, 255, 0));
DCHECK(value);
// Use a Thread to emulate worklet thread.
thread_ = blink::Thread::CreateThread(
ThreadCreationParams(ThreadType::kTestThread).SetSupportsGC(true));
base::WaitableEvent waitable_event;
PostCrossThreadTask(
*thread_->GetTaskRunner(), FROM_HERE,
CrossThreadBindOnce(&CrossThreadStyleValueTest::CheckColorValue,
CrossThreadUnretained(this),
CrossThreadUnretained(&waitable_event),
std::move(value)));
waitable_event.Wait();
ShutDownThread();
}
TEST_F(CrossThreadStyleValueTest, CrossThreadColorValueToCSSStyleValue) {
std::unique_ptr<CrossThreadColorValue> value =
std::make_unique<CrossThreadColorValue>(Color(0, 255, 0));
DCHECK(value);
CSSStyleValue* style_value = value->ToCSSStyleValue();
EXPECT_EQ(style_value->GetType(),
CSSStyleValue::StyleValueType::kUnsupportedColorType);
EXPECT_EQ(static_cast<CSSUnsupportedColorValue*>(style_value)->Value(),
Color(0, 255, 0));
}
TEST_F(CrossThreadStyleValueTest, ComparingNullValues) {
// Two null values are equal to each other.
std::unique_ptr<CrossThreadStyleValue> null_value1(nullptr);
std::unique_ptr<CrossThreadStyleValue> null_value2(nullptr);
EXPECT_TRUE(DataEquivalent(null_value1, null_value2));
// If one argument is null and the other isn't they are never equal.
std::unique_ptr<CrossThreadStyleValue> keyword_value(
new CrossThreadKeywordValue("keyword"));
std::unique_ptr<CrossThreadStyleValue> unit_value(
new CrossThreadUnitValue(1, CSSPrimitiveValue::UnitType::kDegrees));
std::unique_ptr<CrossThreadStyleValue> unsupported_value(
new CrossThreadUnsupportedValue("unsupported"));
EXPECT_FALSE(DataEquivalent(null_value1, keyword_value));
EXPECT_FALSE(DataEquivalent(null_value1, unit_value));
EXPECT_FALSE(DataEquivalent(null_value1, unsupported_value));
EXPECT_FALSE(DataEquivalent(keyword_value, null_value1));
EXPECT_FALSE(DataEquivalent(unit_value, null_value1));
EXPECT_FALSE(DataEquivalent(unsupported_value, null_value1));
}
TEST_F(CrossThreadStyleValueTest, ComparingDifferentTypes) {
// Mismatching types are never equal.
std::unique_ptr<CrossThreadStyleValue> keyword_value(
new CrossThreadKeywordValue("keyword"));
std::unique_ptr<CrossThreadStyleValue> unit_value(
new CrossThreadUnitValue(1, CSSPrimitiveValue::UnitType::kDegrees));
std::unique_ptr<CrossThreadStyleValue> unsupported_value(
new CrossThreadUnsupportedValue("unsupported"));
EXPECT_FALSE(DataEquivalent(keyword_value, unit_value));
EXPECT_FALSE(DataEquivalent(keyword_value, unsupported_value));
EXPECT_FALSE(DataEquivalent(unit_value, unsupported_value));
EXPECT_FALSE(DataEquivalent(unit_value, keyword_value));
EXPECT_FALSE(DataEquivalent(unsupported_value, keyword_value));
EXPECT_FALSE(DataEquivalent(unsupported_value, unit_value));
}
TEST_F(CrossThreadStyleValueTest, ComparingCrossThreadKeywordValue) {
// CrossThreadKeywordValues are compared on their keyword; if it is equal then
// so are they.
std::unique_ptr<CrossThreadStyleValue> keyword_value_1(
new CrossThreadKeywordValue("keyword"));
std::unique_ptr<CrossThreadStyleValue> keyword_value_2(
new CrossThreadKeywordValue("keyword"));
std::unique_ptr<CrossThreadStyleValue> keyword_value_3(
new CrossThreadKeywordValue("different"));
EXPECT_TRUE(DataEquivalent(keyword_value_1, keyword_value_2));
EXPECT_FALSE(DataEquivalent(keyword_value_1, keyword_value_3));
}
TEST_F(CrossThreadStyleValueTest, ComparingCrossThreadUnitValue) {
// CrossThreadUnitValues are compared based on their value and unit type; both
// have to match. There are a lot of unit types; we just test a single sample.
std::unique_ptr<CrossThreadStyleValue> unit_value_1(
new CrossThreadUnitValue(1, CSSPrimitiveValue::UnitType::kDegrees));
// Same value, same unit.
std::unique_ptr<CrossThreadStyleValue> unit_value_2(
new CrossThreadUnitValue(1, CSSPrimitiveValue::UnitType::kDegrees));
EXPECT_TRUE(DataEquivalent(unit_value_1, unit_value_2));
// Same value, different unit.
std::unique_ptr<CrossThreadStyleValue> unit_value_3(
new CrossThreadUnitValue(1, CSSPrimitiveValue::UnitType::kPoints));
EXPECT_FALSE(DataEquivalent(unit_value_1, unit_value_3));
// Different value, same unit.
std::unique_ptr<CrossThreadStyleValue> unit_value_4(
new CrossThreadUnitValue(2, CSSPrimitiveValue::UnitType::kDegrees));
EXPECT_FALSE(DataEquivalent(unit_value_1, unit_value_4));
}
TEST_F(CrossThreadStyleValueTest, ComparingCrossThreadColorValue) {
// CrossThreadColorValues are compared on their color channel values; all
// channels must match.
std::unique_ptr<CrossThreadStyleValue> color_value_1(
new CrossThreadColorValue(Color(0, 0, 0)));
std::unique_ptr<CrossThreadStyleValue> color_value_2(
new CrossThreadColorValue(Color(0, 0, 0)));
std::unique_ptr<CrossThreadStyleValue> color_value_3(
new CrossThreadColorValue(Color(0, 255, 0)));
EXPECT_TRUE(DataEquivalent(color_value_1, color_value_2));
EXPECT_FALSE(DataEquivalent(color_value_1, color_value_3));
}
TEST_F(CrossThreadStyleValueTest, ComparingCrossThreadUnsupportedValue) {
// CrossThreadUnsupportedValues are compared on their value; if it is equal
// then so are they.
std::unique_ptr<CrossThreadStyleValue> unsupported_value_1(
new CrossThreadUnsupportedValue("value"));
std::unique_ptr<CrossThreadStyleValue> unsupported_value_2(
new CrossThreadUnsupportedValue("value"));
std::unique_ptr<CrossThreadStyleValue> unsupported_value_3(
new CrossThreadUnsupportedValue("different"));
EXPECT_TRUE(DataEquivalent(unsupported_value_1, unsupported_value_2));
EXPECT_FALSE(DataEquivalent(unsupported_value_1, unsupported_value_3));
}
} // namespace blink