// Copyright (c) 2019 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 "source/fuzz/transformation_add_constant_scalar.h"

#include "test/fuzz/fuzz_test_util.h"

namespace spvtools {
namespace fuzz {
namespace {

TEST(TransformationAddConstantScalarTest, IsApplicable) {
  std::string reference_shader = R"(
               OpCapability Shader
               OpCapability Int64
               OpCapability Float64
          %1 = OpExtInstImport "GLSL.std.450"
               OpMemoryModel Logical GLSL450
               OpEntryPoint Vertex %17 "main"

; Types

  ; 32-bit types
          %2 = OpTypeInt 32 0
          %3 = OpTypeInt 32 1
          %4 = OpTypeFloat 32

  ; 64-bit types
          %5 = OpTypeInt 64 0
          %6 = OpTypeInt 64 1
          %7 = OpTypeFloat 64

          %8 = OpTypePointer Private %2
          %9 = OpTypeVoid
         %10 = OpTypeFunction %9

; Constants

  ; 32-bit constants
         %11 = OpConstant %2 1
         %12 = OpConstant %3 2
         %13 = OpConstant %4 3

  ; 64-bit constants
         %14 = OpConstant %5 1
         %15 = OpConstant %6 2
         %16 = OpConstant %7 3

; main function
         %17 = OpFunction %9 None %10
         %18 = OpLabel
               OpReturn
               OpFunctionEnd
  )";

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

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

  // Tests |fresh_id| being non-fresh.
  auto transformation = TransformationAddConstantScalar(18, 2, {0}, false);
  ASSERT_FALSE(
      transformation.IsApplicable(context.get(), transformation_context));

  // Tests undefined |type_id|.
  transformation = TransformationAddConstantScalar(19, 20, {0}, false);
  ASSERT_FALSE(
      transformation.IsApplicable(context.get(), transformation_context));

  // Tests |type_id| not representing a type instruction.
  transformation = TransformationAddConstantScalar(19, 11, {0}, false);
  ASSERT_FALSE(
      transformation.IsApplicable(context.get(), transformation_context));

  // Tests |type_id| representing an OpTypePointer instruction.
  transformation = TransformationAddConstantScalar(19, 8, {0}, false);
  ASSERT_FALSE(
      transformation.IsApplicable(context.get(), transformation_context));

  // Tests |type_id| representing an OpTypeVoid instruction.
  transformation = TransformationAddConstantScalar(19, 9, {0}, false);
  ASSERT_FALSE(
      transformation.IsApplicable(context.get(), transformation_context));

  // Tests |words| having no words.
  transformation = TransformationAddConstantScalar(19, 2, {}, false);
  ASSERT_FALSE(
      transformation.IsApplicable(context.get(), transformation_context));

  // Tests |words| having 2 words for a 32-bit type.
  transformation = TransformationAddConstantScalar(19, 2, {0, 1}, false);
  ASSERT_FALSE(
      transformation.IsApplicable(context.get(), transformation_context));

  // Tests |words| having 3 words for a 64-bit type.
  transformation = TransformationAddConstantScalar(19, 5, {0, 1, 2}, false);
  ASSERT_FALSE(
      transformation.IsApplicable(context.get(), transformation_context));
}

TEST(TransformationAddConstantScalarTest, Apply) {
  std::string reference_shader = R"(
               OpCapability Shader
               OpCapability Int64
               OpCapability Float64
          %1 = OpExtInstImport "GLSL.std.450"
               OpMemoryModel Logical GLSL450
               OpEntryPoint Vertex %17 "main"

; Types

  ; 32-bit types
          %2 = OpTypeInt 32 0
          %3 = OpTypeInt 32 1
          %4 = OpTypeFloat 32

  ; 64-bit types
          %5 = OpTypeInt 64 0
          %6 = OpTypeInt 64 1
          %7 = OpTypeFloat 64

          %8 = OpTypePointer Private %2
          %9 = OpTypeVoid
         %10 = OpTypeFunction %9

; Constants

  ; 32-bit constants
         %11 = OpConstant %2 1
         %12 = OpConstant %3 2
         %13 = OpConstant %4 3

  ; 64-bit constants
         %14 = OpConstant %5 1
         %15 = OpConstant %6 2
         %16 = OpConstant %7 3

; main function
         %17 = OpFunction %9 None %10
         %18 = OpLabel
               OpReturn
               OpFunctionEnd
  )";

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

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

