/*
* Copyright 2016 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.errorprone.bugpatterns;
import com.google.common.io.ByteStreams;
import com.google.errorprone.CompilationTestHelper;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public class FunctionalInterfaceClashTest {
@Rule public final TemporaryFolder tempFolder = new TemporaryFolder();
private final CompilationTestHelper testHelper =
CompilationTestHelper.newInstance(FunctionalInterfaceClash.class, getClass());
@Test
public void positive() {
testHelper
.addSourceLines(
"Test.java", //
"import java.util.function.Function;",
"import java.util.function.Consumer;",
"public class Test {",
" // BUG: Diagnostic contains: disambiguate with: foo(Function<String, String>)",
" void foo(Consumer<String> x) {}",
" void foo(Function<String, String> c) {}",
"}")
.doTest();
}
@Test
public void positiveNullary() {
testHelper
.addSourceLines(
"Test.java", //
"import java.util.concurrent.Callable;",
"public class Test {",
" interface MyCallable {",
" String call();",
" }",
" // BUG: Diagnostic contains: disambiguate with: foo(MyCallable)",
" void foo(Callable<String> x) {}",
" void foo(MyCallable c) {}",
"}")
.doTest();
}
@Test
public void positiveInherited() {
testHelper
.addSourceLines(
"Super.java", //
"import java.util.function.Function;",
"class Super {",
" void foo(Function<String, String> x) {}",
"}")
.addSourceLines(
"Test.java", //
"import java.util.function.Consumer;",
"public class Test extends Super {",
" // BUG: Diagnostic contains: disambiguate with: Super.foo(Function<String, String>)",
" void foo(Consumer<String> c) {}",
"}")
.doTest();
}
@Test
public void positiveArgs() {
testHelper
.addSourceLines(
"Test.java", //
"import java.util.function.Function;",
"import java.util.function.Consumer;",
"public class Test {",
" // BUG: Diagnostic contains: disambiguate with: foo(Function<String, Integer>)",
" void foo(Consumer<String> c) {}",
" void foo(Function<String, Integer> f) {}",
"}")
.doTest();
}
@Test
public void negativeOverride() {
testHelper
.addSourceLines(
"Super.java", //
"import java.util.function.Consumer;",
"class Super {",
" void foo(Consumer<String> x) {}",
"}")
.addSourceLines(
"Test.java", //
"import java.util.function.Consumer;",
"public class Test extends Super {",
" void foo(Consumer<String> x) {}",
"}")
.doTest();
}
@Test
public void negativeSuperConstructor() {
testHelper
.addSourceLines(
"Super.java", //
"import java.util.function.Function;",
"class Super {",
" Super(Function<String, String> r) {}",
"}")
.addSourceLines(
"Test.java", //
"import java.util.function.Consumer;",
"public class Test extends Super {",
" Test(Consumer<String> r) { super(null); }",
"}")
.doTest();
}
@Test
public void positiveConstructor() {
testHelper
.addSourceLines(
"Test.java", //
"import java.util.function.Function;",
"import java.util.function.Consumer;",
"public class Test {",
" // BUG: Diagnostic contains: disambiguate with: Test(Function<String, String>)",
" Test(Consumer<String> r) {}",
" Test(Function<String, String> c) {}",
"}")
.doTest();
}
@Test
public void positiveStatic() {
testHelper
.addSourceLines(
"Test.java", //
"import java.util.function.Function;",
"import java.util.function.Consumer;",
"public class Test {",
" // BUG: Diagnostic contains: disambiguate with: foo(Function<String, String>)",
" static void foo(Consumer<String> x) {}",
" void foo(Function<String, String> c) {}",
"}")
.doTest();
}
public static class Other {}
public static class Super {
public void f(Other o) {}
}
static void addClassToJar(JarOutputStream jos, Class<?> clazz) throws IOException {
String entryPath = clazz.getName().replace('.', '/') + ".class";
try (InputStream is = clazz.getClassLoader().getResourceAsStream(entryPath)) {
jos.putNextEntry(new JarEntry(entryPath));
ByteStreams.copy(is, jos);
}
}
@Test
public void incompleteClasspath() throws Exception {
File libJar = tempFolder.newFile("lib.jar");
try (FileOutputStream fis = new FileOutputStream(libJar);
JarOutputStream jos = new JarOutputStream(fis)) {
addClassToJar(jos, getClass());
addClassToJar(jos, Super.class);
}
testHelper
.addSourceLines(
"Test.java",
"import " + Super.class.getCanonicalName() + ";",
"class Test extends Super {}")
.setArgs(Arrays.asList("-cp", libJar.toString()))
.doTest();
}
public void suppressWarningsOnMethod() {
testHelper
.addSourceLines(
"Test.java",
"import java.lang.SuppressWarnings;",
"import java.util.function.Function;",
"import java.util.function.Consumer;",
"public class Test {",
" @SuppressWarnings(\"FunctionalInterfaceClash\")",
" void foo(Consumer<String> x) {}",
" void foo(Function<String, String> c) {}",
"}")
.doTest();
}
}