// 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. #include "remoting/protocol/audio_decode_scheduler.h" #include <utility> #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" #include "base/run_loop.h" #include "base/test/task_environment.h" #include "base/threading/thread.h" #include "remoting/base/auto_thread.h" #include "remoting/base/auto_thread_task_runner.h" #include "remoting/proto/audio.pb.h" #include "remoting/protocol/session_config.h" #include "testing/gtest/include/gtest/gtest.h" namespace remoting::protocol { namespace { const int kAudioSampleBytes = 4; const uint8_t kDummyAudioData = 0x8B; class FakeAudioConsumer : public AudioStub { public: FakeAudioConsumer() {} FakeAudioConsumer(const FakeAudioConsumer&) = delete; FakeAudioConsumer& operator=(const FakeAudioConsumer&) = delete; ~FakeAudioConsumer() override = default; base::WeakPtr<FakeAudioConsumer> GetWeakPtr() { return weak_factory_.GetWeakPtr(); } // AudioStub implementation. void ProcessAudioPacket(std::unique_ptr<AudioPacket> packet, base::OnceClosure done) override { if (!done.is_null()) { std::move(done).Run(); } } private: base::WeakPtrFactory<FakeAudioConsumer> weak_factory_{this}; }; } // namespace class AudioDecodeSchedulerTest : public ::testing::Test { public: AudioDecodeSchedulerTest() = default; void SetUp() override; void TearDown() override; protected: base::test::SingleThreadTaskEnvironment task_environment_; base::RunLoop run_loop_; scoped_refptr<AutoThreadTaskRunner> audio_decode_task_runner_; scoped_refptr<AutoThreadTaskRunner> main_task_runner_; std::unique_ptr<SessionConfig> session_config_; }; void AudioDecodeSchedulerTest::SetUp() { main_task_runner_ = new AutoThreadTaskRunner( task_environment_.GetMainThreadTaskRunner(), run_loop_.QuitClosure()); audio_decode_task_runner_ = AutoThread::Create("decode", main_task_runner_); session_config_ = SessionConfig::ForTestWithAudio(); } void AudioDecodeSchedulerTest::TearDown() { // Release the task runners, so that the test can quit. audio_decode_task_runner_ = nullptr; main_task_runner_ = nullptr; // Run the MessageLoop until everything has torn down. run_loop_.Run(); } // TODO(nicholss): Could share the following in a common class for use // in other places. std::unique_ptr<AudioPacket> CreatePacketWithSamplingRate_( AudioPacket::SamplingRate rate, int samples) { std::unique_ptr<AudioPacket> packet(new AudioPacket()); packet->set_encoding(AudioPacket::ENCODING_RAW); packet->set_sampling_rate(rate); packet->set_bytes_per_sample(AudioPacket::BYTES_PER_SAMPLE_2); packet->set_channels(AudioPacket::CHANNELS_STEREO); // The data must be a multiple of 4 bytes (channels x bytes_per_sample). std::string data; data.resize(samples * kAudioSampleBytes, kDummyAudioData); packet->add_data(data); return packet; } std::unique_ptr<AudioPacket> CreatePacket44100Hz_(int samples) { return CreatePacketWithSamplingRate_(AudioPacket::SAMPLING_RATE_44100, samples); } std::unique_ptr<AudioPacket> CreatePacket48000Hz_(int samples) { return CreatePacketWithSamplingRate_(AudioPacket::SAMPLING_RATE_48000, samples); } TEST_F(AudioDecodeSchedulerTest, Shutdown) { std::unique_ptr<FakeAudioConsumer> audio_consumer(new FakeAudioConsumer()); std::unique_ptr<AudioDecodeScheduler> audio_scheduler( new AudioDecodeScheduler(audio_decode_task_runner_, audio_consumer->GetWeakPtr())); audio_scheduler->Initialize(*session_config_); audio_scheduler->ProcessAudioPacket(CreatePacket44100Hz_(1000), base::DoNothing()); audio_scheduler.reset(); audio_consumer.reset(); // TODO(nicholss): This test does not really test anything. Add a way to get a // count of the calls to AddAudioPacket. } } // namespace remoting::protocol