Reland "Adding unittests to AudioConferenceMixer."

Previous code review, see
https://codereview.chromium.org/1257583011/

Did not pass Mac bots since vector(size_t n) needs copy ctor before C++11.

BUG=

Review URL: https://codereview.webrtc.org/1303273004

Cr-Commit-Position: refs/heads/master@{#9851}
diff --git a/webrtc/modules/audio_conference_mixer/test/audio_conference_mixer_unittest.cc b/webrtc/modules/audio_conference_mixer/test/audio_conference_mixer_unittest.cc
new file mode 100644
index 0000000..d4fbd20
--- /dev/null
+++ b/webrtc/modules/audio_conference_mixer/test/audio_conference_mixer_unittest.cc
@@ -0,0 +1,165 @@
+/*
+ *  Copyright (c) 2015 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 "testing/gmock/include/gmock/gmock.h"
+#include "webrtc/base/scoped_ptr.h"
+#include "webrtc/modules/audio_conference_mixer/interface/audio_conference_mixer.h"
+#include "webrtc/modules/audio_conference_mixer/interface/audio_conference_mixer_defines.h"
+
+namespace webrtc {
+
+using testing::_;
+using testing::AtLeast;
+using testing::Invoke;
+using testing::Return;
+
+class MockAudioMixerOutputReceiver : public AudioMixerOutputReceiver {
+ public:
+  MOCK_METHOD4(NewMixedAudio, void(const int32_t id,
+                                   const AudioFrame& general_audio_frame,
+                                   const AudioFrame** unique_audio_frames,
+                                   const uint32_t size));
+};
+
+class MockMixerParticipant : public MixerParticipant {
+ public:
+  MockMixerParticipant() {
+    ON_CALL(*this, GetAudioFrame(_, _))
+        .WillByDefault(Invoke(this, &MockMixerParticipant::FakeAudioFrame));
+  }
+  MOCK_METHOD2(GetAudioFrame,
+               int32_t(const int32_t id, AudioFrame* audio_frame));
+  MOCK_CONST_METHOD1(NeededFrequency, int32_t(const int32_t id));
+  AudioFrame* fake_frame() { return &fake_frame_; }
+
+ private:
+  AudioFrame fake_frame_;
+  int32_t FakeAudioFrame(const int32_t id, AudioFrame* audio_frame) {
+    audio_frame->CopyFrom(fake_frame_);
+    return 0;
+  }
+};
+
+TEST(AudioConferenceMixer, AnonymousAndNamed) {
+  const int kId = 1;
+  // Should not matter even if partipants are more than
+  // kMaximumAmountOfMixedParticipants.
+  const int kNamed =
+      AudioConferenceMixer::kMaximumAmountOfMixedParticipants + 1;
+  const int kAnonymous =
+      AudioConferenceMixer::kMaximumAmountOfMixedParticipants + 1;
+
+  rtc::scoped_ptr<AudioConferenceMixer> mixer(
+      AudioConferenceMixer::Create(kId));
+
+  MockMixerParticipant named[kNamed];
+  MockMixerParticipant anonymous[kAnonymous];
+
+  for (int i = 0; i < kNamed; ++i) {
+    EXPECT_EQ(0, mixer->SetMixabilityStatus(&named[i], true));
+    EXPECT_TRUE(mixer->MixabilityStatus(named[i]));
+  }
+
+  for (int i = 0; i < kAnonymous; ++i) {
+    // Participant must be registered before turning it into anonymous.
+    EXPECT_EQ(-1, mixer->SetAnonymousMixabilityStatus(&anonymous[i], true));
+    EXPECT_EQ(0, mixer->SetMixabilityStatus(&anonymous[i], true));
+    EXPECT_TRUE(mixer->MixabilityStatus(anonymous[i]));
+    EXPECT_FALSE(mixer->AnonymousMixabilityStatus(anonymous[i]));
+
+    EXPECT_EQ(0, mixer->SetAnonymousMixabilityStatus(&anonymous[i], true));
+    EXPECT_TRUE(mixer->AnonymousMixabilityStatus(anonymous[i]));
+
+    // Anonymous participants do not show status by MixabilityStatus.
+    EXPECT_FALSE(mixer->MixabilityStatus(anonymous[i]));
+  }
+
+  for (int i = 0; i < kNamed; ++i) {
+    EXPECT_EQ(0, mixer->SetMixabilityStatus(&named[i], false));
+    EXPECT_FALSE(mixer->MixabilityStatus(named[i]));
+  }
+
+  for (int i = 0; i < kAnonymous - 1; i++) {
+    EXPECT_EQ(0, mixer->SetAnonymousMixabilityStatus(&anonymous[i], false));
+    EXPECT_FALSE(mixer->AnonymousMixabilityStatus(anonymous[i]));
+
+    // SetAnonymousMixabilityStatus(anonymous, false) moves anonymous to the
+    // named group.
+    EXPECT_TRUE(mixer->MixabilityStatus(anonymous[i]));
+  }
+
+  // SetMixabilityStatus(anonymous, false) will remove anonymous from both
+  // anonymous and named groups.
+  EXPECT_EQ(0, mixer->SetMixabilityStatus(&anonymous[kAnonymous - 1], false));
+  EXPECT_FALSE(mixer->AnonymousMixabilityStatus(anonymous[kAnonymous - 1]));
+  EXPECT_FALSE(mixer->MixabilityStatus(anonymous[kAnonymous - 1]));
+}
+
+TEST(AudioConferenceMixer, LargestEnergyVadActiveMixed) {
+  const int kId = 1;
+  const int kParticipants =
+      AudioConferenceMixer::kMaximumAmountOfMixedParticipants + 3;
+  const int kSampleRateHz = 32000;
+
+  rtc::scoped_ptr<AudioConferenceMixer> mixer(
+      AudioConferenceMixer::Create(kId));
+
+  MockAudioMixerOutputReceiver output_receiver;
+  EXPECT_EQ(0, mixer->RegisterMixedStreamCallback(&output_receiver));
+
+  MockMixerParticipant participants[kParticipants];
+
+  for (int i = 0; i < kParticipants; ++i) {
+    participants[i].fake_frame()->id_ = i;
+    participants[i].fake_frame()->sample_rate_hz_ = kSampleRateHz;
+    participants[i].fake_frame()->speech_type_ =  AudioFrame::kNormalSpeech;
+    participants[i].fake_frame()->vad_activity_ = AudioFrame::kVadActive;
+    participants[i].fake_frame()->num_channels_ = 1;
+
+    // Frame duration 10ms.
+    participants[i].fake_frame()->samples_per_channel_ = kSampleRateHz / 100;
+
+    // We set the 80-th sample value since the first 80 samples may be
+    // modified by a ramped-in window.
+    participants[i].fake_frame()->data_[80] = i;
+
+    EXPECT_EQ(0, mixer->SetMixabilityStatus(&participants[i], true));
+    EXPECT_CALL(participants[i], GetAudioFrame(_, _))
+        .Times(AtLeast(1));
+    EXPECT_CALL(participants[i], NeededFrequency(_))
+        .WillRepeatedly(Return(kSampleRateHz));
+  }
+
+  // Last participant gives audio frame with passive VAD, although it has the
+  // largest energy.
+  participants[kParticipants - 1].fake_frame()->vad_activity_ =
+      AudioFrame::kVadPassive;
+
+  EXPECT_CALL(output_receiver, NewMixedAudio(_, _, _, _))
+      .Times(AtLeast(1));
+
+  EXPECT_EQ(0, mixer->Process());
+
+  for (int i = 0; i < kParticipants; ++i) {
+    bool is_mixed = participants[i].IsMixed();
+    if (i == kParticipants - 1 || i < kParticipants - 1 -
+        AudioConferenceMixer::kMaximumAmountOfMixedParticipants) {
+      EXPECT_FALSE(is_mixed) << "Mixing status of Participant #"
+                             << i << " wrong.";
+    } else {
+      EXPECT_TRUE(is_mixed) << "Mixing status of Participant #"
+                            << i << " wrong.";
+    }
+  }
+
+  EXPECT_EQ(0, mixer->UnRegisterMixedStreamCallback());
+}
+
+}  // namespace webrtc
diff --git a/webrtc/modules/modules.gyp b/webrtc/modules/modules.gyp
index 65921a5..8204b90 100644
--- a/webrtc/modules/modules.gyp
+++ b/webrtc/modules/modules.gyp
@@ -58,6 +58,7 @@
             'acm_receive_test',
             'acm_send_test',
             'audio_coding_module',
+            'audio_conference_mixer',
             'audio_device'  ,
             'audio_processing',
             'audioproc_test_utils',
@@ -158,6 +159,7 @@
             'audio_coding/neteq/mock/mock_payload_splitter.h',
             'audio_coding/neteq/tools/input_audio_file_unittest.cc',
             'audio_coding/neteq/tools/packet_unittest.cc',
+            'audio_conference_mixer/test/audio_conference_mixer_unittest.cc',
             'audio_processing/aec/echo_cancellation_unittest.cc',
             'audio_processing/aec/system_delay_unittest.cc',
             # TODO(ajm): Fix to match new interface.