/*
 * Copyright 2019 The GraphicsFuzz Project Authors
 *
 * 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
 *
 *     https://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.
 */

package com.graphicsfuzz.reducer.reductionopportunities;

import com.graphicsfuzz.common.ast.TranslationUnit;
import com.graphicsfuzz.common.glslversion.ShadingLanguageVersion;
import com.graphicsfuzz.common.util.CompareAsts;
import com.graphicsfuzz.common.util.ParseHelper;
import com.graphicsfuzz.common.util.RandomWrapper;
import java.util.List;
import org.junit.Ignore;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

public class VariableDeclToExprReductionOpportunitiesTest {

  // TODO(480): Enable this test once the issue is fixed.
  @Ignore
  @Test
  public void testDoNotReplace() throws Exception {
    final String original = "void main() { int a = 1, b = 2; int c = 3; }";
    final TranslationUnit tu = ParseHelper.parse(original);
    final List<VariableDeclToExprReductionOpportunity> ops =
        VariableDeclToExprReductionOpportunities
        .findOpportunities(MakeShaderJobFromFragmentShader.make(tu), new ReducerContext(false,
            ShadingLanguageVersion.ESSL_100,
            new RandomWrapper(0), null, true));
    // There should be no opportunities as the preserve semantics is enabled.
    assertTrue(ops.isEmpty());
  }

  @Ignore
  @Test
  public void testMultipleDeclarations() throws Exception {
    final String program = "void main() {"
        + "int a = 1;"      // Initialized variable declaration.
        + "int b = foo();"  // Initialized variable declaration.
        + "int c;"          // Uninitialized variable declaration.
        + "}";
    final String expected = "void main() {"
        + " int a;"
        + " a = 1;"
        + " int b;"
        + " b = foo();"
        + " int c;"
        + "}";
    final TranslationUnit tu = ParseHelper.parse(program);
    List<VariableDeclToExprReductionOpportunity> ops = VariableDeclToExprReductionOpportunities
        .findOpportunities(MakeShaderJobFromFragmentShader.make(tu), new ReducerContext(true,
            ShadingLanguageVersion.ESSL_100,
            new RandomWrapper(0), null, true));
    // Only variable declarations a and b have the initializer.
    // Thus, we expect the reducer to find only 2 opportunities.
    assertEquals(2, ops.size());
    ops.forEach(VariableDeclToExprReductionOpportunity::applyReductionImpl);
    CompareAsts.assertEqualAsts(expected, tu);
  }

  @Ignore
  @Test
  public void testMultipleLineDeclarationsOneLine() throws Exception {
    final String program = "void main() {"
        + "int a;"
        + "int b = 1, c, d = foo(), e, f = bar(); " // This variable declaration has many
                                                    // declaration infos but we consider only
                                                    // the one that has initializer (b, d, and f).
        + "int g;"
        + "}";
    final String expected = "void main() {"
        + " int a;"
        + " int b, c, d, e, f;"
        + " b = 1;"
        + " d = foo();"
        + " f = bar();"
        + " int g;"
        + "}";
    final TranslationUnit tu = ParseHelper.parse(program);
    List<VariableDeclToExprReductionOpportunity> ops = VariableDeclToExprReductionOpportunities
        .findOpportunities(MakeShaderJobFromFragmentShader.make(tu), new ReducerContext(true,
            ShadingLanguageVersion.ESSL_100,
            new RandomWrapper(0), null, true));
    assertEquals(3, ops.size());
    ops.forEach(VariableDeclToExprReductionOpportunity::applyReductionImpl);
    CompareAsts.assertEqualAsts(expected, tu);
  }

  @Ignore
  @Test
  public void testAssignVariableIdentifier() throws Exception {
    final String program = "void main() {"
        + "int a = 1;"
        + "int b = a, c = b;"   // b depends on a and c depends on b.
        + "int d = c;"          // d depends on c.
        + "}";
    // As here we have the variable identifier as the initializer, we need to
    // make sure that new expressions generated by the reducer are added
    // in the correct order.
    final String expected = "void main() {"
        + " int a;"
        + " a = 1;"
        + " int b, c;"
        + " b = a;"
        + " c = b;"
        + " int d;"
        + " d = c;"
        + "}";
    final TranslationUnit tu = ParseHelper.parse(program);
    List<VariableDeclToExprReductionOpportunity> ops = VariableDeclToExprReductionOpportunities
        .findOpportunities(MakeShaderJobFromFragmentShader.make(tu), new ReducerContext(true,
            ShadingLanguageVersion.ESSL_100,
            new RandomWrapper(0), null, true));
    assertEquals(4, ops.size());
    ops.forEach(VariableDeclToExprReductionOpportunity::applyReductionImpl);
    CompareAsts.assertEqualAsts(expected, tu);
  }

}

@@ -1827,32 +1827,694 @@
 sEmpty());%0A  %7D%0A%0A
+  @Ignore%0A  @Test%0A  public void testDoNotReplaceConst() throws Exception %7B%0A    final String original = %22void main() %7B const int a = 1;%7D%22;%0A    final TranslationUnit tu = ParseHelper.parse(original);%0A    final List%3CVariableDeclToExprReductionOpportunity%3E ops =%0A        VariableDeclToExprReductionOpportunities%0A            .findOpportunities(MakeShaderJobFromFragmentShader.make(tu), new ReducerContext(true,%0A                ShadingLanguageVersion.ESSL_100,%0A                new RandomWrapper(0), null, true));%0A    // There should be no opportunities as it is invalid to declare constant variable%0A    // without an initial value.%0A    assertTrue(ops.isEmpty());%0A  %7D%0A%0A
   @Ignore%0A  @Tes

Add test for const variable declaration (#538)