diff options
author | cushon <cushon@google.com> | 2018-10-17 19:58:23 -0700 |
---|---|---|
committer | Liam Miller-Cushon <cushon@google.com> | 2018-10-17 20:45:45 -0700 |
commit | 0f63464d583386a99e08085e28a3d63426bdf81a (patch) | |
tree | faa0b6a8b2abd40b0fc2ffe590b8fde808806e26 /javatests | |
parent | d20ab95d9aa808139ea36474640315ce8a2aa139 (diff) | |
download | turbine-0f63464d583386a99e08085e28a3d63426bdf81a.tar.gz |
Fill in more of classes bound from bytecode
The additional information is read in lazily, so it's inexpensive if we
don't end up needing it.
MOE_MIGRATED_REVID=217633111
Diffstat (limited to 'javatests')
3 files changed, 166 insertions, 3 deletions
diff --git a/javatests/com/google/turbine/binder/ClassPathBinderTest.java b/javatests/com/google/turbine/binder/ClassPathBinderTest.java index 60af2a3..c2122b6 100644 --- a/javatests/com/google/turbine/binder/ClassPathBinderTest.java +++ b/javatests/com/google/turbine/binder/ClassPathBinderTest.java @@ -16,6 +16,9 @@ package com.google.turbine.binder; +import static com.google.common.collect.Iterables.getLast; +import static com.google.common.collect.Iterables.getOnlyElement; +import static com.google.common.collect.MoreCollectors.onlyElement; import static com.google.common.truth.Truth.assertThat; import static com.google.turbine.testing.TestClassPaths.TURBINE_BOOTCLASSPATH; import static java.nio.charset.StandardCharsets.UTF_8; @@ -24,16 +27,20 @@ import static org.junit.Assert.fail; import com.google.common.base.VerifyException; import com.google.common.collect.ImmutableList; import com.google.common.io.ByteStreams; -import com.google.turbine.binder.bound.HeaderBoundClass; +import com.google.turbine.binder.bound.EnumConstantValue; +import com.google.turbine.binder.bound.TypeBoundClass; import com.google.turbine.binder.bytecode.BytecodeBoundClass; import com.google.turbine.binder.env.Env; import com.google.turbine.binder.lookup.LookupKey; import com.google.turbine.binder.lookup.LookupResult; import com.google.turbine.binder.lookup.Scope; import com.google.turbine.binder.sym.ClassSymbol; +import com.google.turbine.binder.sym.FieldSymbol; import com.google.turbine.model.TurbineFlag; import com.google.turbine.model.TurbineTyKind; import com.google.turbine.tree.Tree.Ident; +import com.google.turbine.type.AnnoInfo; +import com.google.turbine.type.Type.ClassTy; import java.io.IOError; import java.io.IOException; import java.nio.file.Files; @@ -67,7 +74,7 @@ public class ClassPathBinderTest { public void classPathClasses() throws IOException { Env<ClassSymbol, BytecodeBoundClass> env = TURBINE_BOOTCLASSPATH.env(); - HeaderBoundClass c = env.get(new ClassSymbol("java/util/Map$Entry")); + TypeBoundClass c = env.get(new ClassSymbol("java/util/Map$Entry")); assertThat(c.owner()).isEqualTo(new ClassSymbol("java/util/Map")); assertThat(c.kind()).isEqualTo(TurbineTyKind.INTERFACE); @@ -85,6 +92,38 @@ public class ClassPathBinderTest { } @Test + public void interfaces() { + Env<ClassSymbol, BytecodeBoundClass> env = TURBINE_BOOTCLASSPATH.env(); + + TypeBoundClass c = env.get(new ClassSymbol("java/lang/annotation/Retention")); + assertThat(c.interfaceTypes()).hasSize(1); + assertThat(getOnlyElement(c.interfaceTypes()).sym()) + .isEqualTo(new ClassSymbol("java/lang/annotation/Annotation")); + + c = env.get(new ClassSymbol("java/util/ArrayList")); + ClassTy listInterface = + c.interfaceTypes().stream() + .filter(i -> i.sym().equals(new ClassSymbol("java/util/List"))) + .collect(onlyElement()); + assertThat(getLast(listInterface.classes).targs()).hasSize(1); + } + + @Test + public void annotations() { + Env<ClassSymbol, BytecodeBoundClass> env = TURBINE_BOOTCLASSPATH.env(); + TypeBoundClass c = env.get(new ClassSymbol("java/lang/annotation/Retention")); + + AnnoInfo anno = + c.annotations().stream() + .filter(a -> a.sym().equals(new ClassSymbol("java/lang/annotation/Retention"))) + .collect(onlyElement()); + assertThat(anno.values().keySet()).containsExactly("value"); + assertThat(((EnumConstantValue) anno.values().get("value")).sym()) + .isEqualTo( + new FieldSymbol(new ClassSymbol("java/lang/annotation/RetentionPolicy"), "RUNTIME")); + } + + @Test public void byteCodeBoundClassName() { BytecodeBoundClass c = new BytecodeBoundClass( diff --git a/javatests/com/google/turbine/binder/bytecode/BytecodeBoundClassTest.java b/javatests/com/google/turbine/binder/bytecode/BytecodeBoundClassTest.java new file mode 100644 index 0000000..da59aa6 --- /dev/null +++ b/javatests/com/google/turbine/binder/bytecode/BytecodeBoundClassTest.java @@ -0,0 +1,125 @@ +/* + * Copyright 2018 Google Inc. All Rights Reserved. + * + * 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.google.turbine.binder.bytecode; + +import static com.google.common.collect.Iterables.getLast; +import static com.google.common.collect.MoreCollectors.onlyElement; +import static com.google.common.truth.Truth.assertThat; +import static com.google.turbine.testing.TestClassPaths.TURBINE_BOOTCLASSPATH; +import static java.util.Objects.requireNonNull; + +import com.google.common.collect.ImmutableMap; +import com.google.common.io.ByteStreams; +import com.google.turbine.binder.bound.TypeBoundClass; +import com.google.turbine.binder.bound.TypeBoundClass.MethodInfo; +import com.google.turbine.binder.env.CompoundEnv; +import com.google.turbine.binder.env.Env; +import com.google.turbine.binder.env.SimpleEnv; +import com.google.turbine.binder.sym.ClassSymbol; +import com.google.turbine.type.Type.ClassTy; +import java.io.IOException; +import java.io.InputStream; +import java.io.Serializable; +import java.io.UncheckedIOException; +import java.util.List; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class BytecodeBoundClassTest { + + static class NoInterfaces {} + + abstract static class RawInterfaces implements Serializable {} + + abstract static class GenericInterfaces implements List<String> {} + + @Test + public void interfaceTypes() { + TypeBoundClass noInterfaces = getBytecodeBoundClass(NoInterfaces.class); + TypeBoundClass rawInterfaces = getBytecodeBoundClass(RawInterfaces.class); + TypeBoundClass genericInterfaces = getBytecodeBoundClass(GenericInterfaces.class); + + assertThat(noInterfaces.interfaceTypes()).isEmpty(); + + assertThat(rawInterfaces.interfaceTypes()).hasSize(1); + assertThat(rawInterfaces.interfaceTypes().get(0).sym()) + .isEqualTo(new ClassSymbol("java/io/Serializable")); + assertThat(getLast(rawInterfaces.interfaceTypes().get(0).classes).targs()).isEmpty(); + + assertThat(genericInterfaces.interfaceTypes()).hasSize(1); + assertThat(genericInterfaces.interfaceTypes().get(0).sym()) + .isEqualTo(new ClassSymbol("java/util/List")); + assertThat(getLast(genericInterfaces.interfaceTypes().get(0).classes).targs()).hasSize(1); + assertThat( + ((ClassTy) getLast(genericInterfaces.interfaceTypes().get(0).classes).targs().get(0)) + .sym()) + .isEqualTo(new ClassSymbol("java/lang/String")); + } + + static class HasMethod { + @Deprecated + <X, Y extends X, Z extends Throwable> X foo(@Deprecated X bar, Y baz) throws IOException, Z { + return null; + } + } + + @Test + public void methodTypes() { + MethodInfo m = + getBytecodeBoundClass(HasMethod.class).methods().stream() + .filter(x -> x.name().equals("foo")) + .collect(onlyElement()); + + assertThat(m.tyParams()).hasSize(3); + assertThat(m.parameters().get(0).annotations()).hasSize(1); + assertThat(m.parameters().get(0).name()).isEqualTo("bar"); + assertThat(m.exceptions()).hasSize(2); + } + + private static byte[] toByteArrayOrDie(InputStream is) { + try { + return ByteStreams.toByteArray(is); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private BytecodeBoundClass getBytecodeBoundClass( + Env<ClassSymbol, BytecodeBoundClass> env, Class<?> clazz) { + String name = clazz.getName().replace('.', '/'); + String path = "/" + name + ".class"; + return new BytecodeBoundClass( + new ClassSymbol(name), + () -> toByteArrayOrDie(requireNonNull(getClass().getResourceAsStream(path), path)), + env, + "test.jar"); + } + + private BytecodeBoundClass getBytecodeBoundClass(Class<?> clazz) { + Env<ClassSymbol, BytecodeBoundClass> env = TURBINE_BOOTCLASSPATH.env(); + env = + CompoundEnv.of(env) + .append( + new SimpleEnv<>( + ImmutableMap.of( + new ClassSymbol(BytecodeBoundClass.class.getName().replace('.', '/')), + getBytecodeBoundClass(env, BytecodeBoundClassTest.class)))); + return getBytecodeBoundClass(env, clazz); + } +} diff --git a/javatests/com/google/turbine/bytecode/ClassReaderTest.java b/javatests/com/google/turbine/bytecode/ClassReaderTest.java index 5bce03d..dda29ac 100644 --- a/javatests/com/google/turbine/bytecode/ClassReaderTest.java +++ b/javatests/com/google/turbine/bytecode/ClassReaderTest.java @@ -133,7 +133,6 @@ public class ClassReaderTest { assertThat(classFile.annotations()).hasSize(1); ClassFile.AnnotationInfo annotation = Iterables.getOnlyElement(classFile.annotations()); assertThat(annotation.typeName()).isEqualTo("Ljava/lang/annotation/Retention;"); - assertThat(annotation.isRuntimeVisible()).isTrue(); assertThat(annotation.elementValuePairs()).hasSize(1); assertThat(annotation.elementValuePairs()).containsKey("value"); ElementValue value = annotation.elementValuePairs().get("value"); |