mirror of
https://github.com/google/guice.git
synced 2024-04-21 12:32:36 +00:00
In Java 15, the annotation `toString` implementation omits the member name. PiperOrigin-RevId: 338746927
657 lines
21 KiB
Java
657 lines
21 KiB
Java
/*
|
|
* Copyright (C) 2010 Google Inc.
|
|
*
|
|
* 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.inject;
|
|
|
|
import static com.google.inject.Asserts.*;
|
|
import static com.google.inject.name.Names.named;
|
|
|
|
import com.google.common.base.Objects;
|
|
import com.google.common.collect.Lists;
|
|
import com.google.inject.internal.Annotations;
|
|
import com.google.inject.name.Named;
|
|
import com.google.inject.spi.Element;
|
|
import com.google.inject.spi.Elements;
|
|
import com.google.inject.util.Providers;
|
|
import java.lang.annotation.Annotation;
|
|
import java.lang.reflect.Constructor;
|
|
import java.util.Arrays;
|
|
import java.util.Collection;
|
|
import java.util.LinkedHashSet;
|
|
import java.util.List;
|
|
import java.util.logging.Logger;
|
|
import junit.framework.TestCase;
|
|
|
|
/**
|
|
* A suite of tests for duplicate bindings.
|
|
*
|
|
* @author sameb@google.com (Sam Berlin)
|
|
*/
|
|
public class DuplicateBindingsTest extends TestCase {
|
|
|
|
private FooImpl foo = new FooImpl();
|
|
private Provider<Foo> pFoo = Providers.<Foo>of(new FooImpl());
|
|
private Class<? extends Provider<? extends Foo>> pclFoo = FooProvider.class;
|
|
private Class<? extends Foo> clFoo = FooImpl.class;
|
|
private Constructor<FooImpl> cFoo = FooImpl.cxtor();
|
|
|
|
public void testDuplicateBindingsAreIgnored() {
|
|
Injector injector =
|
|
Guice.createInjector(
|
|
new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo),
|
|
new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo));
|
|
List<Key<?>> bindings = Lists.newArrayList(injector.getAllBindings().keySet());
|
|
removeBasicBindings(bindings);
|
|
|
|
// Ensure only one binding existed for each type.
|
|
assertTrue(bindings.remove(Key.get(Foo.class, named("instance"))));
|
|
assertTrue(bindings.remove(Key.get(Foo.class, named("pInstance"))));
|
|
assertTrue(bindings.remove(Key.get(Foo.class, named("pKey"))));
|
|
assertTrue(bindings.remove(Key.get(Foo.class, named("linkedKey"))));
|
|
assertTrue(bindings.remove(Key.get(FooImpl.class)));
|
|
assertTrue(bindings.remove(Key.get(Foo.class, named("constructor"))));
|
|
assertTrue(bindings.remove(Key.get(FooProvider.class))); // JIT binding
|
|
assertTrue(bindings.remove(Key.get(Foo.class, named("providerMethod"))));
|
|
|
|
assertEquals(bindings.toString(), 0, bindings.size());
|
|
}
|
|
|
|
public void testElementsDeduplicate() {
|
|
List<Element> elements =
|
|
Elements.getElements(
|
|
new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo),
|
|
new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo));
|
|
assertEquals(14, elements.size());
|
|
assertEquals(7, new LinkedHashSet<Element>(elements).size());
|
|
}
|
|
|
|
public void testProviderMethodsFailIfInstancesDiffer() {
|
|
try {
|
|
Guice.createInjector(new FailingProviderModule(), new FailingProviderModule());
|
|
fail("should have failed");
|
|
} catch (CreationException ce) {
|
|
assertContains(
|
|
ce.getMessage(),
|
|
"DuplicateBindingsTest$Foo was bound multiple times.",
|
|
"1 : DuplicateBindingsTest$FailingProviderModule.foo",
|
|
"2 : DuplicateBindingsTest$FailingProviderModule.foo");
|
|
}
|
|
}
|
|
|
|
public void testSameScopeInstanceIgnored() {
|
|
Guice.createInjector(
|
|
new ScopedModule(Scopes.SINGLETON, foo, pFoo, pclFoo, clFoo, cFoo),
|
|
new ScopedModule(Scopes.SINGLETON, foo, pFoo, pclFoo, clFoo, cFoo));
|
|
|
|
Guice.createInjector(
|
|
new ScopedModule(Scopes.NO_SCOPE, foo, pFoo, pclFoo, clFoo, cFoo),
|
|
new ScopedModule(Scopes.NO_SCOPE, foo, pFoo, pclFoo, clFoo, cFoo));
|
|
}
|
|
|
|
public void testSameScopeAnnotationIgnored() {
|
|
Guice.createInjector(
|
|
new AnnotatedScopeModule(Singleton.class, foo, pFoo, pclFoo, clFoo, cFoo),
|
|
new AnnotatedScopeModule(Singleton.class, foo, pFoo, pclFoo, clFoo, cFoo));
|
|
}
|
|
|
|
public void testMixedAnnotationAndScopeForSingletonIgnored() {
|
|
Guice.createInjector(
|
|
new ScopedModule(Scopes.SINGLETON, foo, pFoo, pclFoo, clFoo, cFoo),
|
|
new AnnotatedScopeModule(Singleton.class, foo, pFoo, pclFoo, clFoo, cFoo));
|
|
}
|
|
|
|
public void testMixedScopeAndUnscopedIgnored() {
|
|
Guice.createInjector(
|
|
new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo),
|
|
new ScopedModule(Scopes.NO_SCOPE, foo, pFoo, pclFoo, clFoo, cFoo));
|
|
}
|
|
|
|
public void testMixedScopeFails() {
|
|
try {
|
|
Guice.createInjector(
|
|
new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo),
|
|
new ScopedModule(Scopes.SINGLETON, foo, pFoo, pclFoo, clFoo, cFoo));
|
|
fail("expected exception");
|
|
} catch (CreationException ce) {
|
|
String template =
|
|
"DuplicateBindingsTest$Foo annotated with @Named(%s)" + " was bound multiple times.";
|
|
String segment1 =
|
|
String.format(template, Annotations.memberValueString("value", "pInstance"));
|
|
String segment2 = String.format(template, Annotations.memberValueString("value", "pKey"));
|
|
String segment3 =
|
|
String.format(template, Annotations.memberValueString("value", "constructor"));
|
|
String segment4 = "DuplicateBindingsTest$FooImpl was bound multiple times";
|
|
String atSegment = "DuplicateBindingsTest$ScopedModule.configure";
|
|
if (isIncludeStackTraceOff()) {
|
|
assertContains(
|
|
ce.getMessage(),
|
|
segment1,
|
|
atSegment,
|
|
segment2,
|
|
atSegment,
|
|
segment3,
|
|
atSegment,
|
|
segment4,
|
|
atSegment);
|
|
} else {
|
|
assertContains(
|
|
ce.getMessage(),
|
|
segment1,
|
|
atSegment,
|
|
segment2,
|
|
atSegment,
|
|
segment4,
|
|
atSegment,
|
|
segment3,
|
|
atSegment);
|
|
}
|
|
}
|
|
}
|
|
|
|
@SuppressWarnings("unchecked")
|
|
public void testMixedTargetsFails() {
|
|
try {
|
|
Guice.createInjector(
|
|
new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo),
|
|
new SimpleModule(
|
|
new FooImpl(),
|
|
Providers.<Foo>of(new FooImpl()),
|
|
(Class) BarProvider.class,
|
|
(Class) Bar.class,
|
|
(Constructor) Bar.cxtor()));
|
|
fail("expected exception");
|
|
} catch (CreationException ce) {
|
|
String template =
|
|
"DuplicateBindingsTest$Foo annotated with @Named(%s) was bound multiple times.";
|
|
String segment1 = String.format(template, Annotations.memberValueString("value", "instance"));
|
|
String segment2 =
|
|
String.format(template, Annotations.memberValueString("value", "pInstance"));
|
|
String segment3 = String.format(template, Annotations.memberValueString("value", "pKey"));
|
|
String segment4 =
|
|
String.format(template, Annotations.memberValueString("value", "linkedKey"));
|
|
String segment5 =
|
|
String.format(template, Annotations.memberValueString("value", "constructor"));
|
|
assertContains(
|
|
ce.getMessage(),
|
|
segment1,
|
|
"1 : DuplicateBindingsTest$SimpleModule.configure",
|
|
"2 : DuplicateBindingsTest$SimpleModule.configure",
|
|
segment2,
|
|
"1 : DuplicateBindingsTest$SimpleModule.configure",
|
|
"2 : DuplicateBindingsTest$SimpleModule.configure",
|
|
segment3,
|
|
"1 : DuplicateBindingsTest$SimpleModule.configure",
|
|
"2 : DuplicateBindingsTest$SimpleModule.configure",
|
|
segment4,
|
|
"1 : DuplicateBindingsTest$SimpleModule.configure",
|
|
"2 : DuplicateBindingsTest$SimpleModule.configure",
|
|
segment5,
|
|
"1 : DuplicateBindingsTest$SimpleModule.configure",
|
|
"2 : DuplicateBindingsTest$SimpleModule.configure");
|
|
}
|
|
}
|
|
|
|
public void testExceptionInEqualsThrowsCreationException() {
|
|
try {
|
|
Guice.createInjector(new ThrowingModule(), new ThrowingModule());
|
|
fail("expected exception");
|
|
} catch (CreationException ce) {
|
|
assertContains(
|
|
ce.getMessage(),
|
|
"A binding to DuplicateBindingsTest$Foo was already configured at"
|
|
+ " DuplicateBindingsTest$ThrowingModule.configure",
|
|
"and an error was thrown while checking duplicate bindings. Error:"
|
|
+ " RuntimeException: Boo!",
|
|
"at DuplicateBindingsTest$ThrowingModule.configure");
|
|
}
|
|
}
|
|
|
|
public void testChildInjectorDuplicateParentFail() {
|
|
Injector injector = Guice.createInjector(new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo));
|
|
|
|
try {
|
|
injector.createChildInjector(new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo));
|
|
fail("expected exception");
|
|
} catch (CreationException ce) {
|
|
String template =
|
|
"DuplicateBindingsTest$Foo annotated with @Named(%s) was bound" + " multiple times.";
|
|
String atSegment = "DuplicateBindingsTest$SimpleModule.configure";
|
|
assertContains(
|
|
ce.getMessage(),
|
|
String.format(template, Annotations.memberValueString("value", "instance")),
|
|
atSegment,
|
|
String.format(template, Annotations.memberValueString("value", "pKey")),
|
|
atSegment,
|
|
String.format(template, Annotations.memberValueString("value", "linkedKey")),
|
|
atSegment,
|
|
String.format(template, Annotations.memberValueString("value", "constructor")),
|
|
atSegment,
|
|
String.format(template, Annotations.memberValueString("value", "providerMethod")),
|
|
"1 : DuplicateBindingsTest$SimpleProviderModule.foo",
|
|
"2 : DuplicateBindingsTest$SimpleProviderModule.foo");
|
|
}
|
|
}
|
|
|
|
public void testDuplicatesSolelyInChildIgnored() {
|
|
Injector injector = Guice.createInjector();
|
|
injector.createChildInjector(
|
|
new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo),
|
|
new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo));
|
|
}
|
|
|
|
public void testDifferentBindingTypesFail() {
|
|
List<Element> elements = Elements.getElements(new FailedModule(foo, pFoo, pclFoo, clFoo, cFoo));
|
|
|
|
// Make sure every combination of the elements with another element fails.
|
|
// This ensures that duplication checks the kind of binding also.
|
|
for (Element e1 : elements) {
|
|
for (Element e2 : elements) {
|
|
// if they're the same, this shouldn't fail.
|
|
try {
|
|
Guice.createInjector(Elements.getModule(Arrays.asList(e1, e2)));
|
|
if (e1 != e2) {
|
|
fail("must fail!");
|
|
}
|
|
} catch (CreationException expected) {
|
|
if (e1 != e2) {
|
|
assertContains(
|
|
expected.getMessage(),
|
|
"DuplicateBindingsTest$Foo was bound multiple times.",
|
|
"1 : DuplicateBindingsTest$FailedModule.",
|
|
"2 : DuplicateBindingsTest$FailedModule.");
|
|
} else {
|
|
throw expected;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void testJitBindingsAreCheckedAfterConversions() {
|
|
Guice.createInjector(
|
|
new AbstractModule() {
|
|
@Override
|
|
protected void configure() {
|
|
bind(A.class);
|
|
bind(A.class).to(RealA.class);
|
|
}
|
|
});
|
|
}
|
|
|
|
public void testEqualsNotCalledByDefaultOnInstance() {
|
|
final HashEqualsTester a = new HashEqualsTester();
|
|
a.throwOnEquals = true;
|
|
Guice.createInjector(
|
|
new AbstractModule() {
|
|
@Override
|
|
protected void configure() {
|
|
bind(String.class);
|
|
bind(HashEqualsTester.class).toInstance(a);
|
|
}
|
|
});
|
|
}
|
|
|
|
public void testEqualsNotCalledByDefaultOnProvider() {
|
|
final HashEqualsTester a = new HashEqualsTester();
|
|
a.throwOnEquals = true;
|
|
Guice.createInjector(
|
|
new AbstractModule() {
|
|
@Override
|
|
protected void configure() {
|
|
bind(String.class);
|
|
bind(Object.class).toProvider(a);
|
|
}
|
|
});
|
|
}
|
|
|
|
public void testHashcodeNeverCalledOnInstance() {
|
|
final HashEqualsTester a = new HashEqualsTester();
|
|
a.throwOnHashcode = true;
|
|
a.equality = "test";
|
|
|
|
final HashEqualsTester b = new HashEqualsTester();
|
|
b.throwOnHashcode = true;
|
|
b.equality = "test";
|
|
Guice.createInjector(
|
|
new AbstractModule() {
|
|
@Override
|
|
protected void configure() {
|
|
bind(String.class);
|
|
bind(HashEqualsTester.class).toInstance(a);
|
|
bind(HashEqualsTester.class).toInstance(b);
|
|
}
|
|
});
|
|
}
|
|
|
|
public void testHashcodeNeverCalledOnProviderInstance() {
|
|
final HashEqualsTester a = new HashEqualsTester();
|
|
a.throwOnHashcode = true;
|
|
a.equality = "test";
|
|
|
|
final HashEqualsTester b = new HashEqualsTester();
|
|
b.throwOnHashcode = true;
|
|
b.equality = "test";
|
|
Guice.createInjector(
|
|
new AbstractModule() {
|
|
@Override
|
|
protected void configure() {
|
|
bind(String.class);
|
|
bind(Object.class).toProvider(a);
|
|
bind(Object.class).toProvider(b);
|
|
}
|
|
});
|
|
}
|
|
|
|
private static class RealA extends A {}
|
|
|
|
@ImplementedBy(RealA.class)
|
|
private static class A {}
|
|
|
|
private void removeBasicBindings(Collection<Key<?>> bindings) {
|
|
bindings.remove(Key.get(Injector.class));
|
|
bindings.remove(Key.get(Logger.class));
|
|
bindings.remove(Key.get(Stage.class));
|
|
}
|
|
|
|
private static class ThrowingModule extends AbstractModule {
|
|
@Override
|
|
protected void configure() {
|
|
bind(Foo.class)
|
|
.toInstance(
|
|
new Foo() {
|
|
@Override
|
|
public boolean equals(Object obj) {
|
|
throw new RuntimeException("Boo!");
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
throw new RuntimeException("Boo!");
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
private abstract static class FooModule extends AbstractModule {
|
|
protected final FooImpl foo;
|
|
protected final Provider<Foo> pFoo;
|
|
protected final Class<? extends Provider<? extends Foo>> pclFoo;
|
|
protected final Class<? extends Foo> clFoo;
|
|
protected final Constructor<FooImpl> cFoo;
|
|
|
|
FooModule(
|
|
FooImpl foo,
|
|
Provider<Foo> pFoo,
|
|
Class<? extends Provider<? extends Foo>> pclFoo,
|
|
Class<? extends Foo> clFoo,
|
|
Constructor<FooImpl> cFoo) {
|
|
this.foo = foo;
|
|
this.pFoo = pFoo;
|
|
this.pclFoo = pclFoo;
|
|
this.clFoo = clFoo;
|
|
this.cFoo = cFoo;
|
|
}
|
|
}
|
|
|
|
private static class FailedModule extends FooModule {
|
|
FailedModule(
|
|
FooImpl foo,
|
|
Provider<Foo> pFoo,
|
|
Class<? extends Provider<? extends Foo>> pclFoo,
|
|
Class<? extends Foo> clFoo,
|
|
Constructor<FooImpl> cFoo) {
|
|
super(foo, pFoo, pclFoo, clFoo, cFoo);
|
|
}
|
|
|
|
@Override
|
|
protected void configure() {
|
|
// InstanceBinding
|
|
bind(Foo.class).toInstance(foo);
|
|
|
|
// ProviderInstanceBinding
|
|
bind(Foo.class).toProvider(pFoo);
|
|
|
|
// ProviderKeyBinding
|
|
bind(Foo.class).toProvider(pclFoo);
|
|
|
|
// LinkedKeyBinding
|
|
bind(Foo.class).to(clFoo);
|
|
|
|
// ConstructorBinding
|
|
bind(Foo.class).toConstructor(cFoo);
|
|
}
|
|
|
|
@Provides
|
|
Foo foo() {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private static class FailingProviderModule extends AbstractModule {
|
|
|
|
@Provides
|
|
Foo foo() {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private static class SimpleProviderModule extends AbstractModule {
|
|
|
|
@Provides
|
|
@Named("providerMethod")
|
|
Foo foo() {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
@SuppressWarnings({
|
|
"EqualsHashCode",
|
|
"EqualsBrokenForNull"
|
|
}) // intentionally NPE on null for the test
|
|
public boolean equals(Object obj) {
|
|
return obj.getClass() == getClass();
|
|
}
|
|
}
|
|
|
|
private static class SimpleModule extends FooModule {
|
|
SimpleModule(
|
|
FooImpl foo,
|
|
Provider<Foo> pFoo,
|
|
Class<? extends Provider<? extends Foo>> pclFoo,
|
|
Class<? extends Foo> clFoo,
|
|
Constructor<FooImpl> cFoo) {
|
|
super(foo, pFoo, pclFoo, clFoo, cFoo);
|
|
}
|
|
|
|
@Override
|
|
protected void configure() {
|
|
// InstanceBinding
|
|
bind(Foo.class).annotatedWith(named("instance")).toInstance(foo);
|
|
|
|
// ProviderInstanceBinding
|
|
bind(Foo.class).annotatedWith(named("pInstance")).toProvider(pFoo);
|
|
|
|
// ProviderKeyBinding
|
|
bind(Foo.class).annotatedWith(named("pKey")).toProvider(pclFoo);
|
|
|
|
// LinkedKeyBinding
|
|
bind(Foo.class).annotatedWith(named("linkedKey")).to(clFoo);
|
|
|
|
// UntargettedBinding / ConstructorBinding
|
|
bind(FooImpl.class);
|
|
|
|
// ConstructorBinding
|
|
bind(Foo.class).annotatedWith(named("constructor")).toConstructor(cFoo);
|
|
|
|
// ProviderMethod
|
|
// (reconstructed from an Element to ensure it doesn't get filtered out
|
|
// by deduplicating Modules)
|
|
install(Elements.getModule(Elements.getElements(new SimpleProviderModule())));
|
|
}
|
|
}
|
|
|
|
private static class ScopedModule extends FooModule {
|
|
private final Scope scope;
|
|
|
|
ScopedModule(
|
|
Scope scope,
|
|
FooImpl foo,
|
|
Provider<Foo> pFoo,
|
|
Class<? extends Provider<? extends Foo>> pclFoo,
|
|
Class<? extends Foo> clFoo,
|
|
Constructor<FooImpl> cFoo) {
|
|
super(foo, pFoo, pclFoo, clFoo, cFoo);
|
|
this.scope = scope;
|
|
}
|
|
|
|
@Override
|
|
protected void configure() {
|
|
// ProviderInstanceBinding
|
|
bind(Foo.class).annotatedWith(named("pInstance")).toProvider(pFoo).in(scope);
|
|
|
|
// ProviderKeyBinding
|
|
bind(Foo.class).annotatedWith(named("pKey")).toProvider(pclFoo).in(scope);
|
|
|
|
// LinkedKeyBinding
|
|
bind(Foo.class).annotatedWith(named("linkedKey")).to(clFoo).in(scope);
|
|
|
|
// UntargettedBinding / ConstructorBinding
|
|
bind(FooImpl.class).in(scope);
|
|
|
|
// ConstructorBinding
|
|
bind(Foo.class).annotatedWith(named("constructor")).toConstructor(cFoo).in(scope);
|
|
}
|
|
}
|
|
|
|
private static class AnnotatedScopeModule extends FooModule {
|
|
private final Class<? extends Annotation> scope;
|
|
|
|
AnnotatedScopeModule(
|
|
Class<? extends Annotation> scope,
|
|
FooImpl foo,
|
|
Provider<Foo> pFoo,
|
|
Class<? extends Provider<? extends Foo>> pclFoo,
|
|
Class<? extends Foo> clFoo,
|
|
Constructor<FooImpl> cFoo) {
|
|
super(foo, pFoo, pclFoo, clFoo, cFoo);
|
|
this.scope = scope;
|
|
}
|
|
|
|
@Override
|
|
protected void configure() {
|
|
// ProviderInstanceBinding
|
|
bind(Foo.class).annotatedWith(named("pInstance")).toProvider(pFoo).in(scope);
|
|
|
|
// ProviderKeyBinding
|
|
bind(Foo.class).annotatedWith(named("pKey")).toProvider(pclFoo).in(scope);
|
|
|
|
// LinkedKeyBinding
|
|
bind(Foo.class).annotatedWith(named("linkedKey")).to(clFoo).in(scope);
|
|
|
|
// UntargettedBinding / ConstructorBinding
|
|
bind(FooImpl.class).in(scope);
|
|
|
|
// ConstructorBinding
|
|
bind(Foo.class).annotatedWith(named("constructor")).toConstructor(cFoo).in(scope);
|
|
}
|
|
}
|
|
|
|
private static interface Foo {}
|
|
|
|
private static class FooImpl implements Foo {
|
|
@Inject
|
|
public FooImpl() {}
|
|
|
|
private static Constructor<FooImpl> cxtor() {
|
|
try {
|
|
return FooImpl.class.getConstructor();
|
|
} catch (SecurityException e) {
|
|
throw new RuntimeException(e);
|
|
} catch (NoSuchMethodException e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static class FooProvider implements Provider<Foo> {
|
|
@Override
|
|
public Foo get() {
|
|
return new FooImpl();
|
|
}
|
|
}
|
|
|
|
private static class Bar implements Foo {
|
|
@Inject
|
|
public Bar() {}
|
|
|
|
private static Constructor<Bar> cxtor() {
|
|
try {
|
|
return Bar.class.getConstructor();
|
|
} catch (SecurityException e) {
|
|
throw new RuntimeException(e);
|
|
} catch (NoSuchMethodException e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static class BarProvider implements Provider<Foo> {
|
|
@Override
|
|
public Foo get() {
|
|
return new Bar();
|
|
}
|
|
}
|
|
|
|
private static class HashEqualsTester implements Provider<Object> {
|
|
private String equality;
|
|
private boolean throwOnEquals;
|
|
private boolean throwOnHashcode;
|
|
|
|
@Override
|
|
public boolean equals(Object obj) {
|
|
if (throwOnEquals) {
|
|
throw new RuntimeException();
|
|
} else if (obj instanceof HashEqualsTester) {
|
|
HashEqualsTester o = (HashEqualsTester) obj;
|
|
if (o.throwOnEquals) {
|
|
throw new RuntimeException();
|
|
}
|
|
if (equality == null && o.equality == null) {
|
|
return this == o;
|
|
} else {
|
|
return Objects.equal(equality, o.equality);
|
|
}
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
if (throwOnHashcode) {
|
|
throw new RuntimeException();
|
|
} else {
|
|
return super.hashCode();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public Object get() {
|
|
return new Object();
|
|
}
|
|
}
|
|
}
|