/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.github.rodionmoiseev.c10n;
import com.github.rodionmoiseev.c10n.annotations.DefaultC10NAnnotations;
import com.github.rodionmoiseev.c10n.annotations.En;
import com.github.rodionmoiseev.c10n.plugin.C10NPlugin;
import com.github.rodionmoiseev.c10n.plugin.PluginResult;
import com.github.rodionmoiseev.c10n.test.utils.RuleUtils;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
import org.mockito.Mockito;
import java.lang.reflect.Method;
import java.util.Locale;
import java.util.NoSuchElementException;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.*;
public class PluginTest {
@Rule
public TestRule tmpLocale = RuleUtils.tmpLocale(Locale.ENGLISH);
@Rule
public TestRule tmpC10N = RuleUtils.tmpC10NConfiguration();
@Before
public void before() {
}
@C10NMessages
public interface MyMessage {
@En("Hello {0}!")
String testMessage(String user);
@En("Hello!")
void voidMethod();
@En("Message")
int intMethod();
}
@Test
public void pluginExecutionStopsWhenPluginReturnsStopSignal() {
final C10NPlugin plugin1 = Mockito.mock(C10NPlugin.class);
pluginReturn(plugin1, PluginResult.last("last message"));
final C10NPlugin plugin2 = Mockito.mock(C10NPlugin.class);
configurePlugins(plugin1, plugin2);
MyMessage mm = C10N.get(MyMessage.class);
assertThat(mm.testMessage("rodion"), is("last message"));
verify(plugin1).format(
eq("Hello rodion!"),
eq("Hello rodion!"),
refEq(new InvocationDetails(null,
MyMessage.class,
getMethod(MyMessage.class, "testMessage"),
new Object[]{"rodion"}), "proxy"));
verifyZeroInteractions(plugin2);
}
@Test
public void pluginExecutionSkipsWhenPluginReturnsNull() {
final C10NPlugin plugin1 = Mockito.mock(C10NPlugin.class);
pluginReturn(plugin1, null);
final C10NPlugin plugin2 = Mockito.mock(C10NPlugin.class);
pluginReturn(plugin2, PluginResult.passOn("plugin result2"));
configurePlugins(plugin1, plugin2);
MyMessage mm = C10N.get(MyMessage.class);
assertThat(mm.testMessage("rodion"), is("plugin result2"));
verify(plugin1).format(
eq("Hello rodion!"),
eq("Hello rodion!"),
refEq(new InvocationDetails(null,
MyMessage.class,
getMethod(MyMessage.class, "testMessage"),
new Object[]{"rodion"}), "proxy"));
verify(plugin2).format(
eq("Hello rodion!"),
eq("Hello rodion!"),
refEq(new InvocationDetails(null,
MyMessage.class,
getMethod(MyMessage.class, "testMessage"),
new Object[]{"rodion"}), "proxy"));// <-- receives the original message
}
@Test
public void pluginPassesTheModifiedValueToTheNextPlugin() {
final C10NPlugin plugin1 = Mockito.mock(C10NPlugin.class);
pluginReturn(plugin1, PluginResult.passOn("plugin result1"));
final C10NPlugin plugin2 = Mockito.mock(C10NPlugin.class);
pluginReturn(plugin2, PluginResult.passOn("plugin result2"));
configurePlugins(plugin1, plugin2);
MyMessage mm = C10N.get(MyMessage.class);
assertThat(mm.testMessage("rodion"), is("plugin result2"));
verify(plugin1).format(
eq("Hello rodion!"),
eq("Hello rodion!"),
refEq(new InvocationDetails(null,
MyMessage.class,
getMethod(MyMessage.class, "testMessage"),
new Object[]{"rodion"}), "proxy"));
verify(plugin2).format(
eq("Hello rodion!"),
eq("plugin result1"),
refEq(new InvocationDetails(null,
MyMessage.class,
getMethod(MyMessage.class, "testMessage"),
new Object[]{"rodion"}), "proxy"));
}
@Test
public void voidMethodEquallyGetsPassedTheTranslatedString() throws Exception {
final C10NPlugin plugin1 = Mockito.mock(C10NPlugin.class);
pluginReturn(plugin1, PluginResult.passOn("plugin result1"));
configurePlugins(plugin1);
MyMessage mm = C10N.get(MyMessage.class);
mm.voidMethod();
verify(plugin1).format(
eq("Hello!"),
eq(null), //void returns null
refEq(new InvocationDetails(null,
MyMessage.class,
getMethod(MyMessage.class, "voidMethod"),
null), "proxy"));
}
@Test
public void pluginCanReturnAnyValueForMethod() throws Exception {
final C10NPlugin plugin1 = Mockito.mock(C10NPlugin.class);
pluginReturn(plugin1, PluginResult.passOn(123));
configurePlugins(plugin1);
MyMessage mm = C10N.get(MyMessage.class);
assertThat(mm.intMethod(), is(equalTo(123)));
verify(plugin1).format(
eq("Message"),
eq(null), //null as int is not known by c10n itself
refEq(new InvocationDetails(null,
MyMessage.class,
getMethod(MyMessage.class, "intMethod"),
null), "proxy"));
}
private void configurePlugins(final C10NPlugin... plugins) {
C10N.configure(new C10NConfigBase() {
@Override
protected void configure() {
install(new DefaultC10NAnnotations());
for (C10NPlugin plugin : plugins) {
installPlugin(plugin);
}
}
});
}
private Method getMethod(Class<?> clazz, String methodName) {
for (Method method : clazz.getMethods()) {
if (method.getName().equals(methodName)) {
return method;
}
}
throw new NoSuchElementException(methodName);
}
private void pluginReturn(C10NPlugin plugin, PluginResult result) {
when(plugin.format(any(String.class),
any(Object.class),
any(InvocationDetails.class))).thenReturn(result);
}
}