/*
 * Copyright (C) 2016, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <cerrno>
#include <memory>
#include <tuple>
#include <utility>

#include "gmock/gmock.h"
#include "gtest/gtest.h"

#include "wifilogd/tests/mock_command_processor.h"
#include "wifilogd/tests/mock_os.h"

#include "wifilogd/main_loop.h"
#include "wifilogd/protocol.h"

namespace android {
namespace wifilogd {
namespace {

using ::testing::_;
using ::testing::AnyNumber;
using ::testing::Ge;
using ::testing::Return;
using ::testing::StrictMock;

constexpr int kControlSocketFd = 100;
constexpr char kFakeSocketName[] = "fake-socket";

class MainLoopTest : public ::testing::Test {
 public:
  MainLoopTest()
      : os_(new StrictMock<MockOs>()),
        command_processor_(new StrictMock<MockCommandProcessor>()) {
    EXPECT_CALL(*os_, GetControlSocket(kFakeSocketName))
        .WillOnce(Return(std::tuple<size_t, Os::Errno>{kControlSocketFd, 0}));
    main_loop_ = std::make_unique<MainLoop>(
        kFakeSocketName, std::unique_ptr<Os>{os_},
        std::unique_ptr<CommandProcessor>{command_processor_});
  }

 protected:
  std::unique_ptr<MainLoop> main_loop_;
  // We use raw pointers to access the mocks, since ownership passes
  // to |main_loop_|.
  StrictMock<MockOs>* os_;
  StrictMock<MockCommandProcessor>* command_processor_;
};

}  // namespace

TEST_F(MainLoopTest, RunOnceReadsFromCorrectSocket) {
  EXPECT_CALL(*os_, ReceiveDatagram(kControlSocketFd, _, _));
  EXPECT_CALL(*command_processor_, ProcessCommand(_, _, _)).Times(AnyNumber());
  main_loop_->RunOnce();
}

TEST_F(MainLoopTest, RunOnceReadsWithSufficientlyLargeBuffer) {
  EXPECT_CALL(*os_, ReceiveDatagram(_, _, Ge(protocol::kMaxMessageSize)));
  EXPECT_CALL(*command_processor_, ProcessCommand(_, _, _)).Times(AnyNumber());
  main_loop_->RunOnce();
}

TEST_F(MainLoopTest, RunOncePassesSmallestValidMessageToCommandProcessor) {
  EXPECT_CALL(*os_, ReceiveDatagram(_, _, _))
      .WillOnce(
          Return(std::tuple<size_t, Os::Errno>{sizeof(protocol::Command), 0}));
  EXPECT_CALL(*command_processor_,
              ProcessCommand(_, sizeof(protocol::Command), _));
  main_loop_->RunOnce();
}

TEST_F(MainLoopTest, RunOncePassesLargestValidMessageToCommandProcessor) {
  EXPECT_CALL(*os_, ReceiveDatagram(_, _, _))
      .WillOnce(
          Return(std::tuple<size_t, Os::Errno>{protocol::kMaxMessageSize, 0}));
  EXPECT_CALL(*command_processor_,
              ProcessCommand(_, protocol::kMaxMessageSize, _));
  main_loop_->RunOnce();
}

TEST_F(MainLoopTest, RunOncePassesRuntMessageToCommandProcessor) {
  EXPECT_CALL(*os_, ReceiveDatagram(_, _, _))
      .WillOnce(Return(std::tuple<size_t, Os::Errno>{0, 0}));
  EXPECT_CALL(*command_processor_, ProcessCommand(_, 0, _));
  main_loop_->RunOnce();
}

TEST_F(MainLoopTest, RunOnceLimitsMaxSizeReportedToCommandProcessor) {
  EXPECT_CALL(*os_, ReceiveDatagram(_, _, _))
      .WillOnce(Return(
          std::tuple<size_t, Os::Errno>{protocol::kMaxMessageSize + 1, 0}));
  EXPECT_CALL(*command_processor_,
              ProcessCommand(_, protocol::kMaxMessageSize, _));
  main_loop_->RunOnce();
}

TEST_F(MainLoopTest, RunOnceDoesNotPassDataToCommandProcessorOnError) {
  EXPECT_CALL(*os_, ReceiveDatagram(_, _, protocol::kMaxMessageSize))
      .WillOnce(Return(std::tuple<size_t, Os::Errno>{0, EINTR}));
  EXPECT_CALL(*command_processor_, ProcessCommand(_, _, _)).Times(0);
  main_loop_->RunOnce();
}

// Per
// github.com/google/googletest/blob/master/googletest/docs/AdvancedGuide.md#death-tests,
// death tests should be specially named.
using MainLoopDeathTest = MainLoopTest;

TEST_F(MainLoopDeathTest, CtorFailureToFetchControlSocketCausesDeath) {
  auto os = std::make_unique<StrictMock<MockOs>>();
  auto command_processor = std::make_unique<StrictMock<MockCommandProcessor>>();
  ON_CALL(*os, GetControlSocket(kFakeSocketName))
      .WillByDefault(Return(std::tuple<size_t, Os::Errno>{-1, ERANGE}));
  EXPECT_DEATH(
      MainLoop(kFakeSocketName, std::move(os), std::move(command_processor)),
      "Failed to get control socket");
}

}  // namespace wifilogd
}  // namespace android
