Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(269)

Side by Side Diff: media/audio/audio_debug_recording_helper_unittest.cc

Issue 2582703003: Audio output debug recording. (Closed)
Patch Set: Code review (pfeldman@/dalecurtis@) and a fix. Rebase. Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "media/audio/audio_debug_recording_helper.h"
6
7 #include "base/bind.h"
8 #include "base/files/file_path.h"
9 #include "base/logging.h"
10 #include "base/memory/ptr_util.h"
11 #include "base/run_loop.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/test/test_message_loop.h"
14 #include "media/base/audio_bus.h"
15 #include "media/base/audio_sample_types.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18
19 using testing::_;
20 using testing::Return;
21
22 #if defined(OS_WIN)
23 #define IntToStringType base::IntToString16
24 #else
25 #define IntToStringType base::IntToString
26 #endif
27
28 namespace media {
29
30 namespace {
31
32 // The filename extension the mock should return in GetFileNameExtension().
33 const base::FilePath::CharType kFileNameExtension[] = FILE_PATH_LITERAL("wav");
34
35 } // namespace
36
37 // Mock class for the audio file writer that the helper wraps.
38 class MockAudioFileWriter : public AudioFileWriter {
39 public:
40 MockAudioFileWriter(const AudioParameters& params)
41 : params_(params), reference_data_(nullptr) {}
42 ~MockAudioFileWriter() override {}
43
44 MOCK_METHOD1(Start, void(const base::FilePath&));
45 MOCK_METHOD0(Stop, void());
46
47 // Functions with move-only types as arguments can't be mocked directly, so
48 // we pass on to DoWrite(). Also, we can verify the data this way.
49 MOCK_METHOD1(DoWrite, void(AudioBus*));
50 void Write(std::unique_ptr<AudioBus> data) override {
51 CHECK(reference_data_);
52 EXPECT_EQ(reference_data_->channels(), data->channels());
53 EXPECT_EQ(reference_data_->frames(), data->frames());
54 for (int i = 0; i < data->channels(); ++i) {
55 float* data_ptr = data->channel(i);
56 float* ref_data_ptr = reference_data_->channel(i);
57 for (int j = 0; j < data->frames(); ++j, ++data_ptr, ++ref_data_ptr)
58 EXPECT_EQ(*ref_data_ptr, *data_ptr);
59 }
60 DoWrite(data.get());
61 }
62
63 MOCK_METHOD0(WillWrite, bool());
64 MOCK_METHOD0(GetFileNameExtension, const base::FilePath::CharType*());
65
66 // Set reference data to compare against. Must be called before Write() is
67 // called.
68 void SetReferenceData(AudioBus* reference_data) {
69 EXPECT_EQ(params_.channels(), reference_data->channels());
70 EXPECT_EQ(params_.frames_per_buffer(), reference_data->frames());
71 reference_data_ = reference_data;
72 }
73
74 private:
75 const AudioParameters params_;
76 AudioBus* reference_data_;
77 };
78
79 // The test fixture.
80 class AudioDebugRecordingHelperTest : public ::testing::Test {
81 public:
82 AudioDebugRecordingHelperTest()
83 : file_path_(base::FilePath::FromUTF8Unsafe("file_path")),
84 mock_audio_file_writer_(nullptr) {}
85
86 ~AudioDebugRecordingHelperTest() override {}
87
88 // Creates the mock writer, passed as a callback to the helper and called by
89 // the helper. After the mock writer is returned, we always expect
90 // GetFileNameExtension() and Start() to be called on it by the helper.
91 std::unique_ptr<AudioFileWriter> CreateMockAudioFileWriter(
92 const AudioParameters& params) {
93 CHECK(!mock_audio_file_writer_);
94 MockAudioFileWriter* writer = new MockAudioFileWriter(params);
95 EXPECT_CALL(*writer, GetFileNameExtension())
96 .WillOnce(Return(kFileNameExtension));
97 base::FilePath expected_file_path =
98 file_path_.AddExtension(kFileNameExtension);
99 EXPECT_CALL(*writer, Start(expected_file_path));
100 mock_audio_file_writer_ = writer;
101 return base::WrapUnique<AudioFileWriter>(writer);
102 }
103
104 // Helper function that creates a recording helper.
105 std::unique_ptr<AudioDebugRecordingHelper> CreateRecordingHelper(
106 const AudioParameters& params,
107 base::OnceClosure on_destruction_closure) {
108 return base::MakeUnique<AudioDebugRecordingHelper>(
109 params, base::BindRepeating(
110 &AudioDebugRecordingHelperTest::CreateMockAudioFileWriter,
111 base::Unretained(this)),
112 message_loop_.task_runner(), std::move(on_destruction_closure));
113 }
114
115 // Helper function that unsets the mock writer pointer after disabling.
116 void DisableDebugRecording(AudioDebugRecordingHelper* recording_helper) {
117 recording_helper->DisableDebugRecording();
118 mock_audio_file_writer_ = nullptr;
119 }
120
121 MOCK_METHOD0(OnAudioDebugRecordingHelperDestruction, void());
122
123 protected:
124 base::FilePath file_path_;
125
126 // Pointer to the mock writer that the helper wraps. Set in
127 // CreateMockAudioFileWriter() and unset in DisableDebugRecording().
128 MockAudioFileWriter* mock_audio_file_writer_;
129
130 base::TestMessageLoop message_loop_;
131
132 private:
133 DISALLOW_COPY_AND_ASSIGN(AudioDebugRecordingHelperTest);
134 };
135
136 // Creates a helper with an on destrcution closure, and verifies that it's
137 // run.
138 TEST_F(AudioDebugRecordingHelperTest, TestDestructionClosure) {
139 const AudioParameters params;
140 std::unique_ptr<AudioDebugRecordingHelper> recording_helper =
141 CreateRecordingHelper(
142 params, base::BindOnce(&AudioDebugRecordingHelperTest::
143 OnAudioDebugRecordingHelperDestruction,
144 base::Unretained(this)));
145
146 EXPECT_CALL(*this, OnAudioDebugRecordingHelperDestruction());
147 }
148
149 // Verifies that disable can be called without being enabled.
150 TEST_F(AudioDebugRecordingHelperTest, OnlyDisable) {
151 const AudioParameters params;
152 std::unique_ptr<AudioDebugRecordingHelper> recording_helper =
153 CreateRecordingHelper(params, base::OnceClosure());
154
155 recording_helper->DisableDebugRecording();
156 }
157
158 TEST_F(AudioDebugRecordingHelperTest, EnableDisable) {
159 const AudioParameters params;
160 std::unique_ptr<AudioDebugRecordingHelper> recording_helper =
161 CreateRecordingHelper(params, base::OnceClosure());
162
163 recording_helper->EnableDebugRecording(file_path_);
164 EXPECT_CALL(*mock_audio_file_writer_, Stop());
165 DisableDebugRecording(recording_helper.get());
166
167 recording_helper->EnableDebugRecording(file_path_);
168 EXPECT_CALL(*mock_audio_file_writer_, Stop());
169 DisableDebugRecording(recording_helper.get());
170 }
171
172 TEST_F(AudioDebugRecordingHelperTest, OnData) {
173 // Only channel layout and frames per buffer is used in the file writer and
174 // AudioBus, the other parameters are ignored.
175 const int number_of_frames = 100;
176 const AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
177 ChannelLayout::CHANNEL_LAYOUT_STEREO, 0, 0,
178 number_of_frames);
179
180 // Setup some data.
181 const int number_of_samples = number_of_frames * params.channels();
182 const float step = std::numeric_limits<int16_t>::max() / number_of_frames;
183 std::unique_ptr<float[]> source_data(new float[number_of_samples]);
184 for (float i = 0; i < number_of_samples; ++i)
185 source_data[i] = i * step;
186 std::unique_ptr<AudioBus> audio_bus = AudioBus::Create(params);
187 audio_bus->FromInterleaved<Float32SampleTypeTraits>(source_data.get(),
188 number_of_frames);
189
190 std::unique_ptr<AudioDebugRecordingHelper> recording_helper =
191 CreateRecordingHelper(params, base::OnceClosure());
192
193 // Should not do anything.
194 recording_helper->OnData(audio_bus.get());
195
196 recording_helper->EnableDebugRecording(file_path_);
197 mock_audio_file_writer_->SetReferenceData(audio_bus.get());
198
199 EXPECT_CALL(*mock_audio_file_writer_, DoWrite(_));
200 recording_helper->OnData(audio_bus.get());
201 base::RunLoop().RunUntilIdle();
202
203 EXPECT_CALL(*mock_audio_file_writer_, Stop());
204 DisableDebugRecording(recording_helper.get());
205
206 // Make sure we clear the loop before enabling again.
207 base::RunLoop().RunUntilIdle();
208
209 // Enable again, this time with two OnData() calls, one OnData() call
210 // without running the message loop until after disabling, and one call after
211 // disabling.
212 recording_helper->EnableDebugRecording(file_path_);
213 mock_audio_file_writer_->SetReferenceData(audio_bus.get());
214
215 EXPECT_CALL(*mock_audio_file_writer_, DoWrite(_)).Times(2);
216 recording_helper->OnData(audio_bus.get());
217 recording_helper->OnData(audio_bus.get());
218 base::RunLoop().RunUntilIdle();
219
220 // This call should not yield a DoWrite() call on the mock, since the message
221 // loop isn't run until after disabling. WillWrite() is expected since
222 // recording is enabled.
223 recording_helper->OnData(audio_bus.get());
224
225 EXPECT_CALL(*mock_audio_file_writer_, Stop());
226 DisableDebugRecording(recording_helper.get());
227
228 // This call should not yield a DoWrite() call on the mock either.
229 recording_helper->OnData(audio_bus.get());
230 base::RunLoop().RunUntilIdle();
231 }
232
233 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698