// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

package com.android.tools.r8.shaking.fields.shadow;

import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;

import com.android.tools.r8.NoVerticalClassMerging;
import com.android.tools.r8.shaking.fields.FieldsTestBase;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableSet;
import java.util.Collection;
import org.junit.Test;

@NoVerticalClassMerging
class Super {
  public int f1;
}

@NoVerticalClassMerging
class Sub extends Super {
  public int f1;
}

@NoVerticalClassMerging
class SubSub extends Sub {
  public int f1;
}

class Main {

  private static void printField(Class<?> clazz, String name) {
    try {
      clazz.getDeclaredField(name);
      System.out.println(clazz.getSimpleName() + "." + name + " found");
    } catch (NoSuchFieldException e) {
      System.out.println(clazz.getSimpleName() + "." + name + " not found");
    }
  }

  public static void main(String[] args) {
    printField(Super.class, "f1");
    printField(Sub.class, "f1");
    printField(SubSub.class, "f1");
  }
}

public class ShadowFieldsTest extends FieldsTestBase {

  @Override
  public Collection<Class<?>> getClasses() {
    return ImmutableSet.of(Super.class, Sub.class, SubSub.class, getMainClass());
  }

  @Override
  public Class<?> getMainClass() {
    return Main.class;
  }

  private void checkAllFields(CodeInspector inspector) {
    ClassSubject superSubject = inspector.clazz(Super.class);
    assertThat(superSubject, isPresent());
    assertThat(superSubject.field("int", "f1"), isPresent());
    ClassSubject subSubject = inspector.clazz(Sub.class);
    assertThat(subSubject, isPresent());
    assertThat(subSubject.field("int", "f1"), isPresent());
    ClassSubject subSubSubject = inspector.clazz(SubSub.class);
    assertThat(subSubSubject, isPresent());
    assertThat(subSubSubject.field("int", "f1"), isPresent());
  }

  @Override
  public String allFieldsOutput() {
    return StringUtils.lines("Super.f1 found", "Sub.f1 found", "SubSub.f1 found");
  }

  @Test
  public void testKeepAllFieldsWithWildcard() throws Throwable {
    runTest("-keep class **.SubSub { *; }", this::checkAllFields, allFieldsOutput());
  }

  @Test
  public void testKeepAllFieldsWithNameWildcard() throws Throwable {
    runTest("-keep class **.SubSub { int f*; }", this::checkAllFields, allFieldsOutput());
  }

  @Test
  public void testKeepAllFieldsWithFields() throws Throwable {
    runTest("-keep class **.SubSub { <fields>; }", this::checkAllFields, allFieldsOutput());
  }

  @Test
  public void testKeepF1() throws Throwable {
    runTest("-keep class **.SubSub { int f1; }", this::checkAllFields, allFieldsOutput());
  }

  @Test
  public void testKeepF1WithExtends() throws Throwable {
    runTest("-keep class * extends **.Sub { int f1; }", this::checkAllFields, allFieldsOutput());
  }
}
