// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/renderer/media/stream/media_stream_constraints_util_audio.h"

#include <cmath>
#include <memory>
#include <string>
#include <utility>

#include "base/message_loop/message_loop.h"
#include "content/renderer/media/stream/local_media_stream_audio_source.h"
#include "content/renderer/media/stream/media_stream_audio_source.h"
#include "content/renderer/media/stream/media_stream_source.h"
#include "content/renderer/media/stream/mock_constraint_factory.h"
#include "content/renderer/media/stream/processed_local_audio_source.h"
#include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h"
#include "media/base/audio_parameters.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/modules/mediastream/media_devices.mojom.h"
#include "third_party/blink/public/platform/web_media_constraints.h"
#include "third_party/blink/public/platform/web_string.h"

namespace content {

using EchoCancellationType = AudioProcessingProperties::EchoCancellationType;

namespace {

using BoolSetFunction = void (blink::BooleanConstraint::*)(bool);
using StringSetFunction =
    void (blink::StringConstraint::*)(const blink::WebString&);
using MockFactoryAccessor =
    blink::WebMediaTrackConstraintSet& (MockConstraintFactory::*)();

const BoolSetFunction kBoolSetFunctions[] = {
    &blink::BooleanConstraint::SetExact, &blink::BooleanConstraint::SetIdeal,
};

const StringSetFunction kStringSetFunctions[] = {
    &blink::StringConstraint::SetExact, &blink::StringConstraint::SetIdeal,
};

const MockFactoryAccessor kFactoryAccessors[] = {
    &MockConstraintFactory::basic, &MockConstraintFactory::AddAdvanced};

const bool kBoolValues[] = {true, false};

using AudioSettingsBoolMembers =
    std::vector<bool (AudioCaptureSettings::*)() const>;
using AudioPropertiesBoolMembers =
    std::vector<bool AudioProcessingProperties::*>;

template <typename T>
static bool Contains(const std::vector<T>& vector, T value) {
  auto it = std::find(vector.begin(), vector.end(), value);
  return it != vector.end();
}

}  // namespace

// This class is only used for setting |override_aec3_|. We simply inject the
// current task runner since they are not used.
class AecDumpMessageFilterForTest : public AecDumpMessageFilter {
 public:
  AecDumpMessageFilterForTest()
      : AecDumpMessageFilter(base::MessageLoopCurrent::Get()->task_runner(),
                             base::MessageLoopCurrent::Get()->task_runner()) {}

  void set_override_aec3(base::Optional<bool> override_aec3) {
    override_aec3_ = override_aec3;
  }

