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 "services/audio/sync_reader.h"
6 
7 #include <limits>
8 #include <memory>
9 #include <string>
10 #include <type_traits>
11 #include <utility>
12 
13 #include "base/bind.h"
14 #include "base/memory/unsafe_shared_memory_region.h"
15 #include "base/sync_socket.h"
16 #include "base/test/task_environment.h"
17 #include "base/time/time.h"
18 #include "media/base/audio_bus.h"
19 #include "media/base/audio_parameters.h"
20 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22 
23 using ::testing::TestWithParam;
24 
25 using media::AudioBus;
26 using media::AudioOutputBuffer;
27 using media::AudioOutputBufferParameters;
28 using media::AudioParameters;
29 
30 namespace audio {
31 
NoLog(const std::string &)32 void NoLog(const std::string&) {}
33 
34 static_assert(
35     std::is_unsigned<
36         decltype(AudioOutputBufferParameters::bitstream_data_size)>::value,
37     "If |bitstream_data_size| is ever made signed, add tests for negative "
38     "buffer sizes.");
39 
40 enum OverflowTestCase {
41   kZero,
42   kNoOverflow,
43   kOverflowByOne,
44   kOverflowByOneThousand,
45   kOverflowByMax
46 };
47 
48 static const OverflowTestCase overflow_test_case_values[]{
49     kZero, kNoOverflow, kOverflowByOne, kOverflowByOneThousand, kOverflowByMax};
50 
51 class SyncReaderBitstreamTest : public TestWithParam<OverflowTestCase> {
52  public:
SyncReaderBitstreamTest()53   SyncReaderBitstreamTest() {}
~SyncReaderBitstreamTest()54   ~SyncReaderBitstreamTest() override {}
55 
56  private:
57   base::test::TaskEnvironment env_;
58 };
59 
TEST_P(SyncReaderBitstreamTest,BitstreamBufferOverflow_DoesNotWriteOOB)60 TEST_P(SyncReaderBitstreamTest, BitstreamBufferOverflow_DoesNotWriteOOB) {
61   const int kSampleRate = 44100;
62   const int kFramesPerBuffer = 1;
63   AudioParameters params(AudioParameters::AUDIO_BITSTREAM_AC3,
64                          media::CHANNEL_LAYOUT_STEREO, kSampleRate,
65                          kFramesPerBuffer);
66 
67   auto socket = std::make_unique<base::CancelableSyncSocket>();
68   SyncReader reader(base::BindRepeating(&NoLog), params, socket.get());
69   ASSERT_TRUE(reader.IsValid());
70   const base::WritableSharedMemoryMapping shmem =
71       reader.TakeSharedMemoryRegion().Map();
72   ASSERT_TRUE(shmem.IsValid());
73   auto* const buffer =
74       reinterpret_cast<media::AudioOutputBuffer*>(shmem.memory());
75   ASSERT_TRUE(buffer);
76   reader.RequestMoreData(base::TimeDelta(), base::TimeTicks(), 0);
77 
78   uint32_t signal;
79   EXPECT_EQ(socket->Receive(&signal, sizeof(signal)), sizeof(signal));
80 
81   // So far, this is an ordinary stream.
82   // Now |reader| expects data to be written to the shared memory. The renderer
83   // says how much data was written.
84   switch (GetParam()) {
85     case kZero:
86       buffer->params.bitstream_data_size = 0;
87       break;
88     case kNoOverflow:
89       buffer->params.bitstream_data_size =
90           shmem.mapped_size() - sizeof(AudioOutputBufferParameters);
91       break;
92     case kOverflowByOne:
93       buffer->params.bitstream_data_size =
94           shmem.mapped_size() - sizeof(AudioOutputBufferParameters) + 1;
95       break;
96     case kOverflowByOneThousand:
97       buffer->params.bitstream_data_size =
98           shmem.mapped_size() - sizeof(AudioOutputBufferParameters) + 1000;
99       break;
100     case kOverflowByMax:
101       buffer->params.bitstream_data_size = std::numeric_limits<decltype(
102           buffer->params.bitstream_data_size)>::max();
103       break;
104   }
105 
106   ++signal;
107   EXPECT_EQ(socket->Send(&signal, sizeof(signal)), sizeof(signal));
108 
109   // The purpose of the test is to ensure this call doesn't result in undefined
110   // behavior, which should be verified by sanitizers.
111   std::unique_ptr<AudioBus> output_bus = AudioBus::Create(params);
112   reader.Read(output_bus.get());
113 }
114 
115 INSTANTIATE_TEST_SUITE_P(All,
116                          SyncReaderBitstreamTest,
117                          ::testing::ValuesIn(overflow_test_case_values));
118 
119 }  // namespace audio
120