// Copyright (c) 2020 Vasyl Teliman
//
// 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 "source/fuzz/transformation_invert_comparison_operator.h"

#include "source/fuzz/instruction_descriptor.h"
#include "test/fuzz/fuzz_test_util.h"

namespace spvtools {
namespace fuzz {
namespace {

TEST(TransformationInvertComparisonOperatorTest, BasicTest) {
  std::string shader = R"(
               OpCapability Shader
          %1 = OpExtInstImport "GLSL.std.450"
               OpMemoryModel Logical GLSL450
               OpEntryPoint Fragment %4 "main"
               OpExecutionMode %4 OriginUpperLeft
               OpSource ESSL 310
          %2 = OpTypeVoid
          %3 = OpTypeFunction %2
          %6 = OpTypeInt 32 1
          %7 = OpTypeInt 32 0
          %8 = OpTypeBool
          %9 = OpConstant %6 3
         %10 = OpConstant %6 4
         %11 = OpConstant %7 3
         %12 = OpConstant %7 4
          %4 = OpFunction %2 None %3
          %5 = OpLabel
         %13 = OpSLessThan %8 %9 %10
         %14 = OpSLessThanEqual %8 %9 %10
         %15 = OpSGreaterThan %8 %9 %10
         %16 = OpSGreaterThanEqual %8 %9 %10
         %17 = OpULessThan %8 %11 %12
         %18 = OpULessThanEqual %8 %11 %12
         %19 = OpUGreaterThan %8 %11 %12
         %20 = OpUGreaterThanEqual %8 %11 %12
         %21 = OpIEqual %8 %9 %10
         %22 = OpINotEqual %8 %9 %10
               OpReturn
               OpFunctionEnd
  )";

  const auto env = SPV_ENV_UNIVERSAL_1_3;
  const auto consumer = nullptr;
  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  ASSERT_TRUE(IsValid(env, context.get()));

  FactManager fact_manager;
  spvtools::ValidatorOptions validator_options;
  TransformationContext transformation_context(&fact_manager,
                                               validator_options);

  // Operator id is not valid.
  ASSERT_FALSE(TransformationInvertComparisonOperator(23, 23).IsApplicable(
      context.get(), transformation_context));

  // Operator instruction is not supported.
  ASSERT_FALSE(TransformationInvertComparisonOperator(5, 23).IsApplicable(
      context.get(), transformation_context));

  // Fresh id is not fresh.
  ASSERT_FALSE(TransformationInvertComparisonOperator(13, 22).IsApplicable(
      context.get(), transformation_context));

  for (uint32_t fresh_id = 23, operator_id = 13; operator_id <= 22;
       ++fresh_id, ++operator_id) {
    TransformationInvertComparisonOperator transformation(operator_id,
                                                          fresh_id);
    ASSERT_TRUE(
        transformation.IsApplicable(context.get(), transformation_context));
    transformation.Apply(context.get(), &transformation_context);
  }

  std::string expected = R"(
               OpCapability Shader
          %1 = OpExtInstImport "GLSL.std.450"
               OpMemoryModel Logical GLSL450
               OpEntryPoint Fragment %4 "main"
               OpExecutionMode %4 OriginUpperLeft
               OpSource ESSL 310
          %2 = OpTypeVoid
          %3 = OpTypeFunction %2
          %6 = OpTypeInt 32 1
          %7 = OpTypeInt 32 0
          %8 = OpTypeBool
          %9 = OpConstant %6 3
         %10 = OpConstant %6 4
         %11 = OpConstant %7 3
         %12 = OpConstant %7 4
          %4 = OpFunction %2 None %3
          %5 = OpLabel
         %23 = OpSGreaterThanEqual %8 %9 %10
         %13 = OpLogicalNot %8 %23
         %24 = OpSGreaterThan %8 %9 %10
         %14 = OpLogicalNot %8 %24
         %25 = OpSLessThanEqual %8 %9 %10
         %15 = OpLogicalNot %8 %25
         %26 = OpSLessThan %8 %9 %10
         %16 = OpLogicalNot %8 %26
         %27 = OpUGreaterThanEqual %8 %11 %12
         %17 = OpLogicalNot %8 %27
         %28 = OpUGreaterThan %8 %11 %12
         %18 = OpLogicalNot %8 %28
         %29 = OpULessThanEqual %8 %11 %12
         %19 = OpLogicalNot %8 %29
         %30 = OpULessThan %8 %11 %12
         %20 = OpLogicalNot %8 %30
         %31 = OpINotEqual %8 %9 %10
         %21 = OpLogicalNot %8 %31
         %32 = OpIEqual %8 %9 %10
         %22 = OpLogicalNot %8 %32
               OpReturn
               OpFunctionEnd
  )";

  ASSERT_TRUE(IsEqual(env, expected, context.get()));
}

}  // namespace
}  // namespace fuzz
}  // namespace spvtools