  // Adds 32-bit unsigned integer (1 logical operand with 1 word).
  auto transformation = TransformationAddConstantScalar(19, 2, {4}, false);
  transformation.Apply(context.get(), &transformation_context);
  auto* constant_instruction = context->get_def_use_mgr()->GetDef(19);
  EXPECT_EQ(constant_instruction->NumInOperands(), 1);
  EXPECT_EQ(constant_instruction->NumInOperandWords(), 1);
  ASSERT_TRUE(IsValid(env, context.get()));

  // Adds 32-bit signed integer (1 logical operand with 1 word).
  transformation = TransformationAddConstantScalar(20, 3, {5}, false);
  transformation.Apply(context.get(), &transformation_context);
  constant_instruction = context->get_def_use_mgr()->GetDef(20);
  EXPECT_EQ(constant_instruction->NumInOperands(), 1);
  EXPECT_EQ(constant_instruction->NumInOperandWords(), 1);
  ASSERT_TRUE(IsValid(env, context.get()));

  // Adds 32-bit float (1 logical operand with 1 word).
  transformation = TransformationAddConstantScalar(
      21, 4, {0b01000000110000000000000000000000}, false);
  transformation.Apply(context.get(), &transformation_context);
  constant_instruction = context->get_def_use_mgr()->GetDef(21);
  EXPECT_EQ(constant_instruction->NumInOperands(), 1);
  EXPECT_EQ(constant_instruction->NumInOperandWords(), 1);
  ASSERT_TRUE(IsValid(env, context.get()));

  // Adds 64-bit unsigned integer (1 logical operand with 2 words).
  transformation = TransformationAddConstantScalar(22, 5, {7, 0}, false);
  transformation.Apply(context.get(), &transformation_context);
  constant_instruction = context->get_def_use_mgr()->GetDef(22);
  EXPECT_EQ(constant_instruction->NumInOperands(), 1);
  EXPECT_EQ(constant_instruction->NumInOperandWords(), 2);
  ASSERT_TRUE(IsValid(env, context.get()));

  // Adds 64-bit signed integer (1 logical operand with 2 words).
  transformation = TransformationAddConstantScalar(23, 6, {8, 0}, false);
  transformation.Apply(context.get(), &transformation_context);
  constant_instruction = context->get_def_use_mgr()->GetDef(23);
  EXPECT_EQ(constant_instruction->NumInOperands(), 1);
  EXPECT_EQ(constant_instruction->NumInOperandWords(), 2);
  ASSERT_TRUE(IsValid(env, context.get()));

  // Adds 64-bit float (1 logical operand with 2 words).
  transformation = TransformationAddConstantScalar(
      24, 7, {0, 0b01000000001000100000000000000000}, false);
  transformation.Apply(context.get(), &transformation_context);
  constant_instruction = context->get_def_use_mgr()->GetDef(24);
  EXPECT_EQ(constant_instruction->NumInOperands(), 1);
  EXPECT_EQ(constant_instruction->NumInOperandWords(), 2);
  ASSERT_TRUE(IsValid(env, context.get()));

  // Adds irrelevant 32-bit unsigned integer (1 logical operand with 1 word).
  transformation = TransformationAddConstantScalar(25, 2, {10}, true);
  transformation.Apply(context.get(), &transformation_context);
  constant_instruction = context->get_def_use_mgr()->GetDef(25);
  EXPECT_EQ(constant_instruction->NumInOperands(), 1);
  EXPECT_EQ(constant_instruction->NumInOperandWords(), 1);
  ASSERT_TRUE(IsValid(env, context.get()));

  // Adds irrelevant 32-bit signed integer (1 logical operand with 1 word).
  transformation = TransformationAddConstantScalar(26, 3, {11}, true);
  transformation.Apply(context.get(), &transformation_context);
  constant_instruction = context->get_def_use_mgr()->GetDef(26);
  EXPECT_EQ(constant_instruction->NumInOperands(), 1);
  EXPECT_EQ(constant_instruction->NumInOperandWords(), 1);
  ASSERT_TRUE(IsValid(env, context.get()));