 protected:
  ~AecDumpMessageFilterForTest() override {}
};

class MediaStreamConstraintsUtilAudioTest
    : public testing::TestWithParam<std::string> {
 public:
  void SetUp() override {
    ResetFactory();
    if (IsDeviceCapture()) {
      capabilities_.emplace_back(
          "default_device", "fake_group1",
          media::AudioParameters(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
                                 media::CHANNEL_LAYOUT_STEREO,
                                 media::AudioParameters::kAudioCDSampleRate,
                                 1000));

      media::AudioParameters system_echo_canceller_parameters(
          media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
          media::CHANNEL_LAYOUT_STEREO,
          media::AudioParameters::kAudioCDSampleRate, 1000);
      system_echo_canceller_parameters.set_effects(
          media::AudioParameters::ECHO_CANCELLER);
      capabilities_.emplace_back("system_echo_canceller_device", "fake_group2",
                                 system_echo_canceller_parameters);

      default_device_ = &capabilities_[0];
      system_echo_canceller_device_ = &capabilities_[1];
    } else {
      // For content capture, use a single capability that admits all possible
      // settings.
      capabilities_.emplace_back();
    }
  }

 protected:
  void MakeSystemEchoCancellerDeviceExperimental() {
    media::AudioParameters experimental_system_echo_canceller_parameters(
        media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
        media::CHANNEL_LAYOUT_STEREO,
        media::AudioParameters::kAudioCDSampleRate, 1000);
    experimental_system_echo_canceller_parameters.set_effects(
        media::AudioParameters::EXPERIMENTAL_ECHO_CANCELLER);
    capabilities_[1] = {"experimental_system_echo_canceller_device",
                        "fake_group3",
                        experimental_system_echo_canceller_parameters};
  }

  void SetMediaStreamSource(const std::string& source) {}

  void ResetFactory() {
    constraint_factory_.Reset();
    constraint_factory_.basic().media_stream_source.SetExact(
        blink::WebString::FromASCII(GetParam()));
  }

  std::string GetMediaStreamSource() { return GetParam(); }
  bool IsDeviceCapture() { return GetMediaStreamSource().empty(); }

  MediaStreamType GetMediaStreamType() {
    std::string media_source = GetMediaStreamSource();
    if (media_source.empty())
      return MEDIA_DEVICE_AUDIO_CAPTURE;
    else if (media_source == kMediaStreamSourceTab)
      return MEDIA_GUM_TAB_AUDIO_CAPTURE;
    return MEDIA_GUM_DESKTOP_AUDIO_CAPTURE;
  }

  std::unique_ptr<ProcessedLocalAudioSource> GetProcessedLocalAudioSource(
      const AudioProcessingProperties& properties,
      bool hotword_enabled,
      bool disable_local_echo,
      bool render_to_associated_sink,
      int effects) {
    MediaStreamDevice device;
    device.id = "processed_source";
    device.type = GetMediaStreamType();
    if (render_to_associated_sink)
      device.matched_output_device_id = std::string("some_device_id");
    device.input.set_effects(effects);

    return std::make_unique<ProcessedLocalAudioSource>(
        -1, device, hotword_enabled, disable_local_echo, properties,
        MediaStreamSource::ConstraintsCallback(), &pc_factory_);
  }

  std::unique_ptr<ProcessedLocalAudioSource> GetProcessedLocalAudioSource(
      const AudioProcessingProperties& properties,
      bool hotword_enabled,
      bool disable_local_echo,
      bool render_to_associated_sink) {
    return GetProcessedLocalAudioSource(
        properties, hotword_enabled, disable_local_echo,
        render_to_associated_sink,
        media::AudioParameters::PlatformEffectsMask::NO_EFFECTS);
  }

  std::unique_ptr<LocalMediaStreamAudioSource> GetLocalMediaStreamAudioSource(
      bool enable_system_echo_canceller,
      bool hotword_enabled,
      bool disable_local_echo,
      bool render_to_associated_sink) {
    MediaStreamDevice device;
    device.type = GetMediaStreamType();
    if (enable_system_echo_canceller)
      device.input.set_effects(media::AudioParameters::ECHO_CANCELLER);
    if (render_to_associated_sink)
      device.matched_output_device_id = std::string("some_device_id");

    return std::make_unique<LocalMediaStreamAudioSource>(
        -1, device, hotword_enabled, disable_local_echo,
        MediaStreamSource::ConstraintsCallback());
  }

  AudioCaptureSettings SelectSettings() {
    blink::WebMediaConstraints constraints =
        constraint_factory_.CreateWebMediaConstraints();
    return SelectSettingsAudioCapture(capabilities_, constraints, false);
  }

  // When googExperimentalEchoCancellation is not explicitly set, its default
  // value is always false on Android. On other platforms it behaves like other
  // audio-processing properties.
  void CheckGoogExperimentalEchoCancellationDefault(
      const AudioProcessingProperties& properties,
      bool value) {
#if defined(OS_ANDROID)
    EXPECT_FALSE(properties.goog_experimental_echo_cancellation);
#else
    EXPECT_EQ(value, properties.goog_experimental_echo_cancellation);
#endif
  }

  void CheckBoolDefaultsDeviceCapture(
      const AudioSettingsBoolMembers& exclude_main_settings,
      const AudioPropertiesBoolMembers& exclude_audio_properties,
      const AudioCaptureSettings& result) {
    if (!Contains(exclude_main_settings,
                  &AudioCaptureSettings::hotword_enabled)) {
      EXPECT_FALSE(result.hotword_enabled());
    }
    if (!Contains(exclude_main_settings,
                  &AudioCaptureSettings::disable_local_echo)) {
      EXPECT_TRUE(result.disable_local_echo());
    }
    if (!Contains(exclude_main_settings,
                  &AudioCaptureSettings::render_to_associated_sink)) {
      EXPECT_FALSE(result.render_to_associated_sink());
    }

    const auto& properties = result.audio_processing_properties();
    if (!Contains(exclude_audio_properties,
                  &AudioProcessingProperties::goog_audio_mirroring)) {
      EXPECT_FALSE(properties.goog_audio_mirroring);
    }
    if (!Contains(exclude_audio_properties,
                  &AudioProcessingProperties::goog_auto_gain_control)) {
      EXPECT_TRUE(properties.goog_auto_gain_control);
    }
    if (!Contains(
            exclude_audio_properties,
            &AudioProcessingProperties::goog_experimental_echo_cancellation)) {
      CheckGoogExperimentalEchoCancellationDefault(properties, true);
    }
    if (!Contains(exclude_audio_properties,
                  &AudioProcessingProperties::goog_typing_noise_detection)) {
      EXPECT_TRUE(properties.goog_typing_noise_detection);
    }
    if (!Contains(exclude_audio_properties,
                  &AudioProcessingProperties::goog_noise_suppression)) {
      EXPECT_TRUE(properties.goog_noise_suppression);
    }
    if (!Contains(
            exclude_audio_properties,
            &AudioProcessingProperties::goog_experimental_noise_suppression)) {
      EXPECT_TRUE(properties.goog_experimental_noise_suppression);
    }
    if (!Contains(exclude_audio_properties,
                  &AudioProcessingProperties::goog_highpass_filter)) {
      EXPECT_TRUE(properties.goog_highpass_filter);
    }
    if (!Contains(
            exclude_audio_properties,
            &AudioProcessingProperties::goog_experimental_auto_gain_control)) {
      EXPECT_TRUE(properties.goog_experimental_auto_gain_control);
    }
  }

  void CheckBoolDefaultsContentCapture(
      const AudioSettingsBoolMembers& exclude_main_settings,
      const AudioPropertiesBoolMembers& exclude_audio_properties,
      const AudioCaptureSettings& result) {
    if (!Contains(exclude_main_settings,
                  &AudioCaptureSettings::hotword_enabled)) {
      EXPECT_FALSE(result.hotword_enabled());
    }
    if (!Contains(exclude_main_settings,
                  &AudioCaptureSettings::disable_local_echo)) {
      EXPECT_EQ(GetMediaStreamSource() != kMediaStreamSourceDesktop,
                result.disable_local_echo());
    }
    if (!Contains(exclude_main_settings,
                  &AudioCaptureSettings::render_to_associated_sink)) {
      EXPECT_FALSE(result.render_to_associated_sink());
    }

    const auto& properties = result.audio_processing_properties();
    if (!Contains(exclude_audio_properties,
                  &AudioProcessingProperties::goog_audio_mirroring)) {
      EXPECT_FALSE(properties.goog_audio_mirroring);
    }
    if (!Contains(exclude_audio_properties,
                  &AudioProcessingProperties::goog_auto_gain_control)) {
      EXPECT_FALSE(properties.goog_auto_gain_control);
    }
    if (!Contains(
            exclude_audio_properties,
            &AudioProcessingProperties::goog_experimental_echo_cancellation)) {
      EXPECT_FALSE(properties.goog_experimental_echo_cancellation);
    }
    if (!Contains(exclude_audio_properties,
                  &AudioProcessingProperties::goog_typing_noise_detection)) {
      EXPECT_FALSE(properties.goog_typing_noise_detection);
    }
    if (!Contains(exclude_audio_properties,
                  &AudioProcessingProperties::goog_noise_suppression)) {
      EXPECT_FALSE(properties.goog_noise_suppression);
    }
    if (!Contains(
            exclude_audio_properties,
            &AudioProcessingProperties::goog_experimental_noise_suppression)) {
      EXPECT_FALSE(properties.goog_experimental_noise_suppression);
    }
    if (!Contains(exclude_audio_properties,
                  &AudioProcessingProperties::goog_highpass_filter)) {
      EXPECT_FALSE(properties.goog_highpass_filter);
    }
    if (!Contains(
            exclude_audio_properties,
            &AudioProcessingProperties::goog_experimental_auto_gain_control)) {
      EXPECT_FALSE(properties.goog_experimental_auto_gain_control);
    }
  }

  void CheckBoolDefaults(
      const AudioSettingsBoolMembers& exclude_main_settings,
      const AudioPropertiesBoolMembers& exclude_audio_properties,
      const AudioCaptureSettings& result) {
    if (IsDeviceCapture()) {
      CheckBoolDefaultsDeviceCapture(exclude_main_settings,
                                     exclude_audio_properties, result);
    } else {
      CheckBoolDefaultsContentCapture(exclude_main_settings,
                                      exclude_audio_properties, result);
    }
  }

  void CheckEchoCancellationTypeDefault(const AudioCaptureSettings& result) {
    const auto& properties = result.audio_processing_properties();
    if (IsDeviceCapture()) {
      EXPECT_EQ(properties.echo_cancellation_type,
                EchoCancellationType::kEchoCancellationAec2);
    } else {
      EXPECT_EQ(properties.echo_cancellation_type,
                EchoCancellationType::kEchoCancellationDisabled);
    }
  }

  void CheckDevice(const AudioDeviceCaptureCapability& expected_device,
                   const AudioCaptureSettings& result) {
    EXPECT_EQ(expected_device.DeviceID(), result.device_id());
    EXPECT_EQ(expected_device.Parameters().sample_rate(),
              result.device_parameters().sample_rate());
    EXPECT_EQ(expected_device.Parameters().channels(),
              result.device_parameters().channels());
    EXPECT_EQ(expected_device.Parameters().effects(),
              result.device_parameters().effects());
  }

  void CheckDeviceDefaults(const AudioCaptureSettings& result) {
    if (IsDeviceCapture())
      CheckDevice(*default_device_, result);
    else
      EXPECT_TRUE(result.device_id().empty());
  }

  void CheckAllDefaults(
      const AudioSettingsBoolMembers& exclude_main_settings,
      const AudioPropertiesBoolMembers& exclude_audio_properties,
      const AudioCaptureSettings& result) {
    CheckBoolDefaults(exclude_main_settings, exclude_audio_properties, result);
    CheckEchoCancellationTypeDefault(result);
    CheckDeviceDefaults(result);
  }

  // Assumes that echoCancellation is set to true as a basic, exact constraint.
  void CheckAudioProcessingPropertiesForExactEchoCancellationType(
      const blink::WebString& echo_cancellation_type_constraint,
      const AudioCaptureSettings& result) {
    const AudioProcessingProperties& properties =
        result.audio_processing_properties();

    // With device capture, the echo_cancellation constraint
    // enables/disables all audio processing by default.
    // With content capture, the echo_cancellation constraint controls
    // only the echo_cancellation properties. The other audio processing
    // properties default to false.
    const EchoCancellationType expected_ec_type =
        GetEchoCancellationTypeFromConstraintString(
            echo_cancellation_type_constraint);
    if (!IsDeviceCapture()) {
      ASSERT_NE(EchoCancellationType::kEchoCancellationSystem,
                expected_ec_type);
    }
    EXPECT_EQ(expected_ec_type, properties.echo_cancellation_type);

    const bool enable_webrtc_audio_processing = IsDeviceCapture();
    EXPECT_EQ(enable_webrtc_audio_processing,
              properties.goog_auto_gain_control);
    CheckGoogExperimentalEchoCancellationDefault(
        properties, enable_webrtc_audio_processing);
    EXPECT_EQ(enable_webrtc_audio_processing,
              properties.goog_typing_noise_detection);
    EXPECT_EQ(enable_webrtc_audio_processing,
              properties.goog_noise_suppression);
    EXPECT_EQ(enable_webrtc_audio_processing,
              properties.goog_experimental_noise_suppression);
    EXPECT_EQ(enable_webrtc_audio_processing, properties.goog_highpass_filter);
    EXPECT_EQ(enable_webrtc_audio_processing,
              properties.goog_experimental_auto_gain_control);

    // The following are not audio processing.
    EXPECT_FALSE(properties.goog_audio_mirroring);
    EXPECT_FALSE(result.hotword_enabled());
    EXPECT_EQ(GetMediaStreamSource() != kMediaStreamSourceDesktop,
              result.disable_local_echo());
    EXPECT_FALSE(result.render_to_associated_sink());
    if (IsDeviceCapture()) {
      CheckDevice(
          expected_ec_type == EchoCancellationType::kEchoCancellationSystem
              ? *system_echo_canceller_device_
              : *default_device_,
          result);
    } else {
      EXPECT_TRUE(result.device_id().empty());
    }
  }

  void CheckAudioProcessingPropertiesForIdealEchoCancellationType(
      const AudioCaptureSettings& result) {
    const AudioProcessingProperties& properties =
        result.audio_processing_properties();

    EXPECT_EQ(EchoCancellationType::kEchoCancellationSystem,
              properties.echo_cancellation_type);
    EXPECT_TRUE(properties.goog_auto_gain_control);
    CheckGoogExperimentalEchoCancellationDefault(properties, true);
    EXPECT_TRUE(properties.goog_typing_noise_detection);
    EXPECT_TRUE(properties.goog_noise_suppression);
    EXPECT_TRUE(properties.goog_experimental_noise_suppression);
    EXPECT_TRUE(properties.goog_highpass_filter);
    EXPECT_TRUE(properties.goog_experimental_auto_gain_control);

    // The following are not audio processing.
    EXPECT_FALSE(properties.goog_audio_mirroring);
    EXPECT_FALSE(result.hotword_enabled());
    EXPECT_EQ(GetMediaStreamSource() != kMediaStreamSourceDesktop,
              result.disable_local_echo());
    EXPECT_FALSE(result.render_to_associated_sink());
    CheckDevice(*system_echo_canceller_device_, result);
  }

  EchoCancellationType GetEchoCancellationTypeFromConstraintString(
      const blink::WebString& constraint_string) {
    if (constraint_string == kEchoCancellationTypeValues[0])
      return EchoCancellationType::kEchoCancellationAec2;
    if (constraint_string == kEchoCancellationTypeValues[1])
      return EchoCancellationType::kEchoCancellationAec3;
    if (constraint_string == kEchoCancellationTypeValues[2])
      return EchoCancellationType::kEchoCancellationSystem;

    ADD_FAILURE() << "Invalid echo cancellation type constraint: "
                  << constraint_string.Ascii();
    return EchoCancellationType::kEchoCancellationDisabled;
  }

  MockConstraintFactory constraint_factory_;
  AudioDeviceCaptureCapabilities capabilities_;
  const AudioDeviceCaptureCapability* default_device_ = nullptr;
  const AudioDeviceCaptureCapability* system_echo_canceller_device_ = nullptr;
  const std::vector<media::Point> kMicPositions = {{8, 8, 8}, {4, 4, 4}};

  // TODO(grunell): Store these as separate constants and compare against those
  // in tests, instead of indexing the vector.
  const std::vector<blink::WebString> kEchoCancellationTypeValues = {
      blink::WebString::FromASCII("browser"),
      blink::WebString::FromASCII("aec3"),
      blink::WebString::FromASCII("system")};

 private:
  // Required for tests involving a MediaStreamAudioSource.
  base::MessageLoop message_loop_;
  MockPeerConnectionDependencyFactory pc_factory_;
};

// The Unconstrained test checks the default selection criteria.
TEST_P(MediaStreamConstraintsUtilAudioTest, Unconstrained) {
  auto result = SelectSettings();

  // All settings should have default values.
  EXPECT_TRUE(result.HasValue());
  CheckAllDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
                   result);
}

