blob: e823bc1070f0a7b32ee839803b26a7e5889162d4 [file] [log] [blame]
/*
* Copyright (C) 2023 The Android Open Source Project
*
* 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.
*/
package com.android.tools.metalava.model.testsuite
import com.android.tools.metalava.testing.java
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
/**
* Provides a set of tests that are geared towards helping to bootstrap a new model.
*
* The basic idea is that each test (in numerical order) requires a small increment over the
* previous test so that a developer would start by running the first test, making it pass,
* submitting the changes and then moving on to the next test.
*/
@RunWith(Parameterized::class)
class BootstrapSourceModelProviderTest(parameters: TestParameters) : BaseModelTest(parameters) {
@Test
fun `010 - check source model provider exists`() {
// Do nothing.
}
@Test
fun `020 - check empty file`() {
runSourceCodebaseTest(java("")) { codebase -> assertNotNull(codebase) }
}
@Test
fun `030 - check simplest class`() {
runSourceCodebaseTest(
java(
"""
package test.pkg;
class Test {
}
"""
),
) { codebase ->
val classItem = codebase.assertClass("test.pkg.Test")
assertEquals("test.pkg.Test", classItem.qualifiedName())
}
}
@Test
fun `040 - check package exists`() {
runSourceCodebaseTest(
java(
"""
package test.pkg;
class Test {
}
"""
),
) { codebase ->
val packageItem = codebase.assertPackage("test.pkg")
assertEquals("test.pkg", packageItem.qualifiedName())
assertEquals(1, packageItem.topLevelClasses().count(), message = "")
}
}
@Test
fun `050 - check field exists`() {
runSourceCodebaseTest(
java(
"""
package test.pkg;
class Test {
int field;
}
"""
),
) { codebase ->
val testClass = codebase.assertClass("test.pkg.Test")
val fieldItem = testClass.assertField("field")
assertEquals("field", fieldItem.name())
assertEquals(testClass, fieldItem.containingClass())
}
}
@Test
fun `060 - check method exists`() {
runSourceCodebaseTest(
java(
"""
package test.pkg;
class Test {
void method();
}
"""
),
) { codebase ->
val testClass = codebase.assertClass("test.pkg.Test")
val methodItem = testClass.assertMethod("method", "")
assertEquals("method", methodItem.name())
}
}
@Test
fun `070 - check constructor exists`() {
runSourceCodebaseTest(
java(
"""
package test.pkg;
class Test {
public Test() {}
}
"""
),
) { codebase ->
val testClass = codebase.assertClass("test.pkg.Test")
val constructorItem = testClass.assertConstructor("")
assertEquals("Test", constructorItem.name())
}
}
@Test
fun `080 - check inner class`() {
runSourceCodebaseTest(
java(
"""
package test.pkg;
class Test {
class InnerTestClass {}
}
"""
),
) { codebase ->
val classItem = codebase.assertClass("test.pkg.Test")
val innerClassItem = codebase.assertClass("test.pkg.Test.InnerTestClass")
assertEquals("test.pkg.Test.InnerTestClass", innerClassItem.qualifiedName())
assertEquals("Test.InnerTestClass", innerClassItem.fullName())
assertEquals("InnerTestClass", innerClassItem.simpleName())
assertEquals(classItem, innerClassItem.containingClass())
assertEquals(1, classItem.innerClasses().count(), message = "")
}
}
@Test
fun `090 - check class hierarchy`() {
runSourceCodebaseTest(
inputSet(
java(
"""
package test.pkg;
import test.parent.SuperInterface;
abstract class SuperClass implements SuperInterface {}
interface SuperChildInterface {}
interface ChildInterface extends SuperChildInterface,SuperInterface {}
class Test extends SuperClass implements ChildInterface {}
"""
),
java(
"""
package test.parent;
public interface SuperInterface {}
"""
),
)
) { codebase ->
val classItem = codebase.assertClass("test.pkg.Test")
val superClassItem = codebase.assertClass("test.pkg.SuperClass")
val superInterfaceItem = codebase.assertClass("test.parent.SuperInterface")
val childInterfaceItem = codebase.assertClass("test.pkg.ChildInterface")
val superChildInterfaceItem = codebase.assertClass("test.pkg.SuperChildInterface")
assertEquals(superClassItem, classItem.superClass())
assertEquals(3, classItem.allInterfaces().count(), message = "")
assertEquals(true, classItem.allInterfaces().contains(childInterfaceItem))
assertEquals(true, classItem.allInterfaces().contains(superInterfaceItem))
assertEquals(true, classItem.allInterfaces().contains(superChildInterfaceItem))
assertEquals(3, childInterfaceItem.allInterfaces().count(), message = "")
assertEquals(true, childInterfaceItem.allInterfaces().contains(superChildInterfaceItem))
assertEquals(true, childInterfaceItem.allInterfaces().contains(childInterfaceItem))
assertEquals(true, classItem.allInterfaces().contains(superInterfaceItem))
}
}
@Test
fun `100 - check class types`() {
runSourceCodebaseTest(
java(
"""
package test.pkg;
interface TestInterface {}
enum TestEnum {}
@interface TestAnnotation {}
"""
),
) { codebase ->
val interfaceItem = codebase.assertClass("test.pkg.TestInterface")
val enumItem = codebase.assertClass("test.pkg.TestEnum")
val annotationItem = codebase.assertClass("test.pkg.TestAnnotation")
assertEquals(true, interfaceItem.isInterface())
assertEquals(true, enumItem.isEnum())
assertEquals(true, annotationItem.isAnnotationType())
}
}
@Test
fun `110 - advanced package test`() {
runSourceCodebaseTest(
inputSet(
java(
"""
package test.pkg;
class Test {
class Inner {}
}
"""
),
java("""
package test;
"""),
),
) { codebase ->
val packageItem = codebase.assertPackage("test.pkg")
val parentPackageItem = codebase.assertPackage("test")
val rootPackageItem = codebase.assertPackage("")
val classItem = codebase.assertClass("test.pkg.Test")
val innerClassItem = codebase.assertClass("test.pkg.Test.Inner")
assertEquals(1, packageItem.topLevelClasses().count())
assertEquals(0, parentPackageItem.topLevelClasses().count())
assertEquals(parentPackageItem, packageItem.containingPackage())
assertEquals(rootPackageItem, parentPackageItem.containingPackage())
assertEquals(null, rootPackageItem.containingPackage())
assertEquals(packageItem, classItem.containingPackage())
assertEquals(packageItem, innerClassItem.containingPackage())
}
}
@Test
fun `120 - check modifiers`() {
runSourceCodebaseTest(
java(
"""
package test.pkg;
public final class Test1 {
private int var1;
protected static final int var2;
int var3;
}
"""
),
) { codebase ->
val packageItem = codebase.assertPackage("test.pkg")
val classItem1 = codebase.assertClass("test.pkg.Test1")
val fieldItem1 = classItem1.assertField("var1")
val fieldItem2 = classItem1.assertField("var2")
val fieldItem3 = classItem1.assertField("var3")
val packageMod = packageItem.mutableModifiers()
val classMod1 = classItem1.mutableModifiers()
val fieldMod1 = fieldItem1.mutableModifiers()
val fieldMod2 = fieldItem2.mutableModifiers()
val fieldMod3 = fieldItem3.mutableModifiers()
assertEquals(true, packageMod.isPublic())
assertEquals(true, classMod1.isPublic())
assertEquals(true, fieldMod1.isPrivate())
assertEquals(false, fieldMod1.isPackagePrivate())
assertEquals(false, fieldMod2.isPrivate())
assertEquals(true, fieldMod2.asAccessibleAs(fieldMod1))
assertEquals(true, fieldMod3.isPackagePrivate())
}
}
/**
* Check for the following:
* 1) If a class from classpath is needed by some source class, the corresponding classItem is
* created
* 2) While classpath may contain a lot of classes , only create classItems for the classes
* required by source classes directly or indirectly (e.g. superclass of superclass)
*/
@Test
fun `130 - check classes from classpath`() {
runSourceCodebaseTest(
java(
"""
package test.pkg;
import java.util.Date;
class Test extends Date {}
"""
),
) { codebase ->
val classItem = codebase.assertClass("test.pkg.Test")
val utilClassItem = codebase.assertClass("java.util.Date")
val objectClassItem = codebase.assertClass("java.lang.Object")
assertEquals(utilClassItem, classItem.superClass())
assertEquals(objectClassItem, utilClassItem.superClass())
assertEquals(3, utilClassItem.allInterfaces().count())
}
}
@Test
fun `130 - test missing symbols`() {
runSourceCodebaseTest(
java(
"""
package test.pkg;
interface Interface {}
class Test extends UnresolvedSuper implements Interface, UnresolvedInterface {}
"""
),
) { codebase ->
val classItem = codebase.assertClass("test.pkg.Test")
assertEquals(null, classItem.superClass())
assertEquals(1, classItem.allInterfaces().count())
}
}
}