// Copyright 2021 Google LLC
//
// 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 "utility.hpp"

#include <flashupdate/flash/mock.hpp>
#include <flashupdate/info.hpp>
#include <flashupdate/ops.hpp>
#include <flashupdate/validator/mock.hpp>

#include <format>
#include <fstream>
#include <sstream>
#include <string>

#include <gtest/gtest.h>

using ::testing::_;
using ::testing::Return;

namespace flashupdate
{

TEST_F(OperationTest, InvalidValidator)
{
    Args args;
    args.validatorHelper = nullptr;

    EXPECT_THROW(
        try { ops::read(args); } catch (const std::runtime_error& e) {
            EXPECT_STREQ(e.what(), "invalid Validator Helper");
            throw;
        },
        std::runtime_error);
}

TEST_F(OperationTest, ReadInvalidFlash)
{
    Args args;
    flash::Mock flashMockHelper;
    args.setFlashHelper(&flashMockHelper);

    EXPECT_CALL(flashMockHelper, getFlash(_, _)).WillOnce(Return(std::nullopt));

    EXPECT_THROW(
        try { ops::read(args); } catch (const std::runtime_error& e) {
            EXPECT_STREQ(e.what(), "failed to find Flash partitions");
            throw;
        },
        std::runtime_error);
}

TEST_F(OperationTest, ReadInvalidImage)
{
    Args args;
    std::string testBin = createTestBin();
    args.file.emplace(testBin);

    validator::Mock validatorMockHelper;
    args.setValidatorHelper(&validatorMockHelper);

    flash::Mock flashMockHelper;
    args.setFlashHelper(&flashMockHelper);

    EXPECT_CALL(validatorMockHelper, validateImage(_, _))
        .WillOnce(Return(false));
    EXPECT_CALL(flashMockHelper, getFlash(_, _))
        .WillOnce(Return(std::make_pair(createTestDev(), inputData.size())));

    EXPECT_THROW(
        try { ops::read(args); } catch (const std::runtime_error& e) {
            EXPECT_STREQ(
                e.what(),
                std::format("failed to validate the CR51 descriptor for {}",
                            testBin)
                    .c_str());
            throw;
        },
        std::runtime_error);
}

TEST_F(OperationTest, ReadPass)
{
    Args args;
    std::string testBin = createTestBin();
    args.file.emplace(testBin);

    validator::Mock validatorMockHelper;
    args.setValidatorHelper(&validatorMockHelper);

    flash::Mock flashMockHelper;
    args.setFlashHelper(&flashMockHelper);

    EXPECT_CALL(validatorMockHelper, validateImage(_, _))
        .WillOnce(Return(true));
    EXPECT_CALL(flashMockHelper, getFlash(_, _))
        .WillOnce(Return(std::make_pair(createTestDev(), inputData.size())));

    ops::read(args);
}

} // namespace flashupdate
