diff --git a/src/common_audio/common_audio.gyp b/src/common_audio/common_audio.gyp index 9d7d0b2e9c..743e9daf9f 100644 --- a/src/common_audio/common_audio.gyp +++ b/src/common_audio/common_audio.gyp @@ -8,9 +8,28 @@ { 'includes': [ - '../common_settings.gypi', # Common settings + '../build/common.gypi', 'signal_processing_library/main/source/spl.gypi', 'resampler/main/source/resampler.gypi', 'vad/main/source/vad.gypi', ], + 'conditions': [ + ['build_with_chromium==0', { + 'targets' : [ + { + 'target_name': 'common_audio_unittests', + 'type': 'executable', + 'dependencies': [ + '<(webrtc_root)/../test/test.gyp:test_support', + '<(webrtc_root)/../testing/gtest.gyp:gtest', + 'resampler', + ], + 'sources': [ + '<(webrtc_root)/../test/run_all_unittests.cc', + 'resampler/main/source/resampler_unittest.cc', + ], + }, + ], + }], + ], } diff --git a/src/common_audio/resampler/main/interface/resampler.h b/src/common_audio/resampler/main/interface/resampler.h index b910098087..41f1a87bc2 100644 --- a/src/common_audio/resampler/main/interface/resampler.h +++ b/src/common_audio/resampler/main/interface/resampler.h @@ -22,7 +22,7 @@ namespace webrtc { // TODO(andrew): the implementation depends on the exact values of this enum. -// It should be rewritten in a less fragile way. +// It should be rewritten in a less fragile way. enum ResamplerType { // 4 MSB = Number of channels @@ -35,6 +35,7 @@ enum ResamplerType kResamplerInvalid = 0xff }; +// TODO(andrew): doesn't need to be part of the interface. enum ResamplerMode { kResamplerMode1To1, @@ -63,6 +64,7 @@ class Resampler public: Resampler(); + // TODO(andrew): use an init function instead. Resampler(int inFreq, int outFreq, ResamplerType type); ~Resampler(); diff --git a/src/common_audio/resampler/main/source/resampler.cc b/src/common_audio/resampler/main/source/resampler.cc index b7d9ead82d..b175e27d44 100644 --- a/src/common_audio/resampler/main/source/resampler.cc +++ b/src/common_audio/resampler/main/source/resampler.cc @@ -62,8 +62,6 @@ Resampler::Resampler(int inFreq, int outFreq, ResamplerType type) slave_left_ = NULL; slave_right_ = NULL; - // TODO(andrew): looks like this class should use an init method - // (and possibly a static create). Reset(inFreq, outFreq, type); } @@ -213,7 +211,7 @@ int Resampler::Reset(int inFreq, int outFreq, ResamplerType type) break; default: my_type_ = kResamplerInvalid; - break; + return -1; } } else if (outFreq == 1) { @@ -233,7 +231,7 @@ int Resampler::Reset(int inFreq, int outFreq, ResamplerType type) break; default: my_type_ = kResamplerInvalid; - break; + return -1; } } else if ((inFreq == 2) && (outFreq == 3)) { diff --git a/src/common_audio/resampler/main/source/resampler_unittest.cc b/src/common_audio/resampler/main/source/resampler_unittest.cc new file mode 100644 index 0000000000..ea91ea4e60 --- /dev/null +++ b/src/common_audio/resampler/main/source/resampler_unittest.cc @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "gtest/gtest.h" + +#include "common_audio/resampler/main/interface/resampler.h" + +// TODO(andrew): this is a work-in-progress. Many more tests are needed. + +namespace webrtc { +namespace { +const ResamplerType kTypes[] = { + kResamplerSynchronous, + kResamplerAsynchronous, + kResamplerSynchronousStereo, + kResamplerAsynchronousStereo + // kResamplerInvalid excluded +}; +const size_t kTypesSize = sizeof(kTypes) / sizeof(*kTypes); + +// Rates we must support. +const int kMaxRate = 96000; +const int kRates[] = { + 8000, + 16000, + 32000, + 44000, + 48000, + kMaxRate +}; +const size_t kRatesSize = sizeof(kRates) / sizeof(*kRates); +const size_t kDataSize = kMaxRate / 100; + +// TODO(andrew): should we be supporting these combinations? +bool ValidRates(int in_rate, int out_rate) { + // Not the most compact notation, for clarity. + if ((in_rate == 44000 && (out_rate == 48000 || out_rate == 96000)) || + (out_rate == 44000 && (in_rate == 48000 || in_rate == 96000)) || + (in_rate == 8000 && out_rate == 96000) || + (in_rate == 96000 && out_rate == 8000)) { + return false; + } + + return true; +} + +class ResamplerTest : public testing::Test { + protected: + ResamplerTest(); + virtual void SetUp(); + virtual void TearDown(); + + Resampler rs_; + int16_t data_in_[kDataSize]; + int16_t data_out_[kDataSize]; +}; + +ResamplerTest::ResamplerTest() { +} + +void ResamplerTest::SetUp() { +} + +void ResamplerTest::TearDown() { +} + +TEST_F(ResamplerTest, Reset) { + // The only failure mode for the constructor is if Reset() fails. For the + // time being then (until an Init function is added), we rely on Reset() + // to test the constructor. + + // Check that all required combinations are supported. + for (size_t i = 0; i < kRatesSize; ++i) { + for (size_t j = 0; j < kRatesSize; ++j) { + for (size_t k = 0; k < kTypesSize; ++k) { + std::ostringstream ss; + ss << "Input rate: " << kRates[i] << ", output rate: " << kRates[j] + << ", type: " << kTypes[k]; + SCOPED_TRACE(ss.str()); + if (ValidRates(kRates[i], kRates[j])) + EXPECT_EQ(0, rs_.Reset(kRates[i], kRates[j], kTypes[k])); + else + EXPECT_EQ(-1, rs_.Reset(kRates[i], kRates[j], kTypes[k])); + } + } + } +} + +TEST_F(ResamplerTest, Synchronous) { + for (size_t i = 0; i < kRatesSize; ++i) { + for (size_t j = 0; j < kRatesSize; ++j) { + std::ostringstream ss; + ss << "Input rate: " << kRates[i] << ", output rate: " << kRates[j]; + SCOPED_TRACE(ss.str()); + + if (ValidRates(kRates[i], kRates[j])) { + int in_length = kRates[i] / 100; + int out_length = 0; + EXPECT_EQ(0, rs_.Reset(kRates[i], kRates[j], kResamplerSynchronous)); + EXPECT_EQ(0, rs_.Push(data_in_, in_length, data_out_, kDataSize, + out_length)); + EXPECT_EQ(kRates[j] / 100, out_length); + } else { + EXPECT_EQ(-1, rs_.Reset(kRates[i], kRates[j], kResamplerSynchronous)); + } + } + } + + // TODO(andrew): test stereo. +} +} // namespace +} // namespace webrtc diff --git a/test/run_all_unittests.cc b/test/run_all_unittests.cc new file mode 100644 index 0000000000..d8f3dd8442 --- /dev/null +++ b/test/run_all_unittests.cc @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "test/test_suite.h" + +int main(int argc, char** argv) { + webrtc::TestSuite test_suite(argc, argv); + return test_suite.Run(); +} diff --git a/test/test.gyp b/test/test.gyp new file mode 100644 index 0000000000..728a240410 --- /dev/null +++ b/test/test.gyp @@ -0,0 +1,27 @@ +# Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. +# +# Use of this source code is governed by a BSD-style license +# that can be found in the LICENSE file in the root of the source +# tree. An additional intellectual property rights grant can be found +# in the file PATENTS. All contributing project authors may +# be found in the AUTHORS file in the root of the source tree. + +# TODO(andrew): consider moving test_support to src/base/test. +{ + 'includes': [ + '../src/build/common.gypi', + ], + 'targets': [ + { + 'target_name': 'test_support', + 'type': 'static_library', + 'dependencies': [ + '../testing/gtest.gyp:gtest', + ], + 'sources': [ + 'test_suite.cc', + 'test_suite.h', + ], + }, + ], +} diff --git a/test/test_suite.cc b/test/test_suite.cc new file mode 100644 index 0000000000..05cfcc43da --- /dev/null +++ b/test/test_suite.cc @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "test/test_suite.h" + +#include "gtest/gtest.h" + +namespace webrtc { +TestSuite::TestSuite(int argc, char** argv) { + testing::InitGoogleTest(&argc, argv); +} + +TestSuite::~TestSuite() { +} + +int TestSuite::Run() { + Initialize(); + int result = RUN_ALL_TESTS(); + Shutdown(); + return result; +} + +void TestSuite::Initialize() { + // TODO(andrew): initialize singletons here (e.g. Trace). +} + +void TestSuite::Shutdown() { +} +} // namespace webrtc diff --git a/test/test_suite.h b/test/test_suite.h new file mode 100644 index 0000000000..580565c174 --- /dev/null +++ b/test/test_suite.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef TEST_TEST_SUITE_H_ +#define TEST_TEST_SUITE_H_ + +// Derived from Chromium's src/base/test/test_suite.h. + +// Defines a basic test suite framework for running gtest based tests. You can +// instantiate this class in your main function and call its Run method to run +// any gtest based tests that are linked into your executable. + +#include "src/system_wrappers/interface/constructor_magic.h" + +namespace webrtc { +class TestSuite { + public: + TestSuite(int argc, char** argv); + virtual ~TestSuite(); + + int Run(); + + protected: + // Override these for custom initialization and shutdown handling. Use these + // instead of putting complex code in your constructor/destructor. + virtual void Initialize(); + virtual void Shutdown(); + + DISALLOW_COPY_AND_ASSIGN(TestSuite); +}; +} // namespace webrtc + +#endif // TEST_TEST_SUITE_H_ diff --git a/webrtc.gyp b/webrtc.gyp index 55f5ea9d0a..ee8c14e928 100644 --- a/webrtc.gyp +++ b/webrtc.gyp @@ -8,24 +8,26 @@ { 'includes': [ - 'src/common_settings.gypi', # Common settings + 'src/build/common.gypi', ], - 'targets': [ + 'targets': [ { - 'target_name': 'auto_tests', + 'target_name': 'All', 'type': 'none', 'dependencies': [ - 'src/voice_engine/voice_engine.gyp:voe_auto_test', + 'src/common_audio/common_audio.gyp:*', + # TODO(andrew): enable these when all tests build. + #'src/common_video/common_video.gyp:*', + #'src/modules/modules.gyp:*', + #'src/system_wrappers/source/system_wrappers.gyp:*', + # TODO(andrew): move the merge_lib targets to a private gyp so we can + # target "*" in these. 'src/video_engine/video_engine.gyp:vie_auto_test', - ], - }, - { - 'target_name': 'cmd_test', - 'type': 'none', - 'dependencies': [ + 'src/voice_engine/voice_engine.gyp:voe_auto_test', 'src/voice_engine/voice_engine.gyp:voe_cmd_test', ], - }, + }, + # TODO(andrew): move peerconnection to its own gyp. { 'target_name': 'peerconnection_server', 'type': 'executable', @@ -61,7 +63,7 @@ ], 'msvs_settings': { 'VCLinkerTool': { - 'SubSystem': '2', # Windows + 'SubSystem': '2', # Windows }, }, 'dependencies': [ @@ -116,5 +118,5 @@ }, ], # targets }, ], # OS="linux" - ], # conditions + ], # conditions }