chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_thread_test.cc

// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/351564777): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#include <memory>
#include <tuple>

#include "base/feature_list.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/v8_cache_options.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/bindings/core/v8/module_record.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_gc_controller.h"
#include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/inspector/worker_devtools_params.h"
#include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h"
#include "third_party/blink/renderer/core/script/js_module_script.h"
#include "third_party/blink/renderer/core/script/script.h"
#include "third_party/blink/renderer/core/testing/module_test_base.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/core/workers/global_scope_creation_params.h"
#include "third_party/blink/renderer/core/workers/worker_backing_thread.h"
#include "third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h"
#include "third_party/blink/renderer/core/workers/worker_reporting_proxy.h"
#include "third_party/blink/renderer/core/workers/worker_thread.h"
#include "third_party/blink/renderer/core/workers/worklet_module_responses_map.h"
#include "third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.h"
#include "third_party/blink/renderer/modules/webaudio/cross_thread_audio_worklet_processor_info.h"
#include "third_party/blink/renderer/modules/webaudio/offline_audio_worklet_thread.h"
#include "third_party/blink/renderer/modules/webaudio/realtime_audio_worklet_thread.h"
#include "third_party/blink/renderer/modules/webaudio/semi_realtime_audio_worklet_thread.h"
#include "third_party/blink/renderer/platform/bindings/source_location.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_copier.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/wtf/text/text_position.h"
#include "third_party/blink/renderer/platform/wtf/threading.h"

namespace blink {

class AudioWorkletThreadTest : public PageTestBase, public ModuleTestBase {};

TEST_F(AudioWorkletThreadTest, Basic) {}

// Creates 2 different AudioWorkletThreads with different RT constraints.
// Checks if they are running on a different thread.
TEST_F(AudioWorkletThreadTest, CreateDifferentWorkletThreadsAndTerminate_1) {}

// Creates 2 AudioWorkletThreads with RT constraint from 2 different
// originating frames. Checks if they are running on a different thread.
TEST_F(AudioWorkletThreadTest, CreateDifferentWorkletThreadsAndTerminate_2) {}

class AudioWorkletThreadInteractionTest
    : public AudioWorkletThreadTest,
      public testing::WithParamInterface<std::tuple<bool, bool>> {};

TEST_P(AudioWorkletThreadInteractionTest, CreateSecondAndTerminateFirst) {}

TEST_P(AudioWorkletThreadInteractionTest, TerminateFirstAndCreateSecond) {}

TEST_P(AudioWorkletThreadInteractionTest,
       ThreadManagementSystemForRealtimeAndTopLevelFrame) {}

INSTANTIATE_TEST_SUITE_P();

struct ThreadPriorityTestParam {};

constexpr ThreadPriorityTestParam kThreadPriorityTestParams[] =;

class AudioWorkletThreadPriorityTest
    : public AudioWorkletThreadTest,
      public testing::WithParamInterface<ThreadPriorityTestParam> {};

TEST_P(AudioWorkletThreadPriorityTest, CheckThreadPriority) {}

INSTANTIATE_TEST_SUITE_P();

}  // namespace blink

#if BUILDFLAG(IS_APPLE)

namespace WTF {
template <>
struct CrossThreadCopier<base::TimeDelta>
    : public CrossThreadCopierPassThrough<base::TimeDelta> {
  STATIC_ONLY(CrossThreadCopier);
};
}  // namespace WTF

namespace blink {

class AudioWorkletRealtimePeriodTestMac : public AudioWorkletThreadTest {
 public:
  std::unique_ptr<WorkerThread> CreateThreadAndCheckRealtimePeriod(
      base::TimeDelta realtime_buffer_duration,
      base::TimeDelta expected_realtime_period) {
    std::unique_ptr<WorkerThread> audio_worklet_thread =
        CreateAudioWorkletThread(/*has_realtime_constraint=*/true,
                                 /*is_top_level_frame=*/true,
                                 realtime_buffer_duration);
    WorkerThread* thread = audio_worklet_thread.get();
    base::WaitableEvent wait_event;
    PostCrossThreadTask(
        *thread->GetWorkerBackingThread().BackingThread().GetTaskRunner(),
        FROM_HERE,
        CrossThreadBindOnce(
            &AudioWorkletRealtimePeriodTestMac::
                CheckThreadRealtimePeriodOnWorkerThread,
            CrossThreadUnretained(this), CrossThreadUnretained(thread),
            expected_realtime_period, CrossThreadUnretained(&wait_event)));
    wait_event.Wait();
    return audio_worklet_thread;
  }

 private:
  void CheckThreadRealtimePeriodOnWorkerThread(
      WorkerThread* thread,
      base::TimeDelta expected_realtime_period,
      base::WaitableEvent* wait_event) {
    ASSERT_TRUE(thread->IsCurrentThread());

    base::ThreadPriorityForTest actual_priority =
        base::PlatformThread::GetCurrentThreadPriorityForTest();

    base::TimeDelta actual_realtime_period =
        base::PlatformThread::GetCurrentThreadRealtimePeriodForTest();

    EXPECT_EQ(actual_priority, base::ThreadPriorityForTest::kRealtimeAudio);
    EXPECT_EQ(actual_realtime_period, expected_realtime_period);

    wait_event->Signal();
  }
};

TEST_F(AudioWorkletRealtimePeriodTestMac, CheckRealtimePeriod) {
  // Creates 5 realtime AudioWorkletThreads with different realtime buffer
  // durations; the last two will be sharing the same backing thread.
  base::TimeDelta realtime_buffer_durations[] = {
      base::Milliseconds(10), base::Milliseconds(20), base::Milliseconds(30),
      base::Milliseconds(40), base::Milliseconds(50)};

  std::vector<std::unique_ptr<WorkerThread>> worklet_threads;
  worklet_threads.push_back(CreateThreadAndCheckRealtimePeriod(
      realtime_buffer_durations[0], realtime_buffer_durations[0]));
  worklet_threads.push_back(CreateThreadAndCheckRealtimePeriod(
      realtime_buffer_durations[1], realtime_buffer_durations[1]));
  worklet_threads.push_back(CreateThreadAndCheckRealtimePeriod(
      realtime_buffer_durations[2], realtime_buffer_durations[2]));
  worklet_threads.push_back(CreateThreadAndCheckRealtimePeriod(
      realtime_buffer_durations[3], realtime_buffer_durations[3]));
  // Note: we expect that the last two worklets share the same backng thread, so
  // the should have the same realtime period.
  worklet_threads.push_back(CreateThreadAndCheckRealtimePeriod(
      realtime_buffer_durations[4], realtime_buffer_durations[3]));

  for (auto& worklet_thread : worklet_threads) {
    if (worklet_thread.get()) {
      worklet_thread->Terminate();
      worklet_thread->WaitForShutdownForTesting();
    }
  }
}

}  // namespace blink

#endif  // BUILDFLAG(IS_APPLE)