// Copyright 2019 The Fuchsia 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 "src/media/audio/audio_core/test/audio_device_test.h"

#include <fuchsia/media/cpp/fidl.h>
#include <lib/gtest/real_loop_fixture.h>

#include <cmath>
#include <cstring>
#include <utility>

#include "gtest/gtest.h"
#include "lib/component/cpp/environment_services_helper.h"
#include "src/lib/fxl/logging.h"
#include "src/media/audio/audio_core/test/audio_tests_shared.h"

namespace media::audio::test {

//
// AudioDeviceTest static variables
//
std::shared_ptr<const ::component::Services>
    AudioDeviceTest::environment_services_;
fuchsia::virtualaudio::ControlSyncPtr AudioDeviceTest::control_sync_;

uint16_t AudioDeviceTest::initial_input_device_count_ = kInvalidDeviceCount;
uint16_t AudioDeviceTest::initial_output_device_count_ = kInvalidDeviceCount;
uint64_t AudioDeviceTest::initial_input_default_ = ZX_KOID_INVALID;
uint64_t AudioDeviceTest::initial_output_default_ = ZX_KOID_INVALID;
float AudioDeviceTest::initial_input_gain_db_ = NAN;
float AudioDeviceTest::initial_output_gain_db_ = NAN;
uint32_t AudioDeviceTest::initial_input_gain_flags_ = 0;
uint32_t AudioDeviceTest::initial_output_gain_flags_ = 0;

//
// AudioDeviceTest implementation
//

// static
void AudioDeviceTest::SetEnvironmentServices(
    std::shared_ptr<const ::component::Services> environment_services) {
  environment_services_ = environment_services;
}

// static
void AudioDeviceTest::SetControl(
    fuchsia::virtualaudio::ControlSyncPtr control_sync) {
  AudioDeviceTest::control_sync_ = std::move(control_sync);
}

// static
void AudioDeviceTest::ResetVirtualDevices() {
  DisableVirtualDevices();
  zx_status_t status = control_sync_->Enable();
  ASSERT_EQ(status, ZX_OK);
}

// static
void AudioDeviceTest::DisableVirtualDevices() {
  zx_status_t status = control_sync_->Disable();
  ASSERT_EQ(status, ZX_OK);

  uint32_t num_inputs = -1, num_outputs = -1, num_tries = 0;
  do {
    status = control_sync_->GetNumDevices(&num_inputs, &num_outputs);
    ASSERT_EQ(status, ZX_OK);

    ++num_tries;
  } while ((num_inputs != 0 || num_outputs != 0) && num_tries < 100);
  ASSERT_EQ(num_inputs, 0u);
  ASSERT_EQ(num_outputs, 0u);
}

// static
void AudioDeviceTest::TearDownTestSuite() { DisableVirtualDevices(); }

void AudioDeviceTest::SetUp() {
  ::gtest::RealLoopFixture::SetUp();

  auto err_handler = [this](zx_status_t error) { error_occurred_ = true; };

  environment_services_->ConnectToService(audio_dev_enum_.NewRequest());
  audio_dev_enum_.set_error_handler(err_handler);
}

void AudioDeviceTest::TearDown() {
  EXPECT_FALSE(error_occurred_);
  EXPECT_TRUE(audio_dev_enum_.is_bound());

  ::gtest::RealLoopFixture::TearDown();
}

bool AudioDeviceTest::ExpectCallback() {
  received_callback_ = false;
  received_device_ = kInvalidDeviceInfo;
  received_removed_token_ = kInvalidDeviceToken;
  received_default_token_ = received_old_token_ = kInvalidDeviceToken;
  received_gain_token_ = kInvalidDeviceToken;
  received_gain_info_ = kInvalidGainInfo;

  bool timed_out = !RunLoopWithTimeoutOrUntil(
      [this]() { return error_occurred_ || received_callback_; },
      kDurationResponseExpected, kDurationGranularity);

  EXPECT_FALSE(error_occurred_);
  EXPECT_TRUE(audio_dev_enum_.is_bound());

  EXPECT_FALSE(timed_out);

  EXPECT_TRUE(received_callback_);

  bool return_val = !error_occurred_ && !timed_out;

  return return_val;
}

// TODO(mpuryear): Refactor tests to eliminate "wait for nothing bad to happen".
bool AudioDeviceTest::ExpectTimeout() {
  received_callback_ = false;
  received_device_ = kInvalidDeviceInfo;
  received_removed_token_ = kInvalidDeviceToken;
  received_default_token_ = received_old_token_ = kInvalidDeviceToken;
  received_gain_token_ = kInvalidDeviceToken;
  received_gain_info_ = kInvalidGainInfo;

  bool timed_out = !RunLoopWithTimeoutOrUntil(
      [this]() { return error_occurred_ || received_callback_; },
      kDurationTimeoutExpected);

  EXPECT_FALSE(error_occurred_);
  EXPECT_TRUE(audio_dev_enum_.is_bound());

  EXPECT_TRUE(timed_out);

  EXPECT_FALSE(received_callback_);
  if (received_callback_) {
    EXPECT_EQ(received_device_.token_id, kInvalidDeviceToken)
        << "Received Add event";
    EXPECT_EQ(received_removed_token_, kInvalidDeviceToken)
        << "Received Remove event";
    EXPECT_EQ(received_default_token_, kInvalidDeviceToken)
        << "Received Default event";
    EXPECT_EQ(received_old_token_, kInvalidDeviceToken)
        << "Received Default event";
    EXPECT_EQ(received_gain_token_, kInvalidDeviceToken)
        << "Received Gain event";
  }

  bool return_val = !error_occurred_ && !received_callback_;

  return return_val;
}

void AudioDeviceTest::SetOnDeviceAddedEvent() {
  audio_dev_enum_.events().OnDeviceAdded =
      [this](fuchsia::media::AudioDeviceInfo dev) {
        received_callback_ = true;
        received_device_ = std::move(dev);
      };
}

void AudioDeviceTest::SetOnDeviceRemovedEvent() {
  audio_dev_enum_.events().OnDeviceRemoved = [this](uint64_t token_id) {
    received_callback_ = true;
    received_removed_token_ = token_id;
  };
}

void AudioDeviceTest::SetOnDeviceGainChangedEvent() {
  audio_dev_enum_.events().OnDeviceGainChanged =
      [this](uint64_t dev_token, fuchsia::media::AudioGainInfo dev_gain_info) {
        received_callback_ = true;
        received_gain_token_ = dev_token;
        received_gain_info_ = dev_gain_info;
      };
}

void AudioDeviceTest::SetOnDefaultDeviceChangedEvent() {
  audio_dev_enum_.events().OnDefaultDeviceChanged =
      [this](uint64_t old_default_token, uint64_t new_default_token) {
        received_callback_ = true;
        received_default_token_ = new_default_token;
        received_old_token_ = old_default_token;
      };
}

uint32_t AudioDeviceTest::GainFlagsFromBools(bool can_mute, bool cur_mute,
                                             bool can_agc, bool cur_agc) {
  return ((can_mute && cur_mute) ? fuchsia::media::AudioGainInfoFlag_Mute
                                 : 0u) |
         (can_agc ? fuchsia::media::AudioGainInfoFlag_AgcSupported : 0u) |
         ((can_agc && cur_agc) ? fuchsia::media::AudioGainInfoFlag_AgcEnabled
                               : 0u);
}

uint32_t AudioDeviceTest::SetFlagsFromBools(bool set_gain, bool set_mute,
                                            bool set_agc) {
  return (set_gain ? fuchsia::media::SetAudioGainFlag_GainValid : 0u) |
         (set_mute ? fuchsia::media::SetAudioGainFlag_MuteValid : 0u) |
         (set_agc ? fuchsia::media::SetAudioGainFlag_AgcValid : 0u);
}

void AudioDeviceTest::RetrieveDefaultDevInfoUsingGetDevices(bool get_input) {
  audio_dev_enum_->GetDevices(
      [this,
       get_input](const std::vector<fuchsia::media::AudioDeviceInfo>& devices) {
        received_callback_ = true;

        for (auto& dev : devices) {
          if (dev.is_default && (dev.is_input == get_input)) {
            received_device_ = dev;
          }
        }
      });

  EXPECT_TRUE(ExpectCallback());
}

bool AudioDeviceTest::RetrieveGainInfoUsingGetDevices(uint64_t token) {
  audio_dev_enum_->GetDevices(
      [this,
       token](const std::vector<fuchsia::media::AudioDeviceInfo>& devices) {
        received_callback_ = true;

        for (auto& dev : devices) {
          if (dev.token_id == token) {
            received_gain_info_ = dev.gain_info;
          }
        }
      });

  return ExpectCallback();
}

void AudioDeviceTest::RetrieveGainInfoUsingGetDeviceGain(uint64_t token,
                                                         bool valid_token) {
  audio_dev_enum_->GetDeviceGain(
      token,
      [this](uint64_t dev_token, fuchsia::media::AudioGainInfo dev_gain_info) {
        received_callback_ = true;
        received_gain_token_ = dev_token;
        received_gain_info_ = dev_gain_info;
      });

  EXPECT_TRUE(ExpectCallback());
  EXPECT_EQ(received_gain_token_, (valid_token ? token : ZX_KOID_INVALID));
}

void AudioDeviceTest::RetrieveTokenUsingGetDefault(bool is_input) {
  auto get_default_handler = [this](uint64_t device_token) {
    received_callback_ = true;
    received_default_token_ = device_token;
  };

  if (is_input) {
    audio_dev_enum_->GetDefaultInputDevice(get_default_handler);
  } else {
    audio_dev_enum_->GetDefaultOutputDevice(get_default_handler);
  }

  EXPECT_TRUE(ExpectCallback());
}

void AudioDeviceTest::RetrievePreExistingDevices() {
  if (AudioDeviceTest::initial_input_device_count_ != kInvalidDeviceCount &&
      AudioDeviceTest::initial_output_device_count_ != kInvalidDeviceCount) {
    return;
  }

  // Wait until all completion (not disconnect) callbacks drain out, then go on.
  while (!error_occurred_) {
    if (ExpectTimeout()) {
      break;
    }
  }

  EXPECT_FALSE(error_occurred_);
  EXPECT_TRUE(audio_dev_enum_.is_bound());

  audio_dev_enum_->GetDevices(
      [this](const std::vector<fuchsia::media::AudioDeviceInfo>& devices) {
        received_callback_ = true;
        AudioDeviceTest::initial_input_device_count_ = 0;
        AudioDeviceTest::initial_output_device_count_ = 0;

        for (auto& dev : devices) {
          if (dev.is_input) {
            ++AudioDeviceTest::initial_input_device_count_;
            if (dev.is_default) {
              AudioDeviceTest::initial_input_default_ = dev.token_id;
              AudioDeviceTest::initial_input_gain_db_ = dev.gain_info.gain_db;
              AudioDeviceTest::initial_input_gain_flags_ = dev.gain_info.flags;
            }
          } else {
            ++AudioDeviceTest::initial_output_device_count_;
            if (dev.is_default) {
              AudioDeviceTest::initial_output_default_ = dev.token_id;
              AudioDeviceTest::initial_output_gain_db_ = dev.gain_info.gain_db;
              AudioDeviceTest::initial_output_gain_flags_ = dev.gain_info.flags;
            }
          }
        }
      });

  EXPECT_TRUE(ExpectCallback());
}

bool AudioDeviceTest::HasPreExistingDevices() {
  RetrievePreExistingDevices();

  EXPECT_NE(AudioDeviceTest::initial_input_device_count_, kInvalidDeviceCount);
  EXPECT_NE(AudioDeviceTest::initial_output_device_count_, kInvalidDeviceCount);

  return ((AudioDeviceTest::initial_input_device_count_ +
           AudioDeviceTest::initial_output_device_count_) > 0);
}

//
// AudioDeviceTest test cases
//

// Basic validation: we don't disconnect and callback is delivered.
// Later tests use RetrievePreExistingDevices which further validates
// GetDevices().
TEST_F(AudioDeviceTest, ReceivesGetDevicesCallback) {
  audio_dev_enum_->GetDevices(
      [this](const std::vector<fuchsia::media::AudioDeviceInfo>& devices) {
        received_callback_ = true;
      });

  EXPECT_TRUE(ExpectCallback());
}

TEST_F(AudioDeviceTest, GetDevicesHandlesLackOfDevices) {
  if (HasPreExistingDevices()) {
    FXL_DLOG(INFO) << "Test case requires an environment with no audio devices";
    return;
  }

  uint16_t num_devs = kInvalidDeviceCount;
  audio_dev_enum_->GetDevices(
      [this,
       &num_devs](const std::vector<fuchsia::media::AudioDeviceInfo>& devices) {
        received_callback_ = true;
        num_devs = devices.size();
      });

  EXPECT_TRUE(ExpectCallback());
  EXPECT_EQ(num_devs, 0u);
}

TEST_F(AudioDeviceTest, GetDefaultInputDeviceHandlesLackOfDevices) {
  if (HasPreExistingDevices()) {
    FXL_DLOG(INFO) << "Test case requires an environment with no audio devices";
    return;
  }
  RetrieveTokenUsingGetDefault(true);
  EXPECT_EQ(received_default_token_, ZX_KOID_INVALID);
}

TEST_F(AudioDeviceTest, GetDefaultOutputDeviceHandlesLackOfDevices) {
  if (HasPreExistingDevices()) {
    FXL_DLOG(INFO) << "Test case requires an environment with no audio devices";
    return;
  }
  RetrieveTokenUsingGetDefault(false);
  EXPECT_EQ(received_default_token_, ZX_KOID_INVALID);
}

// Given invalid token to GetDeviceGain, callback should be received with
// ZX_KOID_INVALID device; FIDL interface should not disconnect.
TEST_F(AudioDeviceTest, GetDeviceGainHandlesNullToken) {
  RetrieveGainInfoUsingGetDeviceGain(ZX_KOID_INVALID);
}

// Given invalid token to GetDeviceGain, callback should be received with
// ZX_KOID_INVALID device; FIDL interface should not disconnect.
TEST_F(AudioDeviceTest, GetDeviceGainHandlesBadToken) {
  RetrieveGainInfoUsingGetDeviceGain(kInvalidDeviceToken, false);
}

// Given null token to GetDeviceGain, FIDL interface should not disconnect.
TEST_F(AudioDeviceTest, SetDeviceGainHandlesNullToken) {
  audio_dev_enum_->SetDeviceGain(ZX_KOID_INVALID,
                                 {.gain_db = 0.0f, .flags = 0u},
                                 fuchsia::media::SetAudioGainFlag_GainValid);
  EXPECT_TRUE(ExpectTimeout());
}

// Given invalid token to SetDeviceGain, FIDL interface should not disconnect.
TEST_F(AudioDeviceTest, SetDeviceGainHandlesBadToken) {
  audio_dev_enum_->SetDeviceGain(kInvalidDeviceToken,
                                 {.gain_db = 0.0f, .flags = 0u},
                                 fuchsia::media::SetAudioGainFlag_GainValid);
  EXPECT_TRUE(ExpectTimeout());
}

// Given invalid token to GetDeviceGain, callback should be received with
// ZX_KOID_INVALID device; FIDL interface should not disconnect.
TEST_F(AudioDeviceTest, OnDeviceGainChangedIgnoresSetDeviceGainNullToken) {
  SetOnDeviceGainChangedEvent();

  audio_dev_enum_->SetDeviceGain(ZX_KOID_INVALID,
                                 {.gain_db = 0.0f, .flags = 0u},
                                 fuchsia::media::SetAudioGainFlag_GainValid);
  EXPECT_TRUE(ExpectTimeout());
}

TEST_F(AudioDeviceTest, OnDeviceGainChangedIgnoresSetDeviceGainBadToken) {
  SetOnDeviceGainChangedEvent();

  audio_dev_enum_->SetDeviceGain(kInvalidDeviceToken,
                                 {.gain_db = 0.0f, .flags = 0u},
                                 fuchsia::media::SetAudioGainFlag_GainValid);
  EXPECT_TRUE(ExpectTimeout());
}

}  // namespace media::audio::test