  // Adds irrelevant 32-bit float (1 logical operand with 1 word).
  transformation = TransformationAddConstantScalar(
      27, 4, {0b01000001010000000000000000000000}, true);
  transformation.Apply(context.get(), &transformation_context);
  constant_instruction = context->get_def_use_mgr()->GetDef(27);
  EXPECT_EQ(constant_instruction->NumInOperands(), 1);
  EXPECT_EQ(constant_instruction->NumInOperandWords(), 1);
  ASSERT_TRUE(IsValid(env, context.get()));

  // Adds irrelevant 64-bit unsigned integer (1 logical operand with 2 words).
  transformation = TransformationAddConstantScalar(28, 5, {13, 0}, true);
  transformation.Apply(context.get(), &transformation_context);
  constant_instruction = context->get_def_use_mgr()->GetDef(28);
  EXPECT_EQ(constant_instruction->NumInOperands(), 1);
  EXPECT_EQ(constant_instruction->NumInOperandWords(), 2);
  ASSERT_TRUE(IsValid(env, context.get()));

  // Adds irrelevant 64-bit signed integer (1 logical operand with 2 words).
  transformation = TransformationAddConstantScalar(29, 6, {14, 0}, true);
  transformation.Apply(context.get(), &transformation_context);
  constant_instruction = context->get_def_use_mgr()->GetDef(29);
  EXPECT_EQ(constant_instruction->NumInOperands(), 1);
  EXPECT_EQ(constant_instruction->NumInOperandWords(), 2);
  ASSERT_TRUE(IsValid(env, context.get()));

  // Adds irrelevant 64-bit float (1 logical operand with 2 words).
  transformation = TransformationAddConstantScalar(
      30, 7, {0, 0b01000000001011100000000000000000}, true);
  transformation.Apply(context.get(), &transformation_context);
  constant_instruction = context->get_def_use_mgr()->GetDef(30);
  EXPECT_EQ(constant_instruction->NumInOperands(), 1);
  EXPECT_EQ(constant_instruction->NumInOperandWords(), 2);
  ASSERT_TRUE(IsValid(env, context.get()));

  for (uint32_t result_id = 19; result_id <= 24; ++result_id) {
    ASSERT_FALSE(fact_manager.IdIsIrrelevant(result_id, context.get()));
  }

  for (uint32_t result_id = 25; result_id <= 30; ++result_id) {
    ASSERT_TRUE(fact_manager.IdIsIrrelevant(result_id, context.get()));
  }

  std::string variant_shader = R"(
               OpCapability Shader
               OpCapability Int64
               OpCapability Float64
          %1 = OpExtInstImport "GLSL.std.450"
               OpMemoryModel Logical GLSL450
               OpEntryPoint Vertex %17 "main"

; Types

  ; 32-bit types
          %2 = OpTypeInt 32 0
          %3 = OpTypeInt 32 1
          %4 = OpTypeFloat 32

  ; 64-bit types
          %5 = OpTypeInt 64 0
          %6 = OpTypeInt 64 1
          %7 = OpTypeFloat 64

          %8 = OpTypePointer Private %2
          %9 = OpTypeVoid
         %10 = OpTypeFunction %9

; Constants

  ; 32-bit constants
         %11 = OpConstant %2 1
         %12 = OpConstant %3 2
         %13 = OpConstant %4 3

  ; 64-bit constants
         %14 = OpConstant %5 1
         %15 = OpConstant %6 2
         %16 = OpConstant %7 3

  ; added constants
         %19 = OpConstant %2 4
         %20 = OpConstant %3 5
         %21 = OpConstant %4 6
         %22 = OpConstant %5 7
         %23 = OpConstant %6 8
         %24 = OpConstant %7 9
         %25 = OpConstant %2 10
         %26 = OpConstant %3 11
         %27 = OpConstant %4 12
         %28 = OpConstant %5 13
         %29 = OpConstant %6 14
         %30 = OpConstant %7 15

; main function
         %17 = OpFunction %9 None %10
         %18 = OpLabel
               OpReturn
               OpFunctionEnd
  )";

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

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