blob: ea11deb4e7e21de77b16189e77535a09035e0102 [file] [log] [blame]
// Copyright 2015 The Chromium Authors
// 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/modules/mediastream/media_constraints.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_string_stringsequence.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_constrain_dom_string_parameters.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_track_constraints.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_typedefs.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_union_constraindomstringparameters_string_stringsequence.h"
#include "third_party/blink/renderer/modules/mediastream/media_constraints_impl.h"
namespace blink {
// The MediaTrackConstraintsTest group tests the types declared in
// third_party/blink/renderer/platform/mediastream/media_constraints.h
TEST(MediaTrackConstraintsTest, LongConstraint) {
LongConstraint range_constraint(nullptr);
range_constraint.SetMin(5);
range_constraint.SetMax(6);
EXPECT_TRUE(range_constraint.Matches(5));
EXPECT_TRUE(range_constraint.Matches(6));
EXPECT_FALSE(range_constraint.Matches(4));
EXPECT_FALSE(range_constraint.Matches(7));
LongConstraint exact_constraint(nullptr);
exact_constraint.SetExact(5);
EXPECT_FALSE(exact_constraint.Matches(4));
EXPECT_TRUE(exact_constraint.Matches(5));
EXPECT_FALSE(exact_constraint.Matches(6));
}
TEST(MediaTrackConstraintsTest, DoubleConstraint) {
DoubleConstraint range_constraint(nullptr);
EXPECT_TRUE(range_constraint.IsUnconstrained());
range_constraint.SetMin(5.0);
range_constraint.SetMax(6.5);
EXPECT_FALSE(range_constraint.IsUnconstrained());
// Matching within epsilon
EXPECT_TRUE(
range_constraint.Matches(5.0 - DoubleConstraint::kConstraintEpsilon / 2));
EXPECT_TRUE(
range_constraint.Matches(6.5 + DoubleConstraint::kConstraintEpsilon / 2));
DoubleConstraint exact_constraint(nullptr);
exact_constraint.SetExact(5.0);
EXPECT_FALSE(range_constraint.IsUnconstrained());
EXPECT_FALSE(exact_constraint.Matches(4.9));
EXPECT_TRUE(exact_constraint.Matches(5.0));
EXPECT_TRUE(
exact_constraint.Matches(5.0 - DoubleConstraint::kConstraintEpsilon / 2));
EXPECT_TRUE(
exact_constraint.Matches(5.0 + DoubleConstraint::kConstraintEpsilon / 2));
EXPECT_FALSE(exact_constraint.Matches(5.1));
}
TEST(MediaTrackConstraintsTest, BooleanConstraint) {
BooleanConstraint bool_constraint(nullptr);
EXPECT_TRUE(bool_constraint.IsUnconstrained());
EXPECT_TRUE(bool_constraint.Matches(false));
EXPECT_TRUE(bool_constraint.Matches(true));
bool_constraint.SetExact(false);
EXPECT_FALSE(bool_constraint.IsUnconstrained());
EXPECT_FALSE(bool_constraint.Matches(true));
EXPECT_TRUE(bool_constraint.Matches(false));
bool_constraint.SetExact(true);
EXPECT_FALSE(bool_constraint.Matches(false));
EXPECT_TRUE(bool_constraint.Matches(true));
}
TEST(MediaTrackConstraintsTest, ConstraintSetEmpty) {
MediaTrackConstraintSetPlatform the_set;
EXPECT_TRUE(the_set.IsUnconstrained());
the_set.echo_cancellation.SetExact(false);
EXPECT_FALSE(the_set.IsUnconstrained());
}
TEST(MediaTrackConstraintsTest, ConstraintName) {
const char* the_name = "name";
BooleanConstraint bool_constraint(the_name);
EXPECT_EQ(the_name, bool_constraint.GetName());
}
TEST(MediaTrackConstraintsTest, MandatoryChecks) {
MediaTrackConstraintSetPlatform the_set;
String found_name;
EXPECT_FALSE(the_set.HasMandatory());
EXPECT_FALSE(the_set.HasMandatoryOutsideSet({"width"}, found_name));
EXPECT_FALSE(the_set.width.HasMandatory());
the_set.width.SetMax(240);
EXPECT_TRUE(the_set.width.HasMandatory());
EXPECT_TRUE(the_set.HasMandatory());
EXPECT_FALSE(the_set.HasMandatoryOutsideSet({"width"}, found_name));
EXPECT_TRUE(the_set.HasMandatoryOutsideSet({"height"}, found_name));
EXPECT_EQ("width", found_name);
the_set.echo_cancellation.SetExact(true);
EXPECT_TRUE(the_set.HasMandatoryOutsideSet({"width"}, found_name));
EXPECT_EQ("echoCancellation", found_name);
}
TEST(MediaTrackConstraintsTest, SetToString) {
MediaTrackConstraintSetPlatform the_set;
EXPECT_EQ("", the_set.ToString());
the_set.width.SetMax(240);
EXPECT_EQ("width: {max: 240}", the_set.ToString().Utf8());
the_set.echo_cancellation.SetIdeal(true);
EXPECT_EQ("width: {max: 240}, echoCancellation: {ideal: true}",
the_set.ToString().Utf8());
}
TEST(MediaTrackConstraintsTest, ConstraintsToString) {
MediaConstraints the_constraints;
MediaTrackConstraintSetPlatform basic;
Vector<MediaTrackConstraintSetPlatform> advanced(static_cast<size_t>(1));
basic.width.SetMax(240);
advanced[0].echo_cancellation.SetExact(true);
the_constraints.Initialize(basic, advanced);
EXPECT_EQ(
"{width: {max: 240}, advanced: [{echoCancellation: {exact: true}}]}",
the_constraints.ToString().Utf8());
MediaConstraints null_constraints;
EXPECT_EQ("", null_constraints.ToString().Utf8());
MediaConstraints pan_constraints;
MediaTrackConstraintSetPlatform pan_basic;
Vector<MediaTrackConstraintSetPlatform> pan_advanced(static_cast<size_t>(1));
pan_basic.pan.SetIsPresent(false);
pan_advanced[0].pan.SetIsPresent(true);
pan_constraints.Initialize(pan_basic, pan_advanced);
EXPECT_EQ("{advanced: [{pan: {}}]}", pan_constraints.ToString().Utf8());
MediaConstraints tilt_constraints;
MediaTrackConstraintSetPlatform tilt_basic;
Vector<MediaTrackConstraintSetPlatform> tilt_advanced(static_cast<size_t>(1));
tilt_basic.tilt.SetIsPresent(false);
tilt_advanced[0].tilt.SetIsPresent(true);
tilt_constraints.Initialize(tilt_basic, tilt_advanced);
EXPECT_EQ("{advanced: [{tilt: {}}]}", tilt_constraints.ToString().Utf8());
MediaConstraints zoom_constraints;
MediaTrackConstraintSetPlatform zoom_basic;
Vector<MediaTrackConstraintSetPlatform> zoom_advanced(static_cast<size_t>(1));
zoom_basic.zoom.SetIsPresent(false);
zoom_advanced[0].zoom.SetIsPresent(true);
zoom_constraints.Initialize(zoom_basic, zoom_advanced);
EXPECT_EQ("{advanced: [{zoom: {}}]}", zoom_constraints.ToString().Utf8());
// TODO(crbug.com/1086338): Test other constraints with IsPresent.
}
TEST(MediaTrackConstraintsTest, ConvertWebConstraintsBasic) {
MediaConstraints input;
[[maybe_unused]] MediaTrackConstraints* output =
media_constraints_impl::ConvertConstraints(input);
}
TEST(MediaTrackConstraintsTest, ConvertWebSingleStringConstraint) {
MediaConstraints input;
MediaTrackConstraintSetPlatform basic;
Vector<MediaTrackConstraintSetPlatform> advanced;
basic.facing_mode.SetIdeal(Vector<String>({"foo"}));
input.Initialize(basic, advanced);
MediaTrackConstraints* output =
media_constraints_impl::ConvertConstraints(input);
ASSERT_TRUE(output->hasFacingMode());
ASSERT_TRUE(output->facingMode()->IsString());
EXPECT_EQ("foo", output->facingMode()->GetAsString());
}
TEST(MediaTrackConstraintsTest, ConvertWebDoubleStringConstraint) {
MediaConstraints input;
Vector<String> buffer(static_cast<size_t>(2u));
buffer[0] = "foo";
buffer[1] = "bar";
MediaTrackConstraintSetPlatform basic;
Vector<MediaTrackConstraintSetPlatform> advanced;
basic.facing_mode.SetIdeal(buffer);
input.Initialize(basic, advanced);
MediaTrackConstraints* output =
media_constraints_impl::ConvertConstraints(input);
ASSERT_TRUE(output->hasFacingMode());
ASSERT_TRUE(output->facingMode()->IsStringSequence());
const auto& out_buffer = output->facingMode()->GetAsStringSequence();
EXPECT_EQ("foo", out_buffer[0]);
EXPECT_EQ("bar", out_buffer[1]);
}
TEST(MediaTrackConstraintsTest, ConvertBlinkStringConstraint) {
MediaTrackConstraints* input = MediaTrackConstraints::Create();
MediaConstraints output;
auto* parameter = MakeGarbageCollected<V8ConstrainDOMString>("foo");
input->setFacingMode(parameter);
String error_message;
output = media_constraints_impl::ConvertTrackConstraintsToMediaConstraints(
input, error_message);
ASSERT_TRUE(error_message.empty());
ASSERT_TRUE(output.Basic().facing_mode.HasIdeal());
ASSERT_EQ(1U, output.Basic().facing_mode.Ideal().size());
ASSERT_EQ("foo", output.Basic().facing_mode.Ideal()[0]);
}
TEST(MediaTrackConstraintsTest, ConvertBlinkComplexStringConstraint) {
MediaTrackConstraints* input = MediaTrackConstraints::Create();
MediaConstraints output;
ConstrainDOMStringParameters* subparameter =
ConstrainDOMStringParameters::Create();
subparameter->setIdeal(
MakeGarbageCollected<V8UnionStringOrStringSequence>("foo"));
auto* parameter = MakeGarbageCollected<V8ConstrainDOMString>(subparameter);
input->setFacingMode(parameter);
String error_message;
output = media_constraints_impl::ConvertTrackConstraintsToMediaConstraints(
input, error_message);
ASSERT_TRUE(error_message.empty());
ASSERT_TRUE(output.Basic().facing_mode.HasIdeal());
ASSERT_EQ(1U, output.Basic().facing_mode.Ideal().size());
ASSERT_EQ("foo", output.Basic().facing_mode.Ideal()[0]);
// Convert this back, and see that it appears as a single string.
MediaTrackConstraints* recycled =
media_constraints_impl::ConvertConstraints(output);
ASSERT_TRUE(recycled->hasFacingMode());
ASSERT_TRUE(recycled->facingMode()->IsString());
ASSERT_EQ("foo", recycled->facingMode()->GetAsString());
}
TEST(MediaTrackConstraintsTest, NakedIsExactInAdvanced) {
MediaTrackConstraints* input = MediaTrackConstraints::Create();
auto* parameter = MakeGarbageCollected<V8ConstrainDOMString>("foo");
input->setFacingMode(parameter);
HeapVector<Member<MediaTrackConstraintSet>> advanced(
1, MediaTrackConstraintSet::Create());
advanced[0]->setFacingMode(parameter);
input->setAdvanced(advanced);
String error_message;
MediaConstraints output =
media_constraints_impl::ConvertTrackConstraintsToMediaConstraints(
input, error_message);
ASSERT_TRUE(error_message.empty());
ASSERT_TRUE(output.Basic().facing_mode.HasIdeal());
ASSERT_FALSE(output.Basic().facing_mode.HasExact());
ASSERT_EQ(1U, output.Basic().facing_mode.Ideal().size());
ASSERT_EQ("foo", output.Basic().facing_mode.Ideal()[0]);
ASSERT_FALSE(output.Advanced()[0].facing_mode.HasIdeal());
ASSERT_TRUE(output.Advanced()[0].facing_mode.HasExact());
ASSERT_EQ(1U, output.Advanced()[0].facing_mode.Exact().size());
ASSERT_EQ("foo", output.Advanced()[0].facing_mode.Exact()[0]);
}
TEST(MediaTrackConstraintsTest, AdvancedParameterFails) {
MediaTrackConstraints* input = MediaTrackConstraints::Create();
String str(
std::string(media_constraints_impl::kMaxConstraintStringLength + 1, 'a')
.c_str());
auto* parameter = MakeGarbageCollected<V8ConstrainDOMString>(str);
HeapVector<Member<MediaTrackConstraintSet>> advanced(
1, MediaTrackConstraintSet::Create());
advanced[0]->setFacingMode(parameter);
input->setAdvanced(advanced);
String error_message;
MediaConstraints output =
media_constraints_impl::ConvertTrackConstraintsToMediaConstraints(
input, error_message);
ASSERT_FALSE(error_message.empty());
EXPECT_EQ(error_message, "Constraint string too long.");
}
TEST(MediaTrackConstraintsTest, IdealAndExactConvertToNaked) {
MediaConstraints input;
Vector<String> buffer(static_cast<size_t>(1u));
MediaTrackConstraintSetPlatform basic;
MediaTrackConstraintSetPlatform advanced_element1;
MediaTrackConstraintSetPlatform advanced_element2;
buffer[0] = "ideal";
basic.facing_mode.SetIdeal(buffer);
advanced_element1.facing_mode.SetIdeal(buffer);
buffer[0] = "exact";
advanced_element2.facing_mode.SetExact(buffer);
Vector<MediaTrackConstraintSetPlatform> advanced;
advanced.push_back(advanced_element1);
advanced.push_back(advanced_element2);
input.Initialize(basic, advanced);
MediaTrackConstraints* output =
media_constraints_impl::ConvertConstraints(input);
// The first element should return a ConstrainDOMStringParameters
// with an "ideal" value containing a String value of "ideal".
// The second element should return a ConstrainDOMStringParameters
// with a String value of "exact".
ASSERT_TRUE(output->hasAdvanced());
ASSERT_EQ(2U, output->advanced().size());
MediaTrackConstraintSet* element1 = output->advanced()[0];
MediaTrackConstraintSet* element2 = output->advanced()[1];
ASSERT_TRUE(output->hasFacingMode());
ASSERT_TRUE(output->facingMode()->IsString());
EXPECT_EQ("ideal", output->facingMode()->GetAsString());
ASSERT_TRUE(element1->hasFacingMode());
ASSERT_TRUE(element1->facingMode()->IsConstrainDOMStringParameters());
EXPECT_EQ("ideal", element1->facingMode()
->GetAsConstrainDOMStringParameters()
->ideal()
->GetAsString());
ASSERT_TRUE(element2->hasFacingMode());
ASSERT_TRUE(element2->facingMode()->IsString());
EXPECT_EQ("exact", element2->facingMode()->GetAsString());
}
TEST(MediaTrackConstraintsTest, MaxLengthStringConstraintPasses) {
MediaTrackConstraints* input = MediaTrackConstraints::Create();
String str(
std::string(media_constraints_impl::kMaxConstraintStringLength, 'a')
.c_str());
auto* parameter = MakeGarbageCollected<V8ConstrainDOMString>(str);
input->setGroupId(parameter);
String error_message;
MediaConstraints output =
media_constraints_impl::ConvertTrackConstraintsToMediaConstraints(
input, error_message);
EXPECT_TRUE(error_message.empty());
EXPECT_EQ(*output.Basic().group_id.Ideal().begin(), str);
}
TEST(MediaTrackConstraintsTest, TooLongStringConstraintFails) {
MediaTrackConstraints* input = MediaTrackConstraints::Create();
String str(
std::string(media_constraints_impl::kMaxConstraintStringLength + 1, 'a')
.c_str());
auto* parameter = MakeGarbageCollected<V8ConstrainDOMString>(str);
input->setGroupId(parameter);
String error_message;
MediaConstraints output =
media_constraints_impl::ConvertTrackConstraintsToMediaConstraints(
input, error_message);
ASSERT_FALSE(error_message.empty());
EXPECT_EQ(error_message, "Constraint string too long.");
}
TEST(MediaTrackConstraintsTest, MaxLengthStringSequenceConstraintPasses) {
MediaTrackConstraints* input = MediaTrackConstraints::Create();
Vector<String> sequence;
sequence.Fill("a", media_constraints_impl::kMaxConstraintStringSeqLength);
auto* parameter = MakeGarbageCollected<V8ConstrainDOMString>(sequence);
input->setGroupId(parameter);
String error_message;
MediaConstraints output =
media_constraints_impl::ConvertTrackConstraintsToMediaConstraints(
input, error_message);
EXPECT_TRUE(error_message.empty());
EXPECT_EQ(output.Basic().group_id.Ideal().size(),
media_constraints_impl::kMaxConstraintStringSeqLength);
}
TEST(MediaTrackConstraintsTest, TooLongStringSequenceConstraintFails) {
MediaTrackConstraints* input = MediaTrackConstraints::Create();
Vector<String> sequence;
sequence.Fill("a", media_constraints_impl::kMaxConstraintStringSeqLength + 1);
auto* parameter = MakeGarbageCollected<V8ConstrainDOMString>(sequence);
input->setGroupId(parameter);
String error_message;
media_constraints_impl::ConvertTrackConstraintsToMediaConstraints(
input, error_message);
ASSERT_FALSE(error_message.empty());
EXPECT_EQ(error_message, "Constraint string sequence too long.");
}
TEST(MediaTrackConstraintsTest,
TooLongStringSequenceForDeviceIdConstraintFails) {
MediaTrackConstraints* input = MediaTrackConstraints::Create();
Vector<String> sequence;
sequence.Fill("a", media_constraints_impl::kMaxConstraintStringSeqLength + 1);
auto* parameter = MakeGarbageCollected<V8ConstrainDOMString>(sequence);
input->setDeviceId(parameter);
String error_message;
media_constraints_impl::ConvertTrackConstraintsToMediaConstraints(
input, error_message);
ASSERT_FALSE(error_message.empty());
EXPECT_EQ(error_message, "Constraint string sequence too long.");
}
TEST(MediaTrackConstraintsTest,
TooLongStringSequenceForFacingModeConstraintFails) {
MediaTrackConstraints* input = MediaTrackConstraints::Create();
Vector<String> sequence;
sequence.Fill("a", media_constraints_impl::kMaxConstraintStringSeqLength + 1);
auto* parameter = MakeGarbageCollected<V8ConstrainDOMString>(sequence);
input->setFacingMode(parameter);
String error_message;
media_constraints_impl::ConvertTrackConstraintsToMediaConstraints(
input, error_message);
ASSERT_FALSE(error_message.empty());
EXPECT_EQ(error_message, "Constraint string sequence too long.");
}
TEST(MediaTrackConstraintsTest,
TooLongStringSequenceForResizeModeConstraintFails) {
MediaTrackConstraints* input = MediaTrackConstraints::Create();
Vector<String> sequence;
sequence.Fill("a", media_constraints_impl::kMaxConstraintStringSeqLength + 1);
auto* parameter = MakeGarbageCollected<V8ConstrainDOMString>(sequence);
input->setResizeMode(parameter);
String error_message;
media_constraints_impl::ConvertTrackConstraintsToMediaConstraints(
input, error_message);
ASSERT_FALSE(error_message.empty());
EXPECT_EQ(error_message, "Constraint string sequence too long.");
}
TEST(MediaTrackConstraintsTest,
TooLongStringSequenceForDisplaySurfaceConstraintFails) {
MediaTrackConstraints* input = MediaTrackConstraints::Create();
Vector<String> sequence;
sequence.Fill("a", media_constraints_impl::kMaxConstraintStringSeqLength + 1);
auto* parameter = MakeGarbageCollected<V8ConstrainDOMString>(sequence);
input->setDisplaySurface(parameter);
String error_message;
media_constraints_impl::ConvertTrackConstraintsToMediaConstraints(
input, error_message);
ASSERT_FALSE(error_message.empty());
EXPECT_EQ(error_message, "Constraint string sequence too long.");
}
} // namespace blink