// This test checks all possible ways to set boolean constraints (except
// echo cancellation constraints, which are not mapped 1:1 to output audio
// processing properties).
TEST_P(MediaStreamConstraintsUtilAudioTest, SingleBoolConstraint) {
  // TODO(crbug.com/736309): Use braced initialization instead of push_back once
  // clang has been fixed.
  AudioSettingsBoolMembers kMainSettings;
  kMainSettings.push_back(&AudioCaptureSettings::hotword_enabled);
  kMainSettings.push_back(&AudioCaptureSettings::disable_local_echo);
  kMainSettings.push_back(&AudioCaptureSettings::render_to_associated_sink);

  const std::vector<
      blink::BooleanConstraint blink::WebMediaTrackConstraintSet::*>
      kMainBoolConstraints = {
          &blink::WebMediaTrackConstraintSet::hotword_enabled,
          &blink::WebMediaTrackConstraintSet::disable_local_echo,
          &blink::WebMediaTrackConstraintSet::render_to_associated_sink};

  ASSERT_EQ(kMainSettings.size(), kMainBoolConstraints.size());
  for (auto set_function : kBoolSetFunctions) {
    for (auto accessor : kFactoryAccessors) {
      // Ideal advanced is ignored by the SelectSettings algorithm.
      // Using array elements instead of pointer values due to the comparison
      // failing on some build configurations.
      if (set_function == kBoolSetFunctions[1] &&
          accessor == kFactoryAccessors[1]) {
        continue;
      }
      for (size_t i = 0; i < kMainSettings.size(); ++i) {
        for (bool value : kBoolValues) {
          ResetFactory();
          (((constraint_factory_.*accessor)().*kMainBoolConstraints[i]).*
           set_function)(value);
          auto result = SelectSettings();
          EXPECT_TRUE(result.HasValue());
          EXPECT_EQ(value, (result.*kMainSettings[i])());
          CheckAllDefaults({kMainSettings[i]}, AudioPropertiesBoolMembers(),
                           result);
        }
      }
    }
  }

  const AudioPropertiesBoolMembers kAudioProcessingProperties = {
      &AudioProcessingProperties::goog_audio_mirroring,
      &AudioProcessingProperties::goog_auto_gain_control,
      &AudioProcessingProperties::goog_experimental_echo_cancellation,
      &AudioProcessingProperties::goog_typing_noise_detection,
      &AudioProcessingProperties::goog_noise_suppression,
      &AudioProcessingProperties::goog_experimental_noise_suppression,
      &AudioProcessingProperties::goog_highpass_filter,
      &AudioProcessingProperties::goog_experimental_auto_gain_control};

  const std::vector<
      blink::BooleanConstraint blink::WebMediaTrackConstraintSet::*>
      kAudioProcessingConstraints = {
          &blink::WebMediaTrackConstraintSet::goog_audio_mirroring,
          &blink::WebMediaTrackConstraintSet::goog_auto_gain_control,
          &blink::WebMediaTrackConstraintSet::
              goog_experimental_echo_cancellation,
          &blink::WebMediaTrackConstraintSet::goog_typing_noise_detection,
          &blink::WebMediaTrackConstraintSet::goog_noise_suppression,
          &blink::WebMediaTrackConstraintSet::
              goog_experimental_noise_suppression,
          &blink::WebMediaTrackConstraintSet::goog_highpass_filter,
          &blink::WebMediaTrackConstraintSet::
              goog_experimental_auto_gain_control,
      };

  ASSERT_EQ(kAudioProcessingProperties.size(),
            kAudioProcessingConstraints.size());
  for (auto set_function : kBoolSetFunctions) {
    for (auto accessor : kFactoryAccessors) {
      // Ideal advanced is ignored by the SelectSettings algorithm.
      // Using array elements instead of pointer values due to the comparison
      // failing on some build configurations.
      if (set_function == kBoolSetFunctions[1] &&
          accessor == kFactoryAccessors[1]) {
        continue;
      }
      for (size_t i = 0; i < kAudioProcessingProperties.size(); ++i) {
        for (bool value : kBoolValues) {
          ResetFactory();
          (((constraint_factory_.*accessor)().*kAudioProcessingConstraints[i]).*
           set_function)(value);
          auto result = SelectSettings();
          EXPECT_TRUE(result.HasValue());
          EXPECT_EQ(value, result.audio_processing_properties().*
                               kAudioProcessingProperties[i]);
          CheckAllDefaults(AudioSettingsBoolMembers(),
                           {kAudioProcessingProperties[i]}, result);
        }
      }
    }
  }
}

// DeviceID tests.
TEST_P(MediaStreamConstraintsUtilAudioTest, ExactArbitraryDeviceID) {
  const std::string kArbitraryDeviceID = "arbitrary";
  constraint_factory_.basic().device_id.SetExact(
      blink::WebString::FromASCII(kArbitraryDeviceID));
  auto result = SelectSettings();
  // kArbitraryDeviceID is invalid for device capture, but it is considered
  // valid for content capture. For content capture, validation of device
  // capture is performed by the getUserMedia() implementation.
  if (IsDeviceCapture()) {
    EXPECT_FALSE(result.HasValue());
    EXPECT_EQ(std::string(constraint_factory_.basic().device_id.GetName()),
              std::string(result.failed_constraint_name()));
  } else {
    EXPECT_TRUE(result.HasValue());
    EXPECT_EQ(kArbitraryDeviceID, result.device_id());
    CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
                      result);
    CheckEchoCancellationTypeDefault(result);
  }
}

// DeviceID tests check various ways to deal with the device_id constraint.
TEST_P(MediaStreamConstraintsUtilAudioTest, IdealArbitraryDeviceID) {
  const std::string kArbitraryDeviceID = "arbitrary";
  constraint_factory_.basic().device_id.SetIdeal(
      blink::WebString::FromASCII(kArbitraryDeviceID));
  auto result = SelectSettings();
  EXPECT_TRUE(result.HasValue());
  // kArbitraryDeviceID is invalid for device capture, but it is considered
  // valid for content capture. For content capture, validation of device
  // capture is performed by the getUserMedia() implementation.
  if (IsDeviceCapture())
    CheckDeviceDefaults(result);
  else
    EXPECT_EQ(kArbitraryDeviceID, result.device_id());
  CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
                    result);
  CheckEchoCancellationTypeDefault(result);
}

TEST_P(MediaStreamConstraintsUtilAudioTest, ExactValidDeviceID) {
  for (const auto& device : capabilities_) {
    constraint_factory_.basic().device_id.SetExact(
        blink::WebString::FromASCII(device.DeviceID()));
    auto result = SelectSettings();
    EXPECT_TRUE(result.HasValue());
    CheckDevice(device, result);
    CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
                      result);
    EchoCancellationType expected_echo_cancellation_type =
        EchoCancellationType::kEchoCancellationDisabled;
    if (IsDeviceCapture()) {
      const bool has_system_echo_cancellation =
          device.Parameters().effects() &
          media::AudioParameters::ECHO_CANCELLER;
      expected_echo_cancellation_type =
          has_system_echo_cancellation
              ? EchoCancellationType::kEchoCancellationSystem
              : EchoCancellationType::kEchoCancellationAec2;
    }
    EXPECT_EQ(expected_echo_cancellation_type,
              result.audio_processing_properties().echo_cancellation_type);
  }
}

TEST_P(MediaStreamConstraintsUtilAudioTest, ExactGroupID) {
  for (const auto& device : capabilities_) {
    constraint_factory_.basic().group_id.SetExact(
        blink::WebString::FromASCII(device.GroupID()));
    auto result = SelectSettings();
    EXPECT_TRUE(result.HasValue());
    CheckDevice(device, result);
    CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
                      result);
    EchoCancellationType expected_echo_cancellation_type =
        EchoCancellationType::kEchoCancellationDisabled;
    if (IsDeviceCapture()) {
      const bool has_system_echo_cancellation =
          device.Parameters().effects() &
          media::AudioParameters::ECHO_CANCELLER;
      expected_echo_cancellation_type =
          has_system_echo_cancellation
              ? EchoCancellationType::kEchoCancellationSystem
              : EchoCancellationType::kEchoCancellationAec2;
    }
    EXPECT_EQ(expected_echo_cancellation_type,
              result.audio_processing_properties().echo_cancellation_type);
  }
}

// Tests the echoCancellation constraint with a device without system echo
// cancellation.
TEST_P(MediaStreamConstraintsUtilAudioTest, EchoCancellationWithWebRtc) {
  for (auto set_function : kBoolSetFunctions) {
    for (auto accessor : kFactoryAccessors) {
      // Ideal advanced is ignored by the SelectSettings algorithm.
      // Using array elements instead of pointer values due to the comparison
      // failing on some build configurations.
      if (set_function == kBoolSetFunctions[1] &&
          accessor == kFactoryAccessors[1]) {
        continue;
      }
      for (bool value : kBoolValues) {
        ResetFactory();
        ((constraint_factory_.*accessor)().echo_cancellation.*
         set_function)(value);
        auto result = SelectSettings();
        EXPECT_TRUE(result.HasValue());
        const AudioProcessingProperties& properties =
            result.audio_processing_properties();
        // With device capture, the echo_cancellation constraint
        // enables/disables all audio processing by default.
        // With content capture, the echo_cancellation constraint controls
        // only the echo_cancellation properties. The other audio processing
        // properties default to false.
        const EchoCancellationType expected_echo_cancellation_type =
            value ? EchoCancellationType::kEchoCancellationAec2
                  : EchoCancellationType::kEchoCancellationDisabled;
        EXPECT_EQ(expected_echo_cancellation_type,
                  properties.echo_cancellation_type);
        const bool enable_webrtc_audio_processing =
            IsDeviceCapture() ? value : false;
        EXPECT_EQ(enable_webrtc_audio_processing,
                  properties.goog_auto_gain_control);
        CheckGoogExperimentalEchoCancellationDefault(
            properties, enable_webrtc_audio_processing);
        EXPECT_EQ(enable_webrtc_audio_processing,
                  properties.goog_typing_noise_detection);
        EXPECT_EQ(enable_webrtc_audio_processing,
                  properties.goog_noise_suppression);
        EXPECT_EQ(enable_webrtc_audio_processing,
                  properties.goog_experimental_noise_suppression);
        EXPECT_EQ(enable_webrtc_audio_processing,
                  properties.goog_highpass_filter);
        EXPECT_EQ(enable_webrtc_audio_processing,
                  properties.goog_experimental_auto_gain_control);

        // The following are not audio processing.
        EXPECT_FALSE(properties.goog_audio_mirroring);
        EXPECT_FALSE(result.hotword_enabled());
        EXPECT_EQ(GetMediaStreamSource() != kMediaStreamSourceDesktop,
                  result.disable_local_echo());
        EXPECT_FALSE(result.render_to_associated_sink());
        if (IsDeviceCapture()) {
          CheckDevice(*default_device_, result);
        } else {
          EXPECT_TRUE(result.device_id().empty());
        }
      }
    }
  }
}

// Tests the echoCancellation constraint with a device with system echo
// cancellation.
TEST_P(MediaStreamConstraintsUtilAudioTest, EchoCancellationWithSystem) {
  // With content capture, there is no system echo cancellation, so
  // nothing to test.
  if (!IsDeviceCapture())
    return;

  for (auto set_function : kBoolSetFunctions) {
    for (auto accessor : kFactoryAccessors) {
      // Ideal advanced is ignored by the SelectSettings algorithm.
      // Using array elements instead of pointer values due to the comparison
      // failing on some build configurations.
      if (set_function == kBoolSetFunctions[1] &&
          accessor == kFactoryAccessors[1]) {
        continue;
      }
      for (bool value : kBoolValues) {
        ResetFactory();
        constraint_factory_.basic().device_id.SetExact(
            blink::WebString::FromASCII(
                system_echo_canceller_device_->DeviceID()));
        ((constraint_factory_.*accessor)().echo_cancellation.*
         set_function)(value);
        auto result = SelectSettings();
        EXPECT_TRUE(result.HasValue());
        const AudioProcessingProperties& properties =
            result.audio_processing_properties();
        // With system echo cancellation, the echo_cancellation constraint
        // enables/disables all audio processing by default, WebRTC echo
        // cancellation is always disabled, and system echo cancellation is
        // disabled if the echo_cancellation constraint is false.
        const EchoCancellationType expected_echo_cancellation_type =
            value ? EchoCancellationType::kEchoCancellationSystem
                  : EchoCancellationType::kEchoCancellationDisabled;
        EXPECT_EQ(expected_echo_cancellation_type,
                  properties.echo_cancellation_type);
        EXPECT_EQ(value, properties.goog_auto_gain_control);
        CheckGoogExperimentalEchoCancellationDefault(properties, value);
        EXPECT_EQ(value, properties.goog_typing_noise_detection);
        EXPECT_EQ(value, properties.goog_noise_suppression);
        EXPECT_EQ(value, properties.goog_experimental_noise_suppression);
        EXPECT_EQ(value, properties.goog_highpass_filter);
        EXPECT_EQ(value, properties.goog_experimental_auto_gain_control);

        // The following are not audio processing.
        EXPECT_FALSE(properties.goog_audio_mirroring);
        EXPECT_FALSE(result.hotword_enabled());
        EXPECT_EQ(GetMediaStreamSource() != kMediaStreamSourceDesktop,
                  result.disable_local_echo());
        EXPECT_FALSE(result.render_to_associated_sink());
        CheckDevice(*system_echo_canceller_device_, result);
      }
    }
  }
}

// Tests the googEchoCancellation constraint with a device without system echo
// cancellation.
TEST_P(MediaStreamConstraintsUtilAudioTest, GoogEchoCancellationWithWebRtc) {
  for (auto set_function : kBoolSetFunctions) {
    for (auto accessor : kFactoryAccessors) {
      // Ideal advanced is ignored by the SelectSettings algorithm.
      // Using array elements instead of pointers due to the comparison failing
      // on compilers.
      if (set_function == kBoolSetFunctions[1] &&
          accessor == kFactoryAccessors[1]) {
        continue;
      }
      for (bool value : kBoolValues) {
        ResetFactory();
        ((constraint_factory_.*accessor)().goog_echo_cancellation.*
         set_function)(value);
        auto result = SelectSettings();
        EXPECT_TRUE(result.HasValue());
        const AudioProcessingProperties& properties =
            result.audio_processing_properties();
        // The goog_echo_cancellation constraint controls only the
        // echo_cancellation properties. The other audio processing properties
        // use the default values.
        const EchoCancellationType expected_echo_cancellation_type =
            value ? EchoCancellationType::kEchoCancellationAec2
                  : EchoCancellationType::kEchoCancellationDisabled;
        EXPECT_EQ(expected_echo_cancellation_type,
                  properties.echo_cancellation_type);
        CheckBoolDefaults(AudioSettingsBoolMembers(),
                          AudioPropertiesBoolMembers(), result);
        if (IsDeviceCapture()) {
          CheckDevice(*default_device_, result);
        } else {
          EXPECT_TRUE(result.device_id().empty());
        }
      }
    }
  }
}

// Tests the googEchoCancellation constraint with a device with system echo
// cancellation.
TEST_P(MediaStreamConstraintsUtilAudioTest, GoogEchoCancellationWithSystem) {
  // With content capture, there is no system echo cancellation, so
  // nothing to test.
  if (!IsDeviceCapture())
    return;

  for (auto set_function : kBoolSetFunctions) {
    for (auto accessor : kFactoryAccessors) {
      // Ideal advanced is ignored by the SelectSettings algorithm.
      // Using array elements instead of pointer values due to the comparison
      // failing on some build configurations.
      if (set_function == kBoolSetFunctions[1] &&
          accessor == kFactoryAccessors[1]) {
        continue;
      }
      for (bool value : kBoolValues) {
        ResetFactory();
        constraint_factory_.basic().device_id.SetExact(
            blink::WebString::FromASCII(
                system_echo_canceller_device_->DeviceID()));
        ((constraint_factory_.*accessor)().goog_echo_cancellation.*
         set_function)(value);
        auto result = SelectSettings();
        EXPECT_TRUE(result.HasValue());
        const AudioProcessingProperties& properties =
            result.audio_processing_properties();
        // With system echo cancellation, WebRTC echo cancellation is always
        // disabled, and system echo cancellation is disabled if
        // goog_echo_cancellation is false.
        const EchoCancellationType expected_echo_cancellation_type =
            value ? EchoCancellationType::kEchoCancellationSystem
                  : EchoCancellationType::kEchoCancellationDisabled;
        EXPECT_EQ(expected_echo_cancellation_type,
                  properties.echo_cancellation_type);
        CheckBoolDefaults(AudioSettingsBoolMembers(),
                          AudioPropertiesBoolMembers(), result);
        CheckDevice(*system_echo_canceller_device_, result);
      }
    }
  }
}

// Tests the echoCancellationType constraint without constraining to a device
// with system echo cancellation. Tested as basic exact constraints.
TEST_P(MediaStreamConstraintsUtilAudioTest, EchoCancellationTypeExact) {
  for (blink::WebString value : kEchoCancellationTypeValues) {
    ResetFactory();
    constraint_factory_.basic().echo_cancellation.SetExact(true);
    constraint_factory_.basic().echo_cancellation_type.SetExact(value);
    auto result = SelectSettings();
    // If content capture and EC type "system", we expect failure.
    if (!IsDeviceCapture() && value == kEchoCancellationTypeValues[2]) {
      EXPECT_FALSE(result.HasValue());
      EXPECT_EQ(result.failed_constraint_name(),
                constraint_factory_.basic().echo_cancellation_type.GetName());
      continue;
    }
    ASSERT_TRUE(result.HasValue());

    CheckAudioProcessingPropertiesForExactEchoCancellationType(value, result);
  }
}

// Like the test above, but changes the device with system echo cancellation
// support to only support experimental system echo cancellation. It should
// still be picked if requested.
TEST_P(MediaStreamConstraintsUtilAudioTest,
       EchoCancellationTypeExact_Experimental) {
  if (!IsDeviceCapture())
    return;

  // Replace the device with one that only supports experimental system echo
  // cancellation.
  MakeSystemEchoCancellerDeviceExperimental();

  for (blink::WebString value : kEchoCancellationTypeValues) {
    ResetFactory();
    constraint_factory_.basic().echo_cancellation.SetExact(true);
    constraint_factory_.basic().echo_cancellation_type.SetExact(value);
    auto result = SelectSettings();
    ASSERT_TRUE(result.HasValue());
    CheckAudioProcessingPropertiesForExactEchoCancellationType(value, result);
  }
}

// Tests the echoCancellationType constraint without constraining to a device
// with system echo cancellation. Tested as basic ideal constraints.
TEST_P(MediaStreamConstraintsUtilAudioTest, EchoCancellationTypeIdeal) {
  // With content capture, there is no system echo cancellation, so
  // nothing to test.
  if (!IsDeviceCapture())
    return;

  constraint_factory_.basic().echo_cancellation.SetExact(true);
  constraint_factory_.basic().echo_cancellation_type.SetIdeal(
      kEchoCancellationTypeValues[2]);
  auto result = SelectSettings();
  ASSERT_TRUE(result.HasValue());
  CheckAudioProcessingPropertiesForIdealEchoCancellationType(result);
}

// Like the test above, but only having a device with experimental system echo
// cancellation available.
TEST_P(MediaStreamConstraintsUtilAudioTest,
       EchoCancellationTypeIdeal_Experimental) {
  // With content capture, there is no system echo cancellation, so
  // nothing to test.
  if (!IsDeviceCapture())
    return;

  // Replace the device with one that only supports experimental system echo
  // cancellation.
  MakeSystemEchoCancellerDeviceExperimental();

  constraint_factory_.basic().echo_cancellation.SetExact(true);
  constraint_factory_.basic().echo_cancellation_type.SetIdeal(
      kEchoCancellationTypeValues[2]);
  auto result = SelectSettings();
  ASSERT_TRUE(result.HasValue());
  CheckAudioProcessingPropertiesForIdealEchoCancellationType(result);
}

// Tests the echoCancellationType constraint with constraining to a device with
// experimental system echo cancellation.
TEST_P(MediaStreamConstraintsUtilAudioTest,
       EchoCancellationTypeWithExpSystemDeviceConstraint) {
  // With content capture, there is no system echo cancellation, so
  // nothing to test.
  if (!IsDeviceCapture())
    return;

  MakeSystemEchoCancellerDeviceExperimental();

  // Include leaving the echoCancellationType constraint unset in the tests.
  // It should then behave as before the constraint was introduced.
  auto echo_cancellation_types_and_unset = kEchoCancellationTypeValues;
  echo_cancellation_types_and_unset.push_back(blink::WebString());

  for (auto set_function : kStringSetFunctions) {
    for (auto accessor : kFactoryAccessors) {
      // Ideal advanced is ignored by the SelectSettings algorithm.
      // Using array elements instead of pointer values due to the comparison
      // failing on some build configurations.
      if (set_function == kStringSetFunctions[1] &&
          accessor == kFactoryAccessors[1]) {
        continue;
      }
      for (blink::WebString ec_type_value : echo_cancellation_types_and_unset) {
        for (bool ec_value : kBoolValues) {
          ResetFactory();
          constraint_factory_.basic().device_id.SetExact(
              blink::WebString::FromASCII(
                  system_echo_canceller_device_->DeviceID()));
          constraint_factory_.basic().echo_cancellation.SetExact(ec_value);
          if (!ec_type_value.IsNull())
            ((constraint_factory_.*accessor)().echo_cancellation_type.*
             set_function)(ec_type_value);

          // We should get a result if echo cancellation is enabled or if it's
          // disabled and we set the type as an advanced or ideal constraint, or
          // we've left the constraint unset.
          auto result = SelectSettings();
          const bool advanced_constraint = accessor == kFactoryAccessors[1];
          const bool ideal_constraint = set_function == kStringSetFunctions[1];
          const bool should_have_result = ec_value || advanced_constraint ||
                                          ideal_constraint ||
                                          ec_type_value.IsNull();
          EXPECT_EQ(should_have_result, result.HasValue());
          if (!should_have_result)
            continue;

          const AudioProcessingProperties& properties =
              result.audio_processing_properties();

          // With experimental system echo cancellation (echo canceller type
          // "system"), the echo_cancellation constraint enables/disables all
          // audio processing by default, WebRTC echo cancellation is always
          // disabled, and experimental system echo cancellation is disabled
          // if the echo_cancellation constraint is false.
          if (ec_value) {
            const EchoCancellationType expected_echo_cancellation_type =
                ec_type_value == blink::WebString()
                    ? EchoCancellationType::kEchoCancellationAec2
                    : GetEchoCancellationTypeFromConstraintString(
                          ec_type_value);
            EXPECT_EQ(expected_echo_cancellation_type,
                      properties.echo_cancellation_type);
          } else {
            EXPECT_EQ(EchoCancellationType::kEchoCancellationDisabled,
                      properties.echo_cancellation_type);
          }
          EXPECT_EQ(ec_value, properties.goog_auto_gain_control);
          CheckGoogExperimentalEchoCancellationDefault(properties, ec_value);
          EXPECT_EQ(ec_value, properties.goog_typing_noise_detection);
          EXPECT_EQ(ec_value, properties.goog_noise_suppression);
          EXPECT_EQ(ec_value, properties.goog_experimental_noise_suppression);
          EXPECT_EQ(ec_value, properties.goog_highpass_filter);
          EXPECT_EQ(ec_value, properties.goog_experimental_auto_gain_control);

          // The following are not audio processing.
          EXPECT_FALSE(properties.goog_audio_mirroring);
          EXPECT_FALSE(result.hotword_enabled());
          EXPECT_EQ(GetMediaStreamSource() != kMediaStreamSourceDesktop,
                    result.disable_local_echo());
          EXPECT_FALSE(result.render_to_associated_sink());
          CheckDevice(*system_echo_canceller_device_, result);
        }
      }
    }
  }
}

// Tests the echoCancellationType constraint with constraining to a device
// without experimental system echo cancellation, which should fail.
TEST_P(MediaStreamConstraintsUtilAudioTest,
       EchoCancellationTypeWithWebRtcDeviceConstraint) {
  if (!IsDeviceCapture())
    return;

  constraint_factory_.basic().device_id.SetExact(
      blink::WebString::FromASCII(default_device_->DeviceID()));
  constraint_factory_.basic().echo_cancellation.SetExact(true);
  constraint_factory_.basic().echo_cancellation_type.SetExact(
      kEchoCancellationTypeValues[2]);

  auto result = SelectSettings();
  EXPECT_FALSE(result.HasValue());
  EXPECT_EQ(result.failed_constraint_name(),
            constraint_factory_.basic().device_id.GetName());
}

// Tests the echoCancellationType constraint when also the AEC3 has been
// selected via the extension API. That selection ends up in
// AecDumpMessageFilter and MediaStreamConstraintsUtil checks there if set and
// to what. It can be unset, true or false. The constraint has precedence over
// the extension API selection. Tested as basic exact constraints.
TEST_P(MediaStreamConstraintsUtilAudioTest,
       EchoCancellationTypeAndAec3Selection) {
  // First test AEC3 selection when no echo cancellation type constraint has
  // been set.
  scoped_refptr<AecDumpMessageFilterForTest> admf =
      new AecDumpMessageFilterForTest();
  admf->set_override_aec3(true);

  ResetFactory();
  constraint_factory_.basic().echo_cancellation.SetExact(true);
  auto result = SelectSettings();
  ASSERT_TRUE(result.HasValue());

  CheckAudioProcessingPropertiesForExactEchoCancellationType(
      kEchoCancellationTypeValues[1],  // AEC3
      result);

  // Set the echo cancellation type constraint to browser and expect that as
  // result.
  ResetFactory();
  constraint_factory_.basic().echo_cancellation.SetExact(true);
  constraint_factory_.basic().echo_cancellation_type.SetExact(
      kEchoCancellationTypeValues[0]);
  result = SelectSettings();
  ASSERT_TRUE(result.HasValue());

  CheckAudioProcessingPropertiesForExactEchoCancellationType(
      kEchoCancellationTypeValues[0],  // Browser
      result);

  // Set the AEC3 selection to false and echo cancellation type constraint to
  // AEC3 and expect AEC3 as result.
  admf->set_override_aec3(false);

  ResetFactory();
  constraint_factory_.basic().echo_cancellation.SetExact(true);
  constraint_factory_.basic().echo_cancellation_type.SetExact(
      kEchoCancellationTypeValues[1]);
  result = SelectSettings();
  ASSERT_TRUE(result.HasValue());

  CheckAudioProcessingPropertiesForExactEchoCancellationType(
      kEchoCancellationTypeValues[1],  // AEC3
      result);
}

// Test that having differing mandatory values for echoCancellation and
// googEchoCancellation fails.
TEST_P(MediaStreamConstraintsUtilAudioTest, ContradictoryEchoCancellation) {
  for (bool value : kBoolValues) {
    constraint_factory_.basic().echo_cancellation.SetExact(value);
    constraint_factory_.basic().goog_echo_cancellation.SetExact(!value);
    auto result = SelectSettings();
    EXPECT_FALSE(result.HasValue());
    EXPECT_EQ(result.failed_constraint_name(),
              constraint_factory_.basic().echo_cancellation.GetName());
  }
}

// Tests that individual boolean audio-processing constraints override the
// default value set by the echoCancellation constraint.
TEST_P(MediaStreamConstraintsUtilAudioTest,
       EchoCancellationAndSingleBoolConstraint) {
  const AudioPropertiesBoolMembers kAudioProcessingProperties = {
      &AudioProcessingProperties::goog_audio_mirroring,
      &AudioProcessingProperties::goog_auto_gain_control,
      &AudioProcessingProperties::goog_experimental_echo_cancellation,
      &AudioProcessingProperties::goog_typing_noise_detection,
      &AudioProcessingProperties::goog_noise_suppression,
      &AudioProcessingProperties::goog_experimental_noise_suppression,
      &AudioProcessingProperties::goog_highpass_filter,
      &AudioProcessingProperties::goog_experimental_auto_gain_control};

  const std::vector<
      blink::BooleanConstraint blink::WebMediaTrackConstraintSet::*>
      kAudioProcessingConstraints = {
          &blink::WebMediaTrackConstraintSet::goog_audio_mirroring,
          &blink::WebMediaTrackConstraintSet::goog_auto_gain_control,
          &blink::WebMediaTrackConstraintSet::
              goog_experimental_echo_cancellation,
          &blink::WebMediaTrackConstraintSet::goog_typing_noise_detection,
          &blink::WebMediaTrackConstraintSet::goog_noise_suppression,
          &blink::WebMediaTrackConstraintSet::
              goog_experimental_noise_suppression,
          &blink::WebMediaTrackConstraintSet::goog_highpass_filter,
          &blink::WebMediaTrackConstraintSet::
              goog_experimental_auto_gain_control,
      };

  ASSERT_EQ(kAudioProcessingProperties.size(),
            kAudioProcessingConstraints.size());
  for (auto set_function : kBoolSetFunctions) {
    for (auto accessor : kFactoryAccessors) {
      // Ideal advanced is ignored by the SelectSettings algorithm.
      // Using array elements instead of pointer values due to the comparison
      // failing on some build configurations.
      if (set_function == kBoolSetFunctions[1] &&
          accessor == kFactoryAccessors[1]) {
        continue;
      }
      for (size_t i = 0; i < kAudioProcessingProperties.size(); ++i) {
        ResetFactory();
        ((constraint_factory_.*accessor)().echo_cancellation.*
         set_function)(false);
        (((constraint_factory_.*accessor)().*kAudioProcessingConstraints[i]).*
         set_function)(true);
        auto result = SelectSettings();
        EXPECT_TRUE(result.HasValue());
        EXPECT_EQ(EchoCancellationType::kEchoCancellationDisabled,
                  result.audio_processing_properties().echo_cancellation_type);
        EXPECT_TRUE(result.audio_processing_properties().*
                    kAudioProcessingProperties[i]);
        for (size_t j = 0; j < kAudioProcessingProperties.size(); ++j) {
          if (i == j)
            continue;
          EXPECT_FALSE(result.audio_processing_properties().*
                       kAudioProcessingProperties[j]);
        }
      }
    }
  }
}

// Test advanced constraints sets that can be satisfied.
TEST_P(MediaStreamConstraintsUtilAudioTest, AdvancedCompatibleConstraints) {
  constraint_factory_.AddAdvanced().render_to_associated_sink.SetExact(true);
  constraint_factory_.AddAdvanced().goog_audio_mirroring.SetExact(true);
  auto result = SelectSettings();
  EXPECT_TRUE(result.HasValue());
  CheckDeviceDefaults(result);
  // TODO(crbug.com/736309): Fold this local when clang is fixed.
  auto render_to_associated_sink =
      &AudioCaptureSettings::render_to_associated_sink;
  CheckBoolDefaults({render_to_associated_sink},
                    {&AudioProcessingProperties::goog_audio_mirroring}, result);
  CheckEchoCancellationTypeDefault(result);
  EXPECT_TRUE(result.render_to_associated_sink());
  EXPECT_TRUE(result.audio_processing_properties().goog_audio_mirroring);
}

// Test that an advanced constraint set that contradicts a previous constraint
// set is ignored, but that further constraint sets that can be satisfied are
// applied.
TEST_P(MediaStreamConstraintsUtilAudioTest,
       AdvancedConflictingMiddleConstraints) {
  constraint_factory_.AddAdvanced().goog_highpass_filter.SetExact(true);
  auto& advanced2 = constraint_factory_.AddAdvanced();
  advanced2.goog_highpass_filter.SetExact(false);
  advanced2.hotword_enabled.SetExact(true);
  constraint_factory_.AddAdvanced().goog_audio_mirroring.SetExact(true);
  auto result = SelectSettings();
  EXPECT_TRUE(result.HasValue());
  CheckDeviceDefaults(result);
  EXPECT_FALSE(result.hotword_enabled());
  // TODO(crbug.com/736309): Fold this local when clang is fixed.
  auto hotword_enabled = &AudioCaptureSettings::hotword_enabled;
  CheckBoolDefaults({hotword_enabled},
                    {&AudioProcessingProperties::goog_audio_mirroring,
                     &AudioProcessingProperties::goog_highpass_filter},
                    result);
  CheckEchoCancellationTypeDefault(result);
  EXPECT_FALSE(result.hotword_enabled());
  EXPECT_TRUE(result.audio_processing_properties().goog_audio_mirroring);
  EXPECT_TRUE(result.audio_processing_properties().goog_highpass_filter);
}

// Test that an advanced constraint set that contradicts a previous constraint
// set with a boolean constraint is ignored.
TEST_P(MediaStreamConstraintsUtilAudioTest, AdvancedConflictingLastConstraint) {
  constraint_factory_.AddAdvanced().goog_highpass_filter.SetExact(true);
  constraint_factory_.AddAdvanced().hotword_enabled.SetExact(true);
  constraint_factory_.AddAdvanced().goog_audio_mirroring.SetExact(true);
  constraint_factory_.AddAdvanced().hotword_enabled.SetExact(false);
  auto result = SelectSettings();
  EXPECT_TRUE(result.HasValue());
  CheckDeviceDefaults(result);
  // TODO(crbug.com/736309): Fold this local when clang is fixed.
  auto hotword_enabled = &AudioCaptureSettings::hotword_enabled;
  CheckBoolDefaults({hotword_enabled},
                    {&AudioProcessingProperties::goog_audio_mirroring,
                     &AudioProcessingProperties::goog_highpass_filter},
                    result);
  CheckEchoCancellationTypeDefault(result);
  // The fourth advanced set is ignored because it contradicts the second set.
  EXPECT_TRUE(result.hotword_enabled());
  EXPECT_TRUE(result.audio_processing_properties().goog_audio_mirroring);
  EXPECT_TRUE(result.audio_processing_properties().goog_highpass_filter);
}

// NoDevices tests verify that the case with no devices is handled correctly.
TEST_P(MediaStreamConstraintsUtilAudioTest, NoDevicesNoConstraints) {
  // This test makes sense only for device capture.
  if (!IsDeviceCapture())
    return;

  AudioDeviceCaptureCapabilities capabilities;
  auto result = SelectSettingsAudioCapture(
      capabilities, constraint_factory_.CreateWebMediaConstraints(), false);
  EXPECT_FALSE(result.HasValue());
  EXPECT_TRUE(std::string(result.failed_constraint_name()).empty());
}

TEST_P(MediaStreamConstraintsUtilAudioTest, NoDevicesWithConstraints) {
  // This test makes sense only for device capture.
  if (!IsDeviceCapture())
    return;

  AudioDeviceCaptureCapabilities capabilities;
  constraint_factory_.basic().sample_size.SetExact(16);
  auto result = SelectSettingsAudioCapture(
      capabilities, constraint_factory_.CreateWebMediaConstraints(), false);
  EXPECT_FALSE(result.HasValue());
  EXPECT_TRUE(std::string(result.failed_constraint_name()).empty());
}

// Test functionality to support applyConstraints() for tracks attached to
// sources that have no audio processing.
TEST_P(MediaStreamConstraintsUtilAudioTest, SourceWithNoAudioProcessing) {
  for (bool enable_properties : {true, false}) {
    std::unique_ptr<LocalMediaStreamAudioSource> source =
        GetLocalMediaStreamAudioSource(
            enable_properties /* enable_system_echo_canceller */,
            enable_properties /* hotword_enabled */,
            enable_properties /* disable_local_echo */,
            enable_properties /* render_to_associated_sink */);

    // These constraints are false in |source|.
    const std::vector<
        blink::BooleanConstraint blink::WebMediaTrackConstraintSet::*>
        kConstraints = {
            &blink::WebMediaTrackConstraintSet::echo_cancellation,
            &blink::WebMediaTrackConstraintSet::hotword_enabled,
            &blink::WebMediaTrackConstraintSet::disable_local_echo,
            &blink::WebMediaTrackConstraintSet::render_to_associated_sink,
        };

    for (size_t i = 0; i < kConstraints.size(); ++i) {
      constraint_factory_.Reset();
      (constraint_factory_.basic().*kConstraints[i])
          .SetExact(enable_properties);
      auto result = SelectSettingsAudioCapture(
          source.get(), constraint_factory_.CreateWebMediaConstraints());
      EXPECT_TRUE(result.HasValue());

      constraint_factory_.Reset();
      (constraint_factory_.basic().*kConstraints[i])
          .SetExact(!enable_properties);
      result = SelectSettingsAudioCapture(
          source.get(), constraint_factory_.CreateWebMediaConstraints());
      EXPECT_FALSE(result.HasValue());

      // Setting just ideal values should always succeed.
      constraint_factory_.Reset();
      (constraint_factory_.basic().*kConstraints[i]).SetIdeal(true);
      result = SelectSettingsAudioCapture(
          source.get(), constraint_factory_.CreateWebMediaConstraints());
      EXPECT_TRUE(result.HasValue());

      constraint_factory_.Reset();
      (constraint_factory_.basic().*kConstraints[i]).SetIdeal(false);
      result = SelectSettingsAudioCapture(
          source.get(), constraint_factory_.CreateWebMediaConstraints());
      EXPECT_TRUE(result.HasValue());
    }
  }
}

// Test functionality to support applyConstraints() for echo cancellation type
// for tracks attached to sources that have no audio processing.
TEST_P(MediaStreamConstraintsUtilAudioTest,
       EchoCancellationTypeWithSourceWithNoAudioProcessing) {
  for (blink::WebString value : kEchoCancellationTypeValues) {
    std::unique_ptr<LocalMediaStreamAudioSource> source =
        GetLocalMediaStreamAudioSource(false /* enable_system_echo_canceller */,
                                       false /* hotword_enabled */,
                                       false /* disable_local_echo */,
                                       false /* render_to_associated_sink */);

    // No echo cancellation is available so we expect failure.
    constraint_factory_.Reset();
    constraint_factory_.basic().echo_cancellation_type.SetExact(value);
    auto result = SelectSettingsAudioCapture(
        source.get(), constraint_factory_.CreateWebMediaConstraints());
    EXPECT_FALSE(result.HasValue());

    // Setting just ideal values should always succeed.
    constraint_factory_.Reset();
    constraint_factory_.basic().echo_cancellation_type.SetIdeal(value);
    result = SelectSettingsAudioCapture(
        source.get(), constraint_factory_.CreateWebMediaConstraints());
    EXPECT_TRUE(result.HasValue());
  }
}

// Test functionality to support applyConstraints() for tracks attached to
// sources that have audio processing.
TEST_P(MediaStreamConstraintsUtilAudioTest, SourceWithAudioProcessing) {
  // Processed audio sources are supported only for device capture.
  if (!IsDeviceCapture())
    return;

  for (bool use_defaults : {true, false}) {
    AudioProcessingProperties properties;
    if (!use_defaults) {
      properties.echo_cancellation_type =
          EchoCancellationType::kEchoCancellationDisabled;
      properties.goog_audio_mirroring = !properties.goog_audio_mirroring;
      properties.goog_auto_gain_control = !properties.goog_auto_gain_control;
      properties.goog_experimental_echo_cancellation =
          !properties.goog_experimental_echo_cancellation;
      properties.goog_typing_noise_detection =
          !properties.goog_typing_noise_detection;
      properties.goog_noise_suppression = !properties.goog_noise_suppression;
      properties.goog_experimental_noise_suppression =
          !properties.goog_experimental_noise_suppression;
      properties.goog_highpass_filter = !properties.goog_highpass_filter;
      properties.goog_experimental_auto_gain_control =
          !properties.goog_experimental_auto_gain_control;
    }

    std::unique_ptr<ProcessedLocalAudioSource> source =
        GetProcessedLocalAudioSource(
            properties, use_defaults /* hotword_enabled */,
            use_defaults /* disable_local_echo */,
            use_defaults /* render_to_associated_sink */);
    const std::vector<
        blink::BooleanConstraint blink::WebMediaTrackConstraintSet::*>
        kAudioProcessingConstraints = {
            &blink::WebMediaTrackConstraintSet::goog_audio_mirroring,
            &blink::WebMediaTrackConstraintSet::goog_auto_gain_control,
            &blink::WebMediaTrackConstraintSet::
                goog_experimental_echo_cancellation,
            &blink::WebMediaTrackConstraintSet::goog_typing_noise_detection,
            &blink::WebMediaTrackConstraintSet::goog_noise_suppression,
            &blink::WebMediaTrackConstraintSet::
                goog_experimental_noise_suppression,
            &blink::WebMediaTrackConstraintSet::goog_highpass_filter,
            &blink::WebMediaTrackConstraintSet::
                goog_experimental_auto_gain_control,
        };
    const AudioPropertiesBoolMembers kAudioProcessingProperties = {
        &AudioProcessingProperties::goog_audio_mirroring,
        &AudioProcessingProperties::goog_auto_gain_control,
        &AudioProcessingProperties::goog_experimental_echo_cancellation,
        &AudioProcessingProperties::goog_typing_noise_detection,
        &AudioProcessingProperties::goog_noise_suppression,
        &AudioProcessingProperties::goog_experimental_noise_suppression,
        &AudioProcessingProperties::goog_highpass_filter,
        &AudioProcessingProperties::goog_experimental_auto_gain_control};

    ASSERT_EQ(kAudioProcessingConstraints.size(),
              kAudioProcessingProperties.size());

    for (size_t i = 0; i < kAudioProcessingConstraints.size(); ++i) {
      constraint_factory_.Reset();
      (constraint_factory_.basic().*kAudioProcessingConstraints[i])
          .SetExact(properties.*kAudioProcessingProperties[i]);
      auto result = SelectSettingsAudioCapture(
          source.get(), constraint_factory_.CreateWebMediaConstraints());
      EXPECT_TRUE(result.HasValue());

      constraint_factory_.Reset();
      (constraint_factory_.basic().*kAudioProcessingConstraints[i])
          .SetExact(!(properties.*kAudioProcessingProperties[i]));
      result = SelectSettingsAudioCapture(
          source.get(), constraint_factory_.CreateWebMediaConstraints());
      EXPECT_FALSE(result.HasValue());

      // Setting just ideal values should always succeed.
      constraint_factory_.Reset();
      (constraint_factory_.basic().*kAudioProcessingConstraints[i])
          .SetIdeal(true);
      result = SelectSettingsAudioCapture(
          source.get(), constraint_factory_.CreateWebMediaConstraints());
      EXPECT_TRUE(result.HasValue());

      constraint_factory_.Reset();
      (constraint_factory_.basic().*kAudioProcessingConstraints[i])
          .SetIdeal(false);
      result = SelectSettingsAudioCapture(
          source.get(), constraint_factory_.CreateWebMediaConstraints());
      EXPECT_TRUE(result.HasValue());
    }

    // Test same as above but for echo cancellation.
    constraint_factory_.Reset();
    constraint_factory_.basic().echo_cancellation.SetExact(
        properties.echo_cancellation_type ==
        EchoCancellationType::kEchoCancellationAec2);
    auto result = SelectSettingsAudioCapture(
        source.get(), constraint_factory_.CreateWebMediaConstraints());
    EXPECT_TRUE(result.HasValue());

    constraint_factory_.Reset();
    constraint_factory_.basic().echo_cancellation.SetExact(
        properties.echo_cancellation_type !=
        EchoCancellationType::kEchoCancellationAec2);
    result = SelectSettingsAudioCapture(
        source.get(), constraint_factory_.CreateWebMediaConstraints());
    EXPECT_FALSE(result.HasValue());

    constraint_factory_.Reset();
    constraint_factory_.basic().echo_cancellation.SetIdeal(true);
    result = SelectSettingsAudioCapture(
        source.get(), constraint_factory_.CreateWebMediaConstraints());
    EXPECT_TRUE(result.HasValue());

    constraint_factory_.Reset();
    constraint_factory_.basic().echo_cancellation.SetIdeal(false);
    result = SelectSettingsAudioCapture(
        source.get(), constraint_factory_.CreateWebMediaConstraints());
    EXPECT_TRUE(result.HasValue());

    // These constraints are false in |source|.
    const std::vector<
        blink::BooleanConstraint blink::WebMediaTrackConstraintSet::*>
        kAudioBrowserConstraints = {
            &blink::WebMediaTrackConstraintSet::hotword_enabled,
            &blink::WebMediaTrackConstraintSet::disable_local_echo,
            &blink::WebMediaTrackConstraintSet::render_to_associated_sink,
        };
    for (size_t i = 0; i < kAudioBrowserConstraints.size(); ++i) {
      constraint_factory_.Reset();
      (constraint_factory_.basic().*kAudioBrowserConstraints[i])
          .SetExact(use_defaults);
      auto result = SelectSettingsAudioCapture(
          source.get(), constraint_factory_.CreateWebMediaConstraints());
      EXPECT_TRUE(result.HasValue());

      constraint_factory_.Reset();
      (constraint_factory_.basic().*kAudioBrowserConstraints[i])
          .SetExact(!use_defaults);
      result = SelectSettingsAudioCapture(
          source.get(), constraint_factory_.CreateWebMediaConstraints());
      EXPECT_FALSE(result.HasValue());

      constraint_factory_.Reset();
      (constraint_factory_.basic().*kAudioBrowserConstraints[i]).SetIdeal(true);
      result = SelectSettingsAudioCapture(
          source.get(), constraint_factory_.CreateWebMediaConstraints());
      EXPECT_TRUE(result.HasValue());

      constraint_factory_.Reset();
      (constraint_factory_.basic().*kAudioBrowserConstraints[i])
          .SetIdeal(false);
      result = SelectSettingsAudioCapture(
          source.get(), constraint_factory_.CreateWebMediaConstraints());
      EXPECT_TRUE(result.HasValue());
    }

    // Test same as above for echo cancellation.
    constraint_factory_.Reset();
    constraint_factory_.basic().echo_cancellation.SetExact(use_defaults);
    result = SelectSettingsAudioCapture(
        source.get(), constraint_factory_.CreateWebMediaConstraints());
    EXPECT_TRUE(result.HasValue());

    constraint_factory_.Reset();
    constraint_factory_.basic().echo_cancellation.SetExact(!use_defaults);
    result = SelectSettingsAudioCapture(
        source.get(), constraint_factory_.CreateWebMediaConstraints());
    EXPECT_FALSE(result.HasValue());

    constraint_factory_.Reset();
    constraint_factory_.basic().echo_cancellation.SetIdeal(true);
    result = SelectSettingsAudioCapture(
        source.get(), constraint_factory_.CreateWebMediaConstraints());
    EXPECT_TRUE(result.HasValue());

    constraint_factory_.Reset();
    constraint_factory_.basic().echo_cancellation.SetIdeal(false);
    result = SelectSettingsAudioCapture(
        source.get(), constraint_factory_.CreateWebMediaConstraints());
    EXPECT_TRUE(result.HasValue());
  }
}

// Test functionality to support applyConstraints() for echo cancellation type
// for tracks attached to sources that have audio processing.
TEST_P(MediaStreamConstraintsUtilAudioTest,
       EchoCancellationTypeWithSourceWithAudioProcessing) {
  // Processed audio sources are supported only for device capture.
  if (!IsDeviceCapture())
    return;

  const EchoCancellationType kEchoCancellationTypes[] = {
      EchoCancellationType::kEchoCancellationDisabled,
      EchoCancellationType::kEchoCancellationAec2,
      EchoCancellationType::kEchoCancellationAec3,
      EchoCancellationType::kEchoCancellationSystem};

  for (EchoCancellationType ec_type : kEchoCancellationTypes) {
    AudioProcessingProperties properties;
    properties.DisableDefaultProperties();
    properties.echo_cancellation_type = ec_type;

    std::unique_ptr<ProcessedLocalAudioSource> source =
        GetProcessedLocalAudioSource(
            properties, false /* hotword_enabled */,
            false /* disable_local_echo */,
            false /* render_to_associated_sink */,
            ec_type == EchoCancellationType::kEchoCancellationSystem
                ? media::AudioParameters::PlatformEffectsMask::
                      EXPERIMENTAL_ECHO_CANCELLER
                : media::AudioParameters::PlatformEffectsMask::NO_EFFECTS);

    for (blink::WebString value : kEchoCancellationTypeValues) {
      constraint_factory_.Reset();
      constraint_factory_.basic().echo_cancellation_type.SetExact(value);
      auto result = SelectSettingsAudioCapture(
          source.get(), constraint_factory_.CreateWebMediaConstraints());
      const bool should_have_result_value =
          ec_type == GetEchoCancellationTypeFromConstraintString(value);
      EXPECT_EQ(should_have_result_value, result.HasValue());

      // Setting just ideal values should always succeed.
      constraint_factory_.Reset();
      constraint_factory_.basic().echo_cancellation_type.SetIdeal(value);
      result = SelectSettingsAudioCapture(
          source.get(), constraint_factory_.CreateWebMediaConstraints());
      EXPECT_TRUE(result.HasValue());
    }
  }
}

TEST_P(MediaStreamConstraintsUtilAudioTest, UsedAndUnusedSources) {
  // The distinction of used and unused sources is relevant only for device
  // capture.
  if (!IsDeviceCapture())
    return;

  AudioProcessingProperties properties;
  std::unique_ptr<ProcessedLocalAudioSource> processed_source =
      GetProcessedLocalAudioSource(properties, false /* hotword_enabled */,
                                   false /* disable_local_echo */,
                                   false /* render_to_associated_sink */);

  const std::string kUnusedDeviceID = "unused_device";
  const std::string kGroupID = "fake_group";
  AudioDeviceCaptureCapabilities capabilities;
  capabilities.emplace_back(processed_source.get());
  capabilities.emplace_back(kUnusedDeviceID, kGroupID,
                            media::AudioParameters::UnavailableDeviceParams());

  {
    constraint_factory_.Reset();
    constraint_factory_.basic().echo_cancellation.SetExact(false);

    auto result = SelectSettingsAudioCapture(
        capabilities, constraint_factory_.CreateWebMediaConstraints(),
        false /* should_disable_hardware_noise_suppression */);
    EXPECT_TRUE(result.HasValue());
    EXPECT_EQ(result.device_id(), kUnusedDeviceID);
    EXPECT_EQ(result.audio_processing_properties().echo_cancellation_type,
              EchoCancellationType::kEchoCancellationDisabled);
  }

  {
    constraint_factory_.Reset();
    constraint_factory_.basic().echo_cancellation.SetExact(true);
    auto result = SelectSettingsAudioCapture(
        capabilities, constraint_factory_.CreateWebMediaConstraints(),
        false /* should_disable_hardware_noise_suppression */);
    EXPECT_TRUE(result.HasValue());
    EXPECT_EQ(result.device_id(), processed_source->device().id);
    EXPECT_EQ(result.audio_processing_properties().echo_cancellation_type,
              EchoCancellationType::kEchoCancellationAec2);
  }
}

INSTANTIATE_TEST_CASE_P(,
                        MediaStreamConstraintsUtilAudioTest,
                        testing::Values("",
                                        kMediaStreamSourceTab,
                                        kMediaStreamSourceSystem,
                                        kMediaStreamSourceDesktop));

}  // namespace content
