summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/modules/mediastream/video_track_signal_underlying_sink_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/modules/mediastream/video_track_signal_underlying_sink_test.cc')
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/video_track_signal_underlying_sink_test.cc244
1 files changed, 244 insertions, 0 deletions
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/video_track_signal_underlying_sink_test.cc b/chromium/third_party/blink/renderer/modules/mediastream/video_track_signal_underlying_sink_test.cc
new file mode 100644
index 00000000000..2eb472de7b4
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/mediastream/video_track_signal_underlying_sink_test.cc
@@ -0,0 +1,244 @@
+// Copyright 2021 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/modules/mediastream/video_track_signal_underlying_sink.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/web/web_heap.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h"
+#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_media_stream_track_signal.h"
+#include "third_party/blink/renderer/core/streams/writable_stream.h"
+#include "third_party/blink/renderer/core/streams/writable_stream_default_writer.h"
+#include "third_party/blink/renderer/modules/mediastream/media_stream_track.h"
+#include "third_party/blink/renderer/modules/mediastream/media_stream_video_track.h"
+#include "third_party/blink/renderer/modules/mediastream/mock_media_stream_video_source.h"
+#include "third_party/blink/renderer/platform/mediastream/media_stream_component.h"
+#include "third_party/blink/renderer/platform/mediastream/media_stream_source.h"
+#include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h"
+
+using testing::_;
+
+namespace blink {
+
+class VideoTrackSignalUnderlyingSinkTest : public testing::Test {
+ public:
+ VideoTrackSignalUnderlyingSinkTest() {
+ mock_video_source_ = new MockMediaStreamVideoSource();
+ media_stream_source_ = MakeGarbageCollected<MediaStreamSource>(
+ "dummy_source_id", MediaStreamSource::kTypeVideo, "dummy_source_name",
+ /*remote=*/false);
+ media_stream_source_->SetPlatformSource(
+ base::WrapUnique(mock_video_source_));
+ web_track_ = MediaStreamVideoTrack::CreateVideoTrack(
+ mock_video_source_, MediaStreamVideoSource::ConstraintsOnceCallback(),
+ true);
+ mock_video_source_->StartMockedSource();
+ }
+
+ ~VideoTrackSignalUnderlyingSinkTest() override {
+ platform_->RunUntilIdle();
+ mock_video_source_->StopSource();
+ base::RunLoop run_loop;
+ platform_->GetIOTaskRunner()->PostTask(FROM_HERE, run_loop.QuitClosure());
+ run_loop.Run();
+ WebHeap::CollectAllGarbageForTesting();
+ }
+
+ MediaStreamTrack* CreateTrack(ExecutionContext* context) const {
+ return MakeGarbageCollected<MediaStreamTrack>(context, web_track_);
+ }
+ VideoTrackSignalUnderlyingSink* CreateUnderlyingSink(
+ MediaStreamTrack* track) {
+ return MakeGarbageCollected<VideoTrackSignalUnderlyingSink>(track);
+ }
+
+ ScriptValue CreateSignalChunk(ScriptState* script_state,
+ const String& signal_name) {
+ MediaStreamTrackSignal* signal = MediaStreamTrackSignal::Create();
+ signal->setSignalType(signal_name);
+ return ScriptValue(script_state->GetIsolate(),
+ ToV8(signal, script_state->GetContext()->Global(),
+ script_state->GetIsolate()));
+ }
+
+ ScriptValue CreateRequestFrameChunk(ScriptState* script_state) {
+ return CreateSignalChunk(script_state, "request-frame");
+ }
+
+ ScriptValue CreateSetMinFrameRateChunk(
+ ScriptState* script_state,
+ const base::Optional<double>& frame_rate = 10.0) {
+ MediaStreamTrackSignal* signal = MediaStreamTrackSignal::Create();
+ signal->setSignalType("set-min-frame-rate");
+ if (frame_rate)
+ signal->setFrameRate(*frame_rate);
+ return ScriptValue(script_state->GetIsolate(),
+ ToV8(signal, script_state->GetContext()->Global(),
+ script_state->GetIsolate()));
+ }
+
+ protected:
+ Persistent<MediaStreamSource> media_stream_source_;
+ WebMediaStreamTrack web_track_;
+ MockMediaStreamVideoSource* mock_video_source_;
+ ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform_;
+};
+
+TEST_F(VideoTrackSignalUnderlyingSinkTest,
+ WriteRequestFrameToStreamForwardsToVideoSource) {
+ V8TestingScope v8_scope;
+ ScriptState* script_state = v8_scope.GetScriptState();
+ auto* track = CreateTrack(v8_scope.GetExecutionContext());
+ auto* underlying_sink = CreateUnderlyingSink(track);
+ auto* writable_stream = WritableStream::CreateWithCountQueueingStrategy(
+ script_state, underlying_sink, 1u);
+
+ NonThrowableExceptionState exception_state;
+ auto* writer = writable_stream->getWriter(script_state, exception_state);
+
+ auto request_frame_chunk = CreateRequestFrameChunk(script_state);
+ EXPECT_CALL(*mock_video_source_, OnRequestRefreshFrame());
+ ScriptPromiseTester write_tester(
+ script_state,
+ writer->write(script_state, request_frame_chunk, exception_state));
+ write_tester.WaitUntilSettled();
+
+ const double frame_rate = 14.8;
+ auto set_min_frame_rate_chunk =
+ CreateSetMinFrameRateChunk(script_state, frame_rate);
+ MediaStreamVideoTrack* video_track =
+ MediaStreamVideoTrack::From(track->Component());
+ EXPECT_FALSE(video_track->min_frame_rate().has_value());
+ ScriptPromiseTester write_tester2(
+ script_state,
+ writer->write(script_state, set_min_frame_rate_chunk, exception_state));
+ write_tester2.WaitUntilSettled();
+ EXPECT_TRUE(video_track->min_frame_rate().has_value());
+ EXPECT_EQ(video_track->min_frame_rate().value(), frame_rate);
+
+ writer->releaseLock(script_state);
+ ScriptPromiseTester close_tester(
+ script_state, writable_stream->close(script_state, exception_state));
+ close_tester.WaitUntilSettled();
+
+ MediaStreamTrack* clone = track->clone(script_state);
+ track->stopTrack(v8_scope.GetExecutionContext());
+
+ // Writing to the sink after the track closes should fail, even if the source
+ // is active.
+ EXPECT_TRUE(mock_video_source_->IsRunning());
+ DummyExceptionStateForTesting dummy_exception_state;
+ underlying_sink->write(script_state, CreateRequestFrameChunk(script_state),
+ nullptr, dummy_exception_state);
+ EXPECT_TRUE(dummy_exception_state.HadException());
+ EXPECT_EQ(dummy_exception_state.Code(),
+ static_cast<ExceptionCode>(DOMExceptionCode::kInvalidStateError));
+
+ clone->stopTrack(v8_scope.GetExecutionContext());
+ EXPECT_FALSE(mock_video_source_->IsRunning());
+ // Writing to the sink after the source closes should fail.
+ dummy_exception_state.ClearException();
+ underlying_sink->write(script_state, CreateRequestFrameChunk(script_state),
+ nullptr, dummy_exception_state);
+ EXPECT_TRUE(dummy_exception_state.HadException());
+ EXPECT_EQ(dummy_exception_state.Code(),
+ static_cast<ExceptionCode>(DOMExceptionCode::kInvalidStateError));
+}
+
+TEST_F(VideoTrackSignalUnderlyingSinkTest, WriteInvalidDataFails) {
+ V8TestingScope v8_scope;
+ ScriptState* script_state = v8_scope.GetScriptState();
+ auto* track = CreateTrack(v8_scope.GetExecutionContext());
+ auto* underlying_sink = CreateUnderlyingSink(track);
+
+ MediaStreamVideoTrack* video_track =
+ MediaStreamVideoTrack::From(track->Component());
+ EXPECT_FALSE(video_track->min_frame_rate().has_value());
+
+ DummyExceptionStateForTesting exception_state;
+ auto set_min_frame_rate_chunk =
+ CreateSetMinFrameRateChunk(script_state, base::nullopt);
+ underlying_sink->write(script_state, set_min_frame_rate_chunk, nullptr,
+ exception_state);
+ EXPECT_TRUE(exception_state.HadException());
+ EXPECT_FALSE(video_track->min_frame_rate().has_value());
+
+ exception_state.ClearException();
+ EXPECT_FALSE(exception_state.HadException());
+ underlying_sink->write(script_state,
+ CreateSignalChunk(script_state, "invalid-signal"),
+ nullptr, exception_state);
+ EXPECT_TRUE(exception_state.HadException());
+
+ // Writing null fails
+ exception_state.ClearException();
+ EXPECT_FALSE(exception_state.HadException());
+ underlying_sink->write(script_state,
+ ScriptValue::CreateNull(v8_scope.GetIsolate()),
+ nullptr, exception_state);
+ EXPECT_TRUE(exception_state.HadException());
+
+ // Writing an intenger fails
+ exception_state.ClearException();
+ EXPECT_FALSE(exception_state.HadException());
+ underlying_sink->write(script_state, ScriptValue::From(script_state, 5),
+ nullptr, exception_state);
+ EXPECT_TRUE(exception_state.HadException());
+
+ track->stopTrack(v8_scope.GetExecutionContext());
+}
+
+TEST_F(VideoTrackSignalUnderlyingSinkTest, WriteToClosedSinkFails) {
+ V8TestingScope v8_scope;
+ ScriptState* script_state = v8_scope.GetScriptState();
+ auto* track = CreateTrack(v8_scope.GetExecutionContext());
+ auto* underlying_sink = CreateUnderlyingSink(track);
+
+ auto* writable_stream = WritableStream::CreateWithCountQueueingStrategy(
+ script_state, underlying_sink, 1u);
+
+ NonThrowableExceptionState exception_state;
+ ScriptPromiseTester abort_tester(
+ script_state, writable_stream->close(script_state, exception_state));
+ abort_tester.WaitUntilSettled();
+
+ // Writing to the sink after the stream closes should fail.
+ DummyExceptionStateForTesting dummy_exception_state;
+ underlying_sink->write(script_state, CreateRequestFrameChunk(script_state),
+ nullptr, dummy_exception_state);
+ EXPECT_TRUE(dummy_exception_state.HadException());
+ EXPECT_EQ(dummy_exception_state.Code(),
+ static_cast<ExceptionCode>(DOMExceptionCode::kInvalidStateError));
+
+ track->stopTrack(v8_scope.GetExecutionContext());
+}
+
+TEST_F(VideoTrackSignalUnderlyingSinkTest, WriteToAbortedSinkFails) {
+ V8TestingScope v8_scope;
+ ScriptState* script_state = v8_scope.GetScriptState();
+ auto* track = CreateTrack(v8_scope.GetExecutionContext());
+ auto* underlying_sink = CreateUnderlyingSink(track);
+
+ auto* writable_stream = WritableStream::CreateWithCountQueueingStrategy(
+ script_state, underlying_sink, 1u);
+
+ NonThrowableExceptionState exception_state;
+ ScriptPromiseTester abort_tester(
+ script_state, writable_stream->abort(script_state, exception_state));
+ abort_tester.WaitUntilSettled();
+
+ // Writing to the sink after the stream aborts should fail.
+ DummyExceptionStateForTesting dummy_exception_state;
+ underlying_sink->write(script_state, CreateRequestFrameChunk(script_state),
+ nullptr, dummy_exception_state);
+ EXPECT_TRUE(dummy_exception_state.HadException());
+ EXPECT_EQ(dummy_exception_state.Code(),
+ static_cast<ExceptionCode>(DOMExceptionCode::kInvalidStateError));
+
+ track->stopTrack(v8_scope.GetExecutionContext());
+}
+
+} // namespace blink