subscriberClassByMethodKey = new HashMap<>();
final StringBuilder methodKeyBuilder = new StringBuilder(128);
Class> subscriberClass;
Class> clazz;
boolean skipSuperClasses;
SubscriberInfo subscriberInfo;
void initForSubscriber(Class> subscriberClass) {
this.subscriberClass = clazz = subscriberClass;
skipSuperClasses = false;
subscriberInfo = null;
}
void recycle() {
subscriberMethods.clear();
anyMethodByEventType.clear();
subscriberClassByMethodKey.clear();
methodKeyBuilder.setLength(0);
subscriberClass = null;
clazz = null;
skipSuperClasses = false;
subscriberInfo = null;
}
boolean checkAdd(Method method, Class> eventType) {
// 2 level check: 1st level with event type only (fast), 2nd level with complete signature when required.
// Usually a subscriber doesn't have methods listening to the same event type.
Object existing = anyMethodByEventType.put(eventType, method);
if (existing == null) {
return true;
} else {
if (existing instanceof Method) {
if (!checkAddWithMethodSignature((Method) existing, eventType)) {
// Paranoia check
throw new IllegalStateException();
}
// Put any non-Method object to "consume" the existing Method
anyMethodByEventType.put(eventType, this);
}
return checkAddWithMethodSignature(method, eventType);
}
}
private boolean checkAddWithMethodSignature(Method method, Class> eventType) {
methodKeyBuilder.setLength(0);
methodKeyBuilder.append(method.getName());
methodKeyBuilder.append('>').append(eventType.getName());
String methodKey = methodKeyBuilder.toString();
Class> methodClass = method.getDeclaringClass();
Class> methodClassOld = subscriberClassByMethodKey.put(methodKey, methodClass);
if (methodClassOld == null || methodClassOld.isAssignableFrom(methodClass)) {
// Only add if not already found in a sub class
return true;
} else {
// Revert the put, old class is further down the class hierarchy
subscriberClassByMethodKey.put(methodKey, methodClassOld);
return false;
}
}
void moveToSuperclass() {
if (skipSuperClasses) {
clazz = null;
} else {
clazz = clazz.getSuperclass();
String clazzName = clazz.getName();
// Skip system classes, this degrades performance.
// Also we might avoid some ClassNotFoundException (see FAQ for background).
if (clazzName.startsWith("java.") || clazzName.startsWith("javax.") ||
clazzName.startsWith("android.") || clazzName.startsWith("androidx.")) {
clazz = null;
}
}
}
}
}
================================================
FILE: EventBus/src/org/greenrobot/eventbus/Subscription.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus;
final class Subscription {
final Object subscriber;
final SubscriberMethod subscriberMethod;
/**
* Becomes false as soon as {@link EventBus#unregister(Object)} is called, which is checked by queued event delivery
* {@link EventBus#invokeSubscriber(PendingPost)} to prevent race conditions.
*/
volatile boolean active;
Subscription(Object subscriber, SubscriberMethod subscriberMethod) {
this.subscriber = subscriber;
this.subscriberMethod = subscriberMethod;
active = true;
}
@Override
public boolean equals(Object other) {
if (other instanceof Subscription) {
Subscription otherSubscription = (Subscription) other;
return subscriber == otherSubscription.subscriber
&& subscriberMethod.equals(otherSubscription.subscriberMethod);
} else {
return false;
}
}
@Override
public int hashCode() {
return subscriber.hashCode() + subscriberMethod.methodString.hashCode();
}
}
================================================
FILE: EventBus/src/org/greenrobot/eventbus/ThreadMode.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus;
/**
* Each subscriber method has a thread mode, which determines in which thread the method is to be called by EventBus.
* EventBus takes care of threading independently of the posting thread.
*
* @see EventBus#register(Object)
*/
public enum ThreadMode {
/**
* This is the default. Subscriber will be called directly in the same thread, which is posting the event. Event delivery
* implies the least overhead because it avoids thread switching completely. Thus, this is the recommended mode for
* simple tasks that are known to complete in a very short time without requiring the main thread. Event handlers
* using this mode must return quickly to avoid blocking the posting thread, which may be the main thread.
*/
POSTING,
/**
* On Android, subscriber will be called in Android's main thread (UI thread). If the posting thread is
* the main thread, subscriber methods will be called directly, blocking the posting thread. Otherwise the event
* is queued for delivery (non-blocking). Subscribers using this mode must return quickly to avoid blocking the main thread.
*
* If not on Android, behaves the same as {@link #POSTING}.
*/
MAIN,
/**
* On Android, subscriber will be called in Android's main thread (UI thread). Different from {@link #MAIN},
* the event will always be queued for delivery. This ensures that the post call is non-blocking.
*
* If not on Android, behaves the same as {@link #POSTING}.
*/
MAIN_ORDERED,
/**
* On Android, subscriber will be called in a background thread. If posting thread is not the main thread, subscriber methods
* will be called directly in the posting thread. If the posting thread is the main thread, EventBus uses a single
* background thread, that will deliver all its events sequentially. Subscribers using this mode should try to
* return quickly to avoid blocking the background thread.
*
* If not on Android, always uses a background thread.
*/
BACKGROUND,
/**
* Subscriber will be called in a separate thread. This is always independent of the posting thread and the
* main thread. Posting events never wait for subscriber methods using this mode. Subscriber methods should
* use this mode if their execution might take some time, e.g. for network access. Avoid triggering a large number
* of long-running asynchronous subscriber methods at the same time to limit the number of concurrent threads. EventBus
* uses a thread pool to efficiently reuse threads from completed asynchronous subscriber notifications.
*/
ASYNC
}
================================================
FILE: EventBus/src/org/greenrobot/eventbus/android/AndroidComponents.java
================================================
package org.greenrobot.eventbus.android;
import org.greenrobot.eventbus.Logger;
import org.greenrobot.eventbus.MainThreadSupport;
public abstract class AndroidComponents {
private static final AndroidComponents implementation;
static {
implementation = AndroidDependenciesDetector.isAndroidSDKAvailable()
? AndroidDependenciesDetector.instantiateAndroidComponents()
: null;
}
public static boolean areAvailable() {
return implementation != null;
}
public static AndroidComponents get() {
return implementation;
}
public final Logger logger;
public final MainThreadSupport defaultMainThreadSupport;
public AndroidComponents(Logger logger, MainThreadSupport defaultMainThreadSupport) {
this.logger = logger;
this.defaultMainThreadSupport = defaultMainThreadSupport;
}
}
================================================
FILE: EventBus/src/org/greenrobot/eventbus/android/AndroidDependenciesDetector.java
================================================
package org.greenrobot.eventbus.android;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@SuppressWarnings("TryWithIdenticalCatches")
public class AndroidDependenciesDetector {
public static boolean isAndroidSDKAvailable() {
try {
Class> looperClass = Class.forName("android.os.Looper");
Method getMainLooper = looperClass.getDeclaredMethod("getMainLooper");
Object mainLooper = getMainLooper.invoke(null);
return mainLooper != null;
}
catch (ClassNotFoundException ignored) {}
catch (NoSuchMethodException ignored) {}
catch (IllegalAccessException ignored) {}
catch (InvocationTargetException ignored) {}
return false;
}
private static final String ANDROID_COMPONENTS_IMPLEMENTATION_CLASS_NAME = "org.greenrobot.eventbus.android.AndroidComponentsImpl";
public static boolean areAndroidComponentsAvailable() {
try {
Class.forName(ANDROID_COMPONENTS_IMPLEMENTATION_CLASS_NAME);
return true;
}
catch (ClassNotFoundException ex) {
return false;
}
}
public static AndroidComponents instantiateAndroidComponents() {
try {
Class> impl = Class.forName(ANDROID_COMPONENTS_IMPLEMENTATION_CLASS_NAME);
return (AndroidComponents) impl.getConstructor().newInstance();
}
catch (Throwable ex) {
return null;
}
}
}
================================================
FILE: EventBus/src/org/greenrobot/eventbus/meta/AbstractSubscriberInfo.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus.meta;
import org.greenrobot.eventbus.EventBusException;
import org.greenrobot.eventbus.SubscriberMethod;
import org.greenrobot.eventbus.ThreadMode;
import java.lang.reflect.Method;
/** Base class for generated subscriber meta info classes created by annotation processing. */
public abstract class AbstractSubscriberInfo implements SubscriberInfo {
private final Class subscriberClass;
private final Class extends SubscriberInfo> superSubscriberInfoClass;
private final boolean shouldCheckSuperclass;
protected AbstractSubscriberInfo(Class subscriberClass, Class extends SubscriberInfo> superSubscriberInfoClass,
boolean shouldCheckSuperclass) {
this.subscriberClass = subscriberClass;
this.superSubscriberInfoClass = superSubscriberInfoClass;
this.shouldCheckSuperclass = shouldCheckSuperclass;
}
@Override
public Class getSubscriberClass() {
return subscriberClass;
}
@Override
public SubscriberInfo getSuperSubscriberInfo() {
if(superSubscriberInfoClass == null) {
return null;
}
try {
return superSubscriberInfoClass.newInstance();
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
@Override
public boolean shouldCheckSuperclass() {
return shouldCheckSuperclass;
}
protected SubscriberMethod createSubscriberMethod(String methodName, Class> eventType) {
return createSubscriberMethod(methodName, eventType, ThreadMode.POSTING, 0, false);
}
protected SubscriberMethod createSubscriberMethod(String methodName, Class> eventType, ThreadMode threadMode) {
return createSubscriberMethod(methodName, eventType, threadMode, 0, false);
}
protected SubscriberMethod createSubscriberMethod(String methodName, Class> eventType, ThreadMode threadMode,
int priority, boolean sticky) {
try {
Method method = subscriberClass.getDeclaredMethod(methodName, eventType);
return new SubscriberMethod(method, eventType, threadMode, priority, sticky);
} catch (NoSuchMethodException e) {
throw new EventBusException("Could not find subscriber method in " + subscriberClass +
". Maybe a missing ProGuard rule?", e);
}
}
}
================================================
FILE: EventBus/src/org/greenrobot/eventbus/meta/SimpleSubscriberInfo.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus.meta;
import org.greenrobot.eventbus.SubscriberMethod;
/**
* Uses {@link SubscriberMethodInfo} objects to create {@link org.greenrobot.eventbus.SubscriberMethod} objects on demand.
*/
public class SimpleSubscriberInfo extends AbstractSubscriberInfo {
private final SubscriberMethodInfo[] methodInfos;
public SimpleSubscriberInfo(Class subscriberClass, boolean shouldCheckSuperclass, SubscriberMethodInfo[] methodInfos) {
super(subscriberClass, null, shouldCheckSuperclass);
this.methodInfos = methodInfos;
}
@Override
public synchronized SubscriberMethod[] getSubscriberMethods() {
int length = methodInfos.length;
SubscriberMethod[] methods = new SubscriberMethod[length];
for (int i = 0; i < length; i++) {
SubscriberMethodInfo info = methodInfos[i];
methods[i] = createSubscriberMethod(info.methodName, info.eventType, info.threadMode,
info.priority, info.sticky);
}
return methods;
}
}
================================================
FILE: EventBus/src/org/greenrobot/eventbus/meta/SubscriberInfo.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus.meta;
import org.greenrobot.eventbus.SubscriberMethod;
/** Base class for generated index classes created by annotation processing. */
public interface SubscriberInfo {
Class> getSubscriberClass();
SubscriberMethod[] getSubscriberMethods();
SubscriberInfo getSuperSubscriberInfo();
boolean shouldCheckSuperclass();
}
================================================
FILE: EventBus/src/org/greenrobot/eventbus/meta/SubscriberInfoIndex.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus.meta;
/**
* Interface for generated indexes.
*/
public interface SubscriberInfoIndex {
SubscriberInfo getSubscriberInfo(Class> subscriberClass);
}
================================================
FILE: EventBus/src/org/greenrobot/eventbus/meta/SubscriberMethodInfo.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus.meta;
import org.greenrobot.eventbus.ThreadMode;
public class SubscriberMethodInfo {
final String methodName;
final ThreadMode threadMode;
final Class> eventType;
final int priority;
final boolean sticky;
public SubscriberMethodInfo(String methodName, Class> eventType, ThreadMode threadMode,
int priority, boolean sticky) {
this.methodName = methodName;
this.threadMode = threadMode;
this.eventType = eventType;
this.priority = priority;
this.sticky = sticky;
}
public SubscriberMethodInfo(String methodName, Class> eventType) {
this(methodName, eventType, ThreadMode.POSTING, 0, false);
}
public SubscriberMethodInfo(String methodName, Class> eventType, ThreadMode threadMode) {
this(methodName, eventType, threadMode, 0, false);
}
}
================================================
FILE: EventBus/src/org/greenrobot/eventbus/util/AsyncExecutor.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus.util;
import org.greenrobot.eventbus.EventBus;
import java.lang.reflect.Constructor;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.logging.Level;
/**
* Executes an {@link RunnableEx} using a thread pool. Thrown exceptions are propagated by posting failure events.
* By default, uses {@link ThrowableFailureEvent}.
*
* Set a custom event type using {@link Builder#failureEventType(Class)}.
* The failure event class must have a constructor with one parameter of type {@link Throwable}.
* If using ProGuard or R8 make sure the constructor of the failure event class is kept, it is accessed via reflection.
* E.g. add a rule like
*
* -keepclassmembers class com.example.CustomThrowableFailureEvent {
* <init>(java.lang.Throwable);
* }
*
*/
public class AsyncExecutor {
public static class Builder {
private Executor threadPool;
private Class> failureEventType;
private EventBus eventBus;
private Builder() {
}
public Builder threadPool(Executor threadPool) {
this.threadPool = threadPool;
return this;
}
public Builder failureEventType(Class> failureEventType) {
this.failureEventType = failureEventType;
return this;
}
public Builder eventBus(EventBus eventBus) {
this.eventBus = eventBus;
return this;
}
public AsyncExecutor build() {
return buildForScope(null);
}
public AsyncExecutor buildForScope(Object executionContext) {
if (eventBus == null) {
eventBus = EventBus.getDefault();
}
if (threadPool == null) {
threadPool = Executors.newCachedThreadPool();
}
if (failureEventType == null) {
failureEventType = ThrowableFailureEvent.class;
}
return new AsyncExecutor(threadPool, eventBus, failureEventType, executionContext);
}
}
/** Like {@link Runnable}, but the run method may throw an exception. */
public interface RunnableEx {
void run() throws Exception;
}
public static Builder builder() {
return new Builder();
}
public static AsyncExecutor create() {
return new Builder().build();
}
private final Executor threadPool;
private final Constructor> failureEventConstructor;
private final EventBus eventBus;
private final Object scope;
private AsyncExecutor(Executor threadPool, EventBus eventBus, Class> failureEventType, Object scope) {
this.threadPool = threadPool;
this.eventBus = eventBus;
this.scope = scope;
try {
failureEventConstructor = failureEventType.getConstructor(Throwable.class);
} catch (NoSuchMethodException e) {
throw new RuntimeException(
"Failure event class must have a constructor with one parameter of type Throwable", e);
}
}
/** Posts an failure event if the given {@link RunnableEx} throws an Exception. */
public void execute(final RunnableEx runnable) {
threadPool.execute(() -> {
try {
runnable.run();
} catch (Exception e) {
Object event;
try {
event = failureEventConstructor.newInstance(e);
} catch (Exception e1) {
eventBus.getLogger().log(Level.SEVERE, "Original exception:", e);
throw new RuntimeException("Could not create failure event", e1);
}
if (event instanceof HasExecutionScope) {
((HasExecutionScope) event).setExecutionScope(scope);
}
eventBus.post(event);
}
});
}
}
================================================
FILE: EventBus/src/org/greenrobot/eventbus/util/ExceptionToResourceMapping.java
================================================
/*
* Copyright (C) 2012-2020 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus.util;
import org.greenrobot.eventbus.Logger;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Level;
/**
* Maps throwables to texts for error dialogs. Use Config to configure the mapping.
*
* @author Markus
*/
public class ExceptionToResourceMapping {
public final Map, Integer> throwableToMsgIdMap;
public ExceptionToResourceMapping() {
throwableToMsgIdMap = new HashMap<>();
}
/** Looks at the exception and its causes trying to find an ID. */
public Integer mapThrowable(final Throwable throwable) {
Throwable throwableToCheck = throwable;
int depthToGo = 20;
while (true) {
Integer resId = mapThrowableFlat(throwableToCheck);
if (resId != null) {
return resId;
} else {
throwableToCheck = throwableToCheck.getCause();
depthToGo--;
if (depthToGo <= 0 || throwableToCheck == throwable || throwableToCheck == null) {
Logger logger = Logger.Default.get(); // No EventBus instance here
logger.log(Level.FINE, "No specific message resource ID found for " + throwable);
// return config.defaultErrorMsgId;
return null;
}
}
}
}
/** Mapping without checking the cause (done in mapThrowable). */
protected Integer mapThrowableFlat(Throwable throwable) {
Class extends Throwable> throwableClass = throwable.getClass();
Integer resId = throwableToMsgIdMap.get(throwableClass);
if (resId == null) {
Class extends Throwable> closestClass = null;
Set, Integer>> mappings = throwableToMsgIdMap.entrySet();
for (Entry, Integer> mapping : mappings) {
Class extends Throwable> candidate = mapping.getKey();
if (candidate.isAssignableFrom(throwableClass)) {
if (closestClass == null || closestClass.isAssignableFrom(candidate)) {
closestClass = candidate;
resId = mapping.getValue();
}
}
}
}
return resId;
}
public ExceptionToResourceMapping addMapping(Class extends Throwable> clazz, int msgId) {
throwableToMsgIdMap.put(clazz, msgId);
return this;
}
}
================================================
FILE: EventBus/src/org/greenrobot/eventbus/util/HasExecutionScope.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus.util;
public interface HasExecutionScope {
Object getExecutionScope();
void setExecutionScope(Object executionScope);
}
================================================
FILE: EventBus/src/org/greenrobot/eventbus/util/ThrowableFailureEvent.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus.util;
/**
* A generic failure event, which can be used by apps to propagate thrown exceptions.
* Used as default failure event by {@link AsyncExecutor}.
*/
public class ThrowableFailureEvent implements HasExecutionScope {
protected final Throwable throwable;
protected final boolean suppressErrorUi;
private Object executionContext;
public ThrowableFailureEvent(Throwable throwable) {
this.throwable = throwable;
suppressErrorUi = false;
}
/**
* @param suppressErrorUi
* true indicates to the receiver that no error UI (e.g. dialog) should now displayed.
*/
public ThrowableFailureEvent(Throwable throwable, boolean suppressErrorUi) {
this.throwable = throwable;
this.suppressErrorUi = suppressErrorUi;
}
public Throwable getThrowable() {
return throwable;
}
public boolean isSuppressErrorUi() {
return suppressErrorUi;
}
public Object getExecutionScope() {
return executionContext;
}
public void setExecutionScope(Object executionContext) {
this.executionContext = executionContext;
}
}
================================================
FILE: EventBusAnnotationProcessor/build.gradle
================================================
apply plugin: 'java'
group = rootProject.group
version = rootProject.version
java.sourceCompatibility = JavaVersion.VERSION_1_8
java.targetCompatibility = JavaVersion.VERSION_1_8
dependencies {
implementation project(':eventbus-java')
implementation 'de.greenrobot:java-common:2.3.1'
// Generates the required META-INF descriptor to make the processor incremental.
def incap = '0.2'
compileOnly "net.ltgt.gradle.incap:incap:$incap"
annotationProcessor "net.ltgt.gradle.incap:incap-processor:$incap"
}
sourceSets {
main {
java {
srcDir 'src'
}
resources {
srcDir 'res'
}
}
}
javadoc {
title = "EventBus Annotation Processor ${version} API"
options.bottom = 'Available under the Apache License, Version 2.0 - Copyright © 2015-2020 greenrobot.org . All Rights Reserved. '
}
task javadocJar(type: Jar, dependsOn: javadoc) {
archiveClassifier.set("javadoc")
from 'build/docs/javadoc'
}
task sourcesJar(type: Jar) {
archiveClassifier.set("sources")
from sourceSets.main.allSource
}
apply from: rootProject.file("gradle/publish.gradle")
// Set project-specific properties
afterEvaluate {
publishing.publications {
mavenJava(MavenPublication) {
artifactId = "eventbus-annotation-processor"
from components.java
artifact javadocJar
artifact sourcesJar
pom {
name = "EventBus Annotation Processor"
description = "Precompiler for EventBus Annotations."
packaging = "jar"
}
}
}
}
================================================
FILE: EventBusAnnotationProcessor/res/META-INF/services/javax.annotation.processing.Processor
================================================
org.greenrobot.eventbus.annotationprocessor.EventBusAnnotationProcessor
================================================
FILE: EventBusAnnotationProcessor/src/org/greenrobot/eventbus/annotationprocessor/EventBusAnnotationProcessor.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus.annotationprocessor;
import net.ltgt.gradle.incap.IncrementalAnnotationProcessor;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.io.BufferedWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Messager;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedOptions;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVariable;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;
import de.greenrobot.common.ListMap;
import static net.ltgt.gradle.incap.IncrementalAnnotationProcessorType.AGGREGATING;
/**
* Is an aggregating processor as it writes a single file, the subscriber index file,
* based on found elements with the @Subscriber annotation.
*/
@SupportedAnnotationTypes("org.greenrobot.eventbus.Subscribe")
@SupportedOptions(value = {"eventBusIndex", "verbose"})
@IncrementalAnnotationProcessor(AGGREGATING)
public class EventBusAnnotationProcessor extends AbstractProcessor {
public static final String OPTION_EVENT_BUS_INDEX = "eventBusIndex";
public static final String OPTION_VERBOSE = "verbose";
/** Found subscriber methods for a class (without superclasses). */
private final ListMap methodsByClass = new ListMap<>();
private final Set classesToSkip = new HashSet<>();
private boolean writerRoundDone;
private int round;
private boolean verbose;
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latest();
}
@Override
public boolean process(Set extends TypeElement> annotations, RoundEnvironment env) {
Messager messager = processingEnv.getMessager();
try {
String index = processingEnv.getOptions().get(OPTION_EVENT_BUS_INDEX);
if (index == null) {
messager.printMessage(Diagnostic.Kind.ERROR, "No option " + OPTION_EVENT_BUS_INDEX +
" passed to annotation processor");
return false;
}
verbose = Boolean.parseBoolean(processingEnv.getOptions().get(OPTION_VERBOSE));
int lastPeriod = index.lastIndexOf('.');
String indexPackage = lastPeriod != -1 ? index.substring(0, lastPeriod) : null;
round++;
if (verbose) {
messager.printMessage(Diagnostic.Kind.NOTE, "Processing round " + round + ", new annotations: " +
!annotations.isEmpty() + ", processingOver: " + env.processingOver());
}
if (env.processingOver()) {
if (!annotations.isEmpty()) {
messager.printMessage(Diagnostic.Kind.ERROR,
"Unexpected processing state: annotations still available after processing over");
return false;
}
}
if (annotations.isEmpty()) {
return false;
}
if (writerRoundDone) {
messager.printMessage(Diagnostic.Kind.ERROR,
"Unexpected processing state: annotations still available after writing.");
}
collectSubscribers(annotations, env, messager);
checkForSubscribersToSkip(messager, indexPackage);
if (!methodsByClass.isEmpty()) {
createInfoIndexFile(index);
} else {
messager.printMessage(Diagnostic.Kind.WARNING, "No @Subscribe annotations found");
}
writerRoundDone = true;
} catch (RuntimeException e) {
// IntelliJ does not handle exceptions nicely, so log and print a message
e.printStackTrace();
messager.printMessage(Diagnostic.Kind.ERROR, "Unexpected error in EventBusAnnotationProcessor: " + e);
}
return true;
}
private void collectSubscribers(Set extends TypeElement> annotations, RoundEnvironment env, Messager messager) {
for (TypeElement annotation : annotations) {
Set extends Element> elements = env.getElementsAnnotatedWith(annotation);
for (Element element : elements) {
if (element instanceof ExecutableElement) {
ExecutableElement method = (ExecutableElement) element;
if (checkHasNoErrors(method, messager)) {
TypeElement classElement = (TypeElement) method.getEnclosingElement();
methodsByClass.putElement(classElement, method);
}
} else {
messager.printMessage(Diagnostic.Kind.ERROR, "@Subscribe is only valid for methods", element);
}
}
}
}
private boolean checkHasNoErrors(ExecutableElement element, Messager messager) {
if (element.getModifiers().contains(Modifier.STATIC)) {
messager.printMessage(Diagnostic.Kind.ERROR, "Subscriber method must not be static", element);
return false;
}
if (!element.getModifiers().contains(Modifier.PUBLIC)) {
messager.printMessage(Diagnostic.Kind.ERROR, "Subscriber method must be public", element);
return false;
}
List extends VariableElement> parameters = ((ExecutableElement) element).getParameters();
if (parameters.size() != 1) {
messager.printMessage(Diagnostic.Kind.ERROR, "Subscriber method must have exactly 1 parameter", element);
return false;
}
return true;
}
/**
* Subscriber classes should be skipped if their class or any involved event class are not visible to the index.
*/
private void checkForSubscribersToSkip(Messager messager, String myPackage) {
for (TypeElement skipCandidate : methodsByClass.keySet()) {
TypeElement subscriberClass = skipCandidate;
while (subscriberClass != null) {
if (!isVisible(myPackage, subscriberClass)) {
boolean added = classesToSkip.add(skipCandidate);
if (added) {
String msg;
if (subscriberClass.equals(skipCandidate)) {
msg = "Falling back to reflection because class is not public";
} else {
msg = "Falling back to reflection because " + skipCandidate +
" has a non-public super class";
}
messager.printMessage(Diagnostic.Kind.NOTE, msg, subscriberClass);
}
break;
}
List methods = methodsByClass.get(subscriberClass);
if (methods != null) {
for (ExecutableElement method : methods) {
String skipReason = null;
VariableElement param = method.getParameters().get(0);
TypeMirror typeMirror = getParamTypeMirror(param, messager);
if (!(typeMirror instanceof DeclaredType) ||
!(((DeclaredType) typeMirror).asElement() instanceof TypeElement)) {
skipReason = "event type cannot be processed";
}
if (skipReason == null) {
TypeElement eventTypeElement = (TypeElement) ((DeclaredType) typeMirror).asElement();
if (!isVisible(myPackage, eventTypeElement)) {
skipReason = "event type is not public";
}
}
if (skipReason != null) {
boolean added = classesToSkip.add(skipCandidate);
if (added) {
String msg = "Falling back to reflection because " + skipReason;
if (!subscriberClass.equals(skipCandidate)) {
msg += " (found in super class for " + skipCandidate + ")";
}
messager.printMessage(Diagnostic.Kind.NOTE, msg, param);
}
break;
}
}
}
subscriberClass = getSuperclass(subscriberClass);
}
}
}
private TypeMirror getParamTypeMirror(VariableElement param, Messager messager) {
TypeMirror typeMirror = param.asType();
// Check for generic type
if (typeMirror instanceof TypeVariable) {
TypeMirror upperBound = ((TypeVariable) typeMirror).getUpperBound();
if (upperBound instanceof DeclaredType) {
if (messager != null) {
messager.printMessage(Diagnostic.Kind.NOTE, "Using upper bound type " + upperBound +
" for generic parameter", param);
}
typeMirror = upperBound;
}
}
return typeMirror;
}
private TypeElement getSuperclass(TypeElement type) {
if (type.getSuperclass().getKind() == TypeKind.DECLARED) {
TypeElement superclass = (TypeElement) processingEnv.getTypeUtils().asElement(type.getSuperclass());
String name = superclass.getQualifiedName().toString();
if (name.startsWith("java.") || name.startsWith("javax.") || name.startsWith("android.")) {
// Skip system classes, this just degrades performance
return null;
} else {
return superclass;
}
} else {
return null;
}
}
private String getClassString(TypeElement typeElement, String myPackage) {
PackageElement packageElement = getPackageElement(typeElement);
String packageString = packageElement.getQualifiedName().toString();
String className = typeElement.getQualifiedName().toString();
if (packageString != null && !packageString.isEmpty()) {
if (packageString.equals(myPackage)) {
className = cutPackage(myPackage, className);
} else if (packageString.equals("java.lang")) {
className = typeElement.getSimpleName().toString();
}
}
return className;
}
private String cutPackage(String paket, String className) {
if (className.startsWith(paket + '.')) {
// Don't use TypeElement.getSimpleName, it doesn't work for us with inner classes
return className.substring(paket.length() + 1);
} else {
// Paranoia
throw new IllegalStateException("Mismatching " + paket + " vs. " + className);
}
}
private PackageElement getPackageElement(TypeElement subscriberClass) {
Element candidate = subscriberClass.getEnclosingElement();
while (!(candidate instanceof PackageElement)) {
candidate = candidate.getEnclosingElement();
}
return (PackageElement) candidate;
}
private void writeCreateSubscriberMethods(BufferedWriter writer, List methods,
String callPrefix, String myPackage) throws IOException {
for (ExecutableElement method : methods) {
List extends VariableElement> parameters = method.getParameters();
TypeMirror paramType = getParamTypeMirror(parameters.get(0), null);
TypeElement paramElement = (TypeElement) processingEnv.getTypeUtils().asElement(paramType);
String methodName = method.getSimpleName().toString();
String eventClass = getClassString(paramElement, myPackage) + ".class";
Subscribe subscribe = method.getAnnotation(Subscribe.class);
List parts = new ArrayList<>();
parts.add(callPrefix + "(\"" + methodName + "\",");
String lineEnd = "),";
if (subscribe.priority() == 0 && !subscribe.sticky()) {
if (subscribe.threadMode() == ThreadMode.POSTING) {
parts.add(eventClass + lineEnd);
} else {
parts.add(eventClass + ",");
parts.add("ThreadMode." + subscribe.threadMode().name() + lineEnd);
}
} else {
parts.add(eventClass + ",");
parts.add("ThreadMode." + subscribe.threadMode().name() + ",");
parts.add(subscribe.priority() + ",");
parts.add(subscribe.sticky() + lineEnd);
}
writeLine(writer, 3, parts.toArray(new String[parts.size()]));
if (verbose) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Indexed @Subscribe at " +
method.getEnclosingElement().getSimpleName() + "." + methodName +
"(" + paramElement.getSimpleName() + ")");
}
}
}
private void createInfoIndexFile(String index) {
BufferedWriter writer = null;
try {
JavaFileObject sourceFile = processingEnv.getFiler().createSourceFile(index);
int period = index.lastIndexOf('.');
String myPackage = period > 0 ? index.substring(0, period) : null;
String clazz = index.substring(period + 1);
writer = new BufferedWriter(sourceFile.openWriter());
if (myPackage != null) {
writer.write("package " + myPackage + ";\n\n");
}
writer.write("import org.greenrobot.eventbus.meta.SimpleSubscriberInfo;\n");
writer.write("import org.greenrobot.eventbus.meta.SubscriberMethodInfo;\n");
writer.write("import org.greenrobot.eventbus.meta.SubscriberInfo;\n");
writer.write("import org.greenrobot.eventbus.meta.SubscriberInfoIndex;\n\n");
writer.write("import org.greenrobot.eventbus.ThreadMode;\n\n");
writer.write("import java.util.HashMap;\n");
writer.write("import java.util.Map;\n\n");
writer.write("/** This class is generated by EventBus, do not edit. */\n");
writer.write("public class " + clazz + " implements SubscriberInfoIndex {\n");
writer.write(" private static final Map, SubscriberInfo> SUBSCRIBER_INDEX;\n\n");
writer.write(" static {\n");
writer.write(" SUBSCRIBER_INDEX = new HashMap, SubscriberInfo>();\n\n");
writeIndexLines(writer, myPackage);
writer.write(" }\n\n");
writer.write(" private static void putIndex(SubscriberInfo info) {\n");
writer.write(" SUBSCRIBER_INDEX.put(info.getSubscriberClass(), info);\n");
writer.write(" }\n\n");
writer.write(" @Override\n");
writer.write(" public SubscriberInfo getSubscriberInfo(Class> subscriberClass) {\n");
writer.write(" SubscriberInfo info = SUBSCRIBER_INDEX.get(subscriberClass);\n");
writer.write(" if (info != null) {\n");
writer.write(" return info;\n");
writer.write(" } else {\n");
writer.write(" return null;\n");
writer.write(" }\n");
writer.write(" }\n");
writer.write("}\n");
} catch (IOException e) {
throw new RuntimeException("Could not write source for " + index, e);
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
//Silent
}
}
}
}
private void writeIndexLines(BufferedWriter writer, String myPackage) throws IOException {
for (TypeElement subscriberTypeElement : methodsByClass.keySet()) {
if (classesToSkip.contains(subscriberTypeElement)) {
continue;
}
String subscriberClass = getClassString(subscriberTypeElement, myPackage);
if (isVisible(myPackage, subscriberTypeElement)) {
writeLine(writer, 2,
"putIndex(new SimpleSubscriberInfo(" + subscriberClass + ".class,",
"true,", "new SubscriberMethodInfo[] {");
List methods = methodsByClass.get(subscriberTypeElement);
writeCreateSubscriberMethods(writer, methods, "new SubscriberMethodInfo", myPackage);
writer.write(" }));\n\n");
} else {
writer.write(" // Subscriber not visible to index: " + subscriberClass + "\n");
}
}
}
private boolean isVisible(String myPackage, TypeElement typeElement) {
Set modifiers = typeElement.getModifiers();
boolean visible;
if (modifiers.contains(Modifier.PUBLIC)) {
visible = true;
} else if (modifiers.contains(Modifier.PRIVATE) || modifiers.contains(Modifier.PROTECTED)) {
visible = false;
} else {
String subscriberPackage = getPackageElement(typeElement).getQualifiedName().toString();
if (myPackage == null) {
visible = subscriberPackage.length() == 0;
} else {
visible = myPackage.equals(subscriberPackage);
}
}
return visible;
}
private void writeLine(BufferedWriter writer, int indentLevel, String... parts) throws IOException {
writeLine(writer, indentLevel, 2, parts);
}
private void writeLine(BufferedWriter writer, int indentLevel, int indentLevelIncrease, String... parts)
throws IOException {
writeIndent(writer, indentLevel);
int len = indentLevel * 4;
for (int i = 0; i < parts.length; i++) {
String part = parts[i];
if (i != 0) {
if (len + part.length() > 118) {
writer.write("\n");
if (indentLevel < 12) {
indentLevel += indentLevelIncrease;
}
writeIndent(writer, indentLevel);
len = indentLevel * 4;
} else {
writer.write(" ");
}
}
writer.write(part);
len += part.length();
}
writer.write("\n");
}
private void writeIndent(BufferedWriter writer, int indentLevel) throws IOException {
for (int i = 0; i < indentLevel; i++) {
writer.write(" ");
}
}
}
================================================
FILE: EventBusPerformance/.gitignore
================================================
/bin
/gen
================================================
FILE: EventBusPerformance/AndroidManifest.xml
================================================
================================================
FILE: EventBusPerformance/build.gradle
================================================
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
// Note: IntelliJ IDEA 2021.1 only supports up to version 4.1
classpath 'com.android.tools.build:gradle:4.1.3'
}
}
apply plugin: 'com.android.application'
dependencies {
implementation project(':eventbus-android')
annotationProcessor project(':eventbus-annotation-processor')
implementation 'com.squareup:otto:1.3.8'
}
android {
compileSdkVersion _compileSdkVersion
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
res.srcDirs = ['res']
}
}
defaultConfig {
minSdkVersion 7
targetSdkVersion 26
versionCode 1
versionName "2.0.0"
javaCompileOptions {
annotationProcessorOptions {
arguments = [eventBusIndex: 'org.greenrobot.eventbusperf.MyEventBusIndex']
}
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
================================================
FILE: EventBusPerformance/proguard-project.txt
================================================
# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
================================================
FILE: EventBusPerformance/project.properties
================================================
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system edit
# "ant.properties", and override values to adapt the script to your
# project structure.
#
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
#proguard.config=${sdk.dir}\tools\proguard\proguard-android.txt:proguard-project.txt
# Project target.
target=android-17
================================================
FILE: EventBusPerformance/res/layout/activity_runtests.xml
================================================
================================================
FILE: EventBusPerformance/res/layout/activity_setuptests.xml
================================================
================================================
FILE: EventBusPerformance/res/values/strings.xml
================================================
EventBus Performance
EventBus
Event Inheritance
Ignore generated index
OttoBus
Broadcast
Local Broadcast
Events:
Subscribers:
Start
- Post Events
- Register Subscribers
- Register Subscribers, no unregister
- Register Subscribers, 1. time
- POSTING
- MAIN
- MAIN_ORDERED
- BACKGROUND
- ASYNC
Test Is \nRunning!
Cancel
Kill Process
================================================
FILE: EventBusPerformance/src/org/greenrobot/eventbusperf/Test.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbusperf;
import android.content.Context;
import java.util.concurrent.atomic.AtomicLong;
public abstract class Test {
protected final Context context;
protected final TestParams params;
public final AtomicLong eventsReceivedCount = new AtomicLong();
protected long primaryResultMicros;
protected int primaryResultCount;
protected String otherTestResults;
protected boolean canceled;
public Test(Context context, TestParams params) {
this.context = context;
this.params = params;
}
public void cancel() {
canceled = true;
}
/** prepares the test, all things which are not relevant for test results */
public abstract void prepareTest();
public abstract void runTest();
/** returns the display name of the test. e.g. EventBus */
public abstract String getDisplayName();
protected void waitForReceivedEventCount(int expectedEventCount) {
while (eventsReceivedCount.get() < expectedEventCount) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
public long getPrimaryResultMicros() {
return primaryResultMicros;
}
public double getPrimaryResultRate() {
return primaryResultCount / (primaryResultMicros / 1000000d);
}
public String getOtherTestResults() {
return otherTestResults;
}
}
================================================
FILE: EventBusPerformance/src/org/greenrobot/eventbusperf/TestEvent.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbusperf;
/** Used by otto and EventBus */
public class TestEvent {
}
================================================
FILE: EventBusPerformance/src/org/greenrobot/eventbusperf/TestFinishedEvent.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbusperf;
public class TestFinishedEvent {
public final Test test;
public final boolean isLastEvent;
public TestFinishedEvent(Test test, boolean isLastEvent) {
this.test = test;
this.isLastEvent = isLastEvent;
}
}
================================================
FILE: EventBusPerformance/src/org/greenrobot/eventbusperf/TestParams.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbusperf;
import org.greenrobot.eventbus.ThreadMode;
import java.io.Serializable;
import java.util.ArrayList;
public class TestParams implements Serializable {
private static final long serialVersionUID = -2739435088947740809L;
private int eventCount;
private int subscriberCount;
private int publisherCount;
private ThreadMode threadMode;
private boolean eventInheritance;
private boolean ignoreGeneratedIndex;
private int testNumber;
private ArrayList> testClasses;
public int getEventCount() {
return eventCount;
}
public void setEventCount(int iterations) {
this.eventCount = iterations;
}
public int getSubscriberCount() {
return subscriberCount;
}
public void setSubscriberCount(int subscriberCount) {
this.subscriberCount = subscriberCount;
}
public int getPublisherCount() {
return publisherCount;
}
public void setPublisherCount(int publisherCount) {
this.publisherCount = publisherCount;
}
public ThreadMode getThreadMode() {
return threadMode;
}
public void setThreadMode(ThreadMode threadMode) {
this.threadMode = threadMode;
}
public boolean isEventInheritance() {
return eventInheritance;
}
public void setEventInheritance(boolean eventInheritance) {
this.eventInheritance = eventInheritance;
}
public boolean isIgnoreGeneratedIndex() {
return ignoreGeneratedIndex;
}
public void setIgnoreGeneratedIndex(boolean ignoreGeneratedIndex) {
this.ignoreGeneratedIndex = ignoreGeneratedIndex;
}
public ArrayList> getTestClasses() {
return testClasses;
}
public void setTestClasses(ArrayList> testClasses) {
this.testClasses = testClasses;
}
public int getTestNumber() {
return testNumber;
}
public void setTestNumber(int testNumber) {
this.testNumber = testNumber;
}
}
================================================
FILE: EventBusPerformance/src/org/greenrobot/eventbusperf/TestRunner.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbusperf;
import android.content.Context;
import org.greenrobot.eventbus.EventBus;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;
/**
* This thread initialize all selected tests and runs them through. Also the thread skips the tests, when it is canceled
*/
public class TestRunner extends Thread {
private List tests;
private volatile boolean canceled;
private final EventBus controlBus;
public TestRunner(Context context, TestParams testParams, EventBus controlBus) {
this.controlBus = controlBus;
tests = new ArrayList();
for (Class extends Test> testClazz : testParams.getTestClasses()) {
try {
Constructor>[] constructors = testClazz.getConstructors();
Constructor extends Test> constructor = testClazz.getConstructor(Context.class, TestParams.class);
Test test = constructor.newInstance(context, testParams);
tests.add(test);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
public void run() {
int idx = 0;
for (Test test : tests) {
// Clean up and let the main thread calm down
System.gc();
try {
Thread.sleep(300);
System.gc();
Thread.sleep(300);
} catch (InterruptedException e) {
}
test.prepareTest();
if (!canceled) {
test.runTest();
}
if (!canceled) {
boolean isLastEvent = idx == tests.size() - 1;
controlBus.post(new TestFinishedEvent(test, isLastEvent));
}
idx++;
}
}
public List getTests() {
return tests;
}
public void cancel() {
canceled = true;
for (Test test : tests) {
test.cancel();
}
}
}
================================================
FILE: EventBusPerformance/src/org/greenrobot/eventbusperf/TestRunnerActivity.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbusperf;
import android.app.Activity;
import android.os.Bundle;
import android.os.Process;
import android.text.Html;
import android.view.View;
import android.widget.TextView;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
/**
* This activity gets the information from the activity before, sets up the test and starts the test. After it watchs
* after that, if a test is finished. When a test is finished, the activity appends it on the textview analyse. If all
* test are finished, it cancels the timer.
*/
public class TestRunnerActivity extends Activity {
private TestRunner testRunner;
private EventBus controlBus;
private TextView textViewResult;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_runtests);
textViewResult = findViewById(R.id.textViewResult);
controlBus = new EventBus();
controlBus.register(this);
}
@Override
protected void onResume() {
super.onResume();
if (testRunner == null) {
TestParams testParams = (TestParams) getIntent().getSerializableExtra("params");
testRunner = new TestRunner(getApplicationContext(), testParams, controlBus);
if (testParams.getTestNumber() == 1) {
textViewResult.append("Events: " + testParams.getEventCount() + "\n");
}
textViewResult.append("Subscribers: " + testParams.getSubscriberCount() + "\n\n");
testRunner.start();
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(TestFinishedEvent event) {
Test test = event.test;
String text = "" + test.getDisplayName() + " " + //
test.getPrimaryResultMicros() + " micro seconds " + //
((int) test.getPrimaryResultRate()) + "/s ";
if (test.getOtherTestResults() != null) {
text += test.getOtherTestResults();
}
text += " ---------------- ";
textViewResult.append(Html.fromHtml(text));
if (event.isLastEvent) {
findViewById(R.id.buttonCancel).setVisibility(View.GONE);
findViewById(R.id.textViewTestRunning).setVisibility(View.GONE);
findViewById(R.id.buttonKillProcess).setVisibility(View.VISIBLE);
}
}
public void onClickCancel(View view) {
// Cancel asap
if (testRunner != null) {
testRunner.cancel();
testRunner = null;
}
finish();
}
public void onClickKillProcess(View view) {
Process.killProcess(Process.myPid());
}
public void onDestroy() {
if (testRunner != null) {
testRunner.cancel();
}
controlBus.unregister(this);
super.onDestroy();
}
}
================================================
FILE: EventBusPerformance/src/org/greenrobot/eventbusperf/TestSetupActivity.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbusperf;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Spinner;
import org.greenrobot.eventbus.ThreadMode;
import java.util.ArrayList;
import org.greenrobot.eventbusperf.testsubject.PerfTestEventBus;
import org.greenrobot.eventbusperf.testsubject.PerfTestOtto;
public class TestSetupActivity extends Activity {
@SuppressWarnings("rawtypes")
static final Class[] TEST_CLASSES_EVENTBUS = {PerfTestEventBus.Post.class,//
PerfTestEventBus.RegisterOneByOne.class,//
PerfTestEventBus.RegisterAll.class, //
PerfTestEventBus.RegisterFirstTime.class};
static final Class[] TEST_CLASSES_OTTO = {PerfTestOtto.Post.class,//
PerfTestOtto.RegisterOneByOne.class,//
PerfTestOtto.RegisterAll.class, //
PerfTestOtto.RegisterFirstTime.class};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_setuptests);
Spinner spinnerRun = findViewById(R.id.spinnerTestToRun);
spinnerRun.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView> adapter, View v, int pos, long lng) {
int eventsVisibility = pos == 0 ? View.VISIBLE : View.GONE;
findViewById(R.id.relativeLayoutForEvents).setVisibility(eventsVisibility);
findViewById(R.id.spinnerThread).setVisibility(eventsVisibility);
}
public void onNothingSelected(AdapterView> arg0) {
}
});
}
public void checkEventBus(View v) {
Spinner spinnerThread = findViewById(R.id.spinnerThread);
CheckBox checkBoxEventBus = findViewById(R.id.checkBoxEventBus);
int visibility = checkBoxEventBus.isChecked() ? View.VISIBLE : View.GONE;
spinnerThread.setVisibility(visibility);
}
public void startClick(View v) {
TestParams params = new TestParams();
Spinner spinnerThread = findViewById(R.id.spinnerThread);
String threadModeStr = spinnerThread.getSelectedItem().toString();
ThreadMode threadMode = ThreadMode.valueOf(threadModeStr);
params.setThreadMode(threadMode);
params.setEventInheritance(((CheckBox) findViewById(R.id.checkBoxEventBusEventHierarchy)).isChecked());
params.setIgnoreGeneratedIndex(((CheckBox) findViewById(R.id.checkBoxEventBusIgnoreGeneratedIndex)).isChecked());
EditText editTextEvent = findViewById(R.id.editTextEvent);
params.setEventCount(Integer.parseInt(editTextEvent.getText().toString()));
EditText editTextSubscriber = findViewById(R.id.editTextSubscribe);
params.setSubscriberCount(Integer.parseInt(editTextSubscriber.getText().toString()));
Spinner spinnerTestToRun = findViewById(R.id.spinnerTestToRun);
int testPos = spinnerTestToRun.getSelectedItemPosition();
params.setTestNumber(testPos + 1);
ArrayList> testClasses = initTestClasses(testPos);
params.setTestClasses(testClasses);
Intent intent = new Intent();
intent.setClass(this, TestRunnerActivity.class);
intent.putExtra("params", params);
startActivity(intent);
}
@SuppressWarnings("unchecked")
private ArrayList> initTestClasses(int testPos) {
ArrayList> testClasses = new ArrayList>();
// the attributes are putted in the intent (eventbus, otto, broadcast, local broadcast)
final CheckBox checkBoxEventBus = findViewById(R.id.checkBoxEventBus);
final CheckBox checkBoxOtto = findViewById(R.id.checkBoxOtto);
final CheckBox checkBoxBroadcast = findViewById(R.id.checkBoxBroadcast);
final CheckBox checkBoxLocalBroadcast = findViewById(R.id.checkBoxLocalBroadcast);
if (checkBoxEventBus.isChecked()) {
testClasses.add(TEST_CLASSES_EVENTBUS[testPos]);
}
if (checkBoxOtto.isChecked()) {
testClasses.add(TEST_CLASSES_OTTO[testPos]);
}
if (checkBoxBroadcast.isChecked()) {
}
if (checkBoxLocalBroadcast.isChecked()) {
}
return testClasses;
}
}
================================================
FILE: EventBusPerformance/src/org/greenrobot/eventbusperf/testsubject/PerfTestEventBus.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbusperf.testsubject;
import android.content.Context;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import org.greenrobot.eventbusperf.MyEventBusIndex;
import org.greenrobot.eventbusperf.Test;
import org.greenrobot.eventbusperf.TestEvent;
import org.greenrobot.eventbusperf.TestParams;
public abstract class PerfTestEventBus extends Test {
private final EventBus eventBus;
private final ArrayList subscribers;
private final Class> subscriberClass;
private final int eventCount;
private final int expectedEventCount;
public PerfTestEventBus(Context context, TestParams params) {
super(context, params);
eventBus = EventBus.builder().eventInheritance(params.isEventInheritance()).addIndex(new MyEventBusIndex())
.ignoreGeneratedIndex(params.isIgnoreGeneratedIndex()).build();
subscribers = new ArrayList();
eventCount = params.getEventCount();
expectedEventCount = eventCount * params.getSubscriberCount();
subscriberClass = getSubscriberClassForThreadMode();
}
@Override
public void prepareTest() {
try {
Constructor> constructor = subscriberClass.getConstructor(PerfTestEventBus.class);
for (int i = 0; i < params.getSubscriberCount(); i++) {
Object subscriber = constructor.newInstance(this);
subscribers.add(subscriber);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private Class> getSubscriberClassForThreadMode() {
switch (params.getThreadMode()) {
case MAIN:
return SubscribeClassEventBusMain.class;
case MAIN_ORDERED:
return SubscribeClassEventBusMainOrdered.class;
case BACKGROUND:
return SubscribeClassEventBusBackground.class;
case ASYNC:
return SubscriberClassEventBusAsync.class;
case POSTING:
return SubscribeClassEventBusDefault.class;
default:
throw new RuntimeException("Unknown: " + params.getThreadMode());
}
}
private static String getDisplayModifier(TestParams params) {
String inheritance = params.isEventInheritance() ? "" : ", no event inheritance";
String ignoreIndex = params.isIgnoreGeneratedIndex() ? ", ignore index" : "";
return inheritance + ignoreIndex;
}
public static class Post extends PerfTestEventBus {
public Post(Context context, TestParams params) {
super(context, params);
}
@Override
public void prepareTest() {
super.prepareTest();
super.registerSubscribers();
}
public void runTest() {
TestEvent event = new TestEvent();
long timeStart = System.nanoTime();
for (int i = 0; i < super.eventCount; i++) {
super.eventBus.post(event);
if (canceled) {
break;
}
}
long timeAfterPosting = System.nanoTime();
waitForReceivedEventCount(super.expectedEventCount);
long timeAllReceived = System.nanoTime();
primaryResultMicros = (timeAfterPosting - timeStart) / 1000;
primaryResultCount = super.expectedEventCount;
long deliveredMicros = (timeAllReceived - timeStart) / 1000;
int deliveryRate = (int) (primaryResultCount / (deliveredMicros / 1000000d));
otherTestResults = "Post and delivery time: " + deliveredMicros + " micros " + //
"Post and delivery rate: " + deliveryRate + "/s";
}
@Override
public String getDisplayName() {
return "EventBus Post Events, " + params.getThreadMode() + getDisplayModifier(params);
}
}
public static class RegisterAll extends PerfTestEventBus {
public RegisterAll(Context context, TestParams params) {
super(context, params);
}
public void runTest() {
super.registerUnregisterOneSubscribers();
long timeNanos = super.registerSubscribers();
primaryResultMicros = timeNanos / 1000;
primaryResultCount = params.getSubscriberCount();
}
@Override
public String getDisplayName() {
return "EventBus Register, no unregister" + getDisplayModifier(params);
}
}
public static class RegisterOneByOne extends PerfTestEventBus {
protected Method clearCachesMethod;
public RegisterOneByOne(Context context, TestParams params) {
super(context, params);
}
public void runTest() {
long time = 0;
if (clearCachesMethod == null) {
// Skip first registration unless just the first registration is tested
super.registerUnregisterOneSubscribers();
}
for (Object subscriber : super.subscribers) {
if (clearCachesMethod != null) {
try {
clearCachesMethod.invoke(null);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
long beforeRegister = System.nanoTime();
super.eventBus.register(subscriber);
long afterRegister = System.nanoTime();
long end = System.nanoTime();
long timeMeasureOverhead = (end - afterRegister) * 2;
long timeRegister = end - beforeRegister - timeMeasureOverhead;
time += timeRegister;
super.eventBus.unregister(subscriber);
if (canceled) {
return;
}
}
primaryResultMicros = time / 1000;
primaryResultCount = params.getSubscriberCount();
}
@Override
public String getDisplayName() {
return "EventBus Register" + getDisplayModifier(params);
}
}
public static class RegisterFirstTime extends RegisterOneByOne {
public RegisterFirstTime(Context context, TestParams params) {
super(context, params);
try {
Class> clazz = Class.forName("org.greenrobot.eventbus.SubscriberMethodFinder");
clearCachesMethod = clazz.getDeclaredMethod("clearCaches");
clearCachesMethod.setAccessible(true);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public String getDisplayName() {
return "EventBus Register, first time"+ getDisplayModifier(params);
}
}
public class SubscribeClassEventBusMain {
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(TestEvent event) {
eventsReceivedCount.incrementAndGet();
}
public void dummy() {
}
public void dummy2() {
}
public void dummy3() {
}
public void dummy4() {
}
public void dummy5() {
}
}
public class SubscribeClassEventBusMainOrdered {
@Subscribe(threadMode = ThreadMode.MAIN_ORDERED)
public void onEvent(TestEvent event) {
eventsReceivedCount.incrementAndGet();
}
public void dummy() {
}
public void dummy2() {
}
public void dummy3() {
}
public void dummy4() {
}
public void dummy5() {
}
}
public class SubscribeClassEventBusBackground {
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onEventBackgroundThread(TestEvent event) {
eventsReceivedCount.incrementAndGet();
}
public void dummy() {
}
public void dummy2() {
}
public void dummy3() {
}
public void dummy4() {
}
public void dummy5() {
}
}
public class SubscriberClassEventBusAsync {
@Subscribe(threadMode = ThreadMode.ASYNC)
public void onEventAsync(TestEvent event) {
eventsReceivedCount.incrementAndGet();
}
public void dummy() {
}
public void dummy2() {
}
public void dummy3() {
}
public void dummy4() {
}
public void dummy5() {
}
}
private long registerSubscribers() {
long time = 0;
for (Object subscriber : subscribers) {
long timeStart = System.nanoTime();
eventBus.register(subscriber);
long timeEnd = System.nanoTime();
time += timeEnd - timeStart;
if (canceled) {
return 0;
}
}
return time;
}
private void registerUnregisterOneSubscribers() {
if (!subscribers.isEmpty()) {
Object subscriber = subscribers.get(0);
eventBus.register(subscriber);
eventBus.unregister(subscriber);
}
}
}
================================================
FILE: EventBusPerformance/src/org/greenrobot/eventbusperf/testsubject/PerfTestOtto.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbusperf.testsubject;
import android.app.Activity;
import android.content.Context;
import android.os.Looper;
import com.squareup.otto.Bus;
import com.squareup.otto.Subscribe;
import com.squareup.otto.ThreadEnforcer;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;
import org.greenrobot.eventbusperf.Test;
import org.greenrobot.eventbusperf.TestEvent;
import org.greenrobot.eventbusperf.TestParams;
public abstract class PerfTestOtto extends Test {
private final Bus eventBus;
private final ArrayList subscribers;
private final Class> subscriberClass;
private final int eventCount;
private final int expectedEventCount;
public PerfTestOtto(Context context, TestParams params) {
super(context, params);
eventBus = new Bus(ThreadEnforcer.ANY);
subscribers = new ArrayList();
eventCount = params.getEventCount();
expectedEventCount = eventCount * params.getSubscriberCount();
subscriberClass = Subscriber.class;
}
@Override
public void prepareTest() {
Looper.prepare();
try {
Constructor> constructor = subscriberClass.getConstructor(PerfTestOtto.class);
for (int i = 0; i < params.getSubscriberCount(); i++) {
Object subscriber = constructor.newInstance(this);
subscribers.add(subscriber);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static class Post extends PerfTestOtto {
public Post(Context context, TestParams params) {
super(context, params);
}
@Override
public void prepareTest() {
super.prepareTest();
super.registerSubscribers();
}
public void runTest() {
TestEvent event = new TestEvent();
long timeStart = System.nanoTime();
for (int i = 0; i < super.eventCount; i++) {
super.eventBus.post(event);
if (canceled) {
break;
}
}
long timeAfterPosting = System.nanoTime();
waitForReceivedEventCount(super.expectedEventCount);
primaryResultMicros = (timeAfterPosting - timeStart) / 1000;
primaryResultCount = super.expectedEventCount;
}
@Override
public String getDisplayName() {
return "Otto Post Events";
}
}
public static class RegisterAll extends PerfTestOtto {
public RegisterAll(Context context, TestParams params) {
super(context, params);
}
public void runTest() {
super.registerUnregisterOneSubscribers();
long timeNanos = super.registerSubscribers();
primaryResultMicros = timeNanos / 1000;
primaryResultCount = params.getSubscriberCount();
}
@Override
public String getDisplayName() {
return "Otto Register, no unregister";
}
}
public static class RegisterOneByOne extends PerfTestOtto {
protected Field cacheField;
public RegisterOneByOne(Context context, TestParams params) {
super(context, params);
}
@SuppressWarnings("rawtypes")
public void runTest() {
long time = 0;
if (cacheField == null) {
// Skip first registration unless just the first registration is tested
super.registerUnregisterOneSubscribers();
}
for (Object subscriber : super.subscribers) {
if (cacheField != null) {
try {
cacheField.set(null, new ConcurrentHashMap());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
long beforeRegister = System.nanoTime();
super.eventBus.register(subscriber);
long afterRegister = System.nanoTime();
long end = System.nanoTime();
long timeMeasureOverhead = (end - afterRegister) * 2;
long timeRegister = end - beforeRegister - timeMeasureOverhead;
time += timeRegister;
super.eventBus.unregister(subscriber);
if (canceled) {
return;
}
}
primaryResultMicros = time / 1000;
primaryResultCount = params.getSubscriberCount();
}
@Override
public String getDisplayName() {
return "Otto Register";
}
}
public static class RegisterFirstTime extends RegisterOneByOne {
public RegisterFirstTime(Context context, TestParams params) {
super(context, params);
try {
Class> clazz = Class.forName("com.squareup.otto.AnnotatedHandlerFinder");
cacheField = clazz.getDeclaredField("SUBSCRIBERS_CACHE");
cacheField.setAccessible(true);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public String getDisplayName() {
return "Otto Register, first time";
}
}
public class Subscriber extends Activity {
public Subscriber() {
}
@Subscribe
public void onEvent(TestEvent event) {
eventsReceivedCount.incrementAndGet();
}
public void dummy() {
}
public void dummy2() {
}
public void dummy3() {
}
public void dummy4() {
}
public void dummy5() {
}
}
private long registerSubscribers() {
long time = 0;
for (Object subscriber : subscribers) {
long timeStart = System.nanoTime();
eventBus.register(subscriber);
long timeEnd = System.nanoTime();
time += timeEnd - timeStart;
if (canceled) {
return 0;
}
}
return time;
}
private void registerUnregisterOneSubscribers() {
if (!subscribers.isEmpty()) {
Object subscriber = subscribers.get(0);
eventBus.register(subscriber);
eventBus.unregister(subscriber);
}
}
}
================================================
FILE: EventBusPerformance/src/org/greenrobot/eventbusperf/testsubject/SubscribeClassEventBusDefault.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbusperf.testsubject;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbusperf.TestEvent;
public class SubscribeClassEventBusDefault {
private PerfTestEventBus perfTestEventBus;
public SubscribeClassEventBusDefault(PerfTestEventBus perfTestEventBus) {
this.perfTestEventBus = perfTestEventBus;
}
@Subscribe
public void onEvent(TestEvent event) {
perfTestEventBus.eventsReceivedCount.incrementAndGet();
}
public void dummy() {
}
public void dummy2() {
}
public void dummy3() {
}
public void dummy4() {
}
public void dummy5() {
}
}
================================================
FILE: EventBusTest/AndroidManifest.xml
================================================
================================================
FILE: EventBusTest/build.gradle
================================================
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
// Note: IntelliJ IDEA 2021.1 only supports up to version 4.1
classpath 'com.android.tools.build:gradle:4.1.3'
}
}
apply plugin: 'com.android.application'
dependencies {
androidTestImplementation project(':eventbus-android')
androidTestImplementation project(':EventBusTestJava')
androidTestAnnotationProcessor project(':eventbus-annotation-processor')
// Trying to repro bug:
// androidTestAnnotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.1.0'
implementation fileTree(dir: 'libs', include: '*.jar')
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test:rules:1.0.2'
}
android {
compileSdkVersion _compileSdkVersion
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
}
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
}
androidTest {
java.srcDirs = ['src']
}
}
defaultConfig {
minSdkVersion 9
targetSdkVersion 26
versionCode 1
versionName "1.0"
testApplicationId "de.greenrobot.event.test"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
javaCompileOptions {
annotationProcessorOptions {
arguments = [ eventBusIndex : 'org.greenrobot.eventbus.EventBusTestsIndex' ]
}
}
}
useLibrary 'android.test.base'
lintOptions {
// To see problems right away, also nice for Travis CI
textOutput 'stdout'
// TODO FIXME: Travis only error
abortOnError false
}
}
================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/AbstractAndroidEventBusTest.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus;
import android.annotation.SuppressLint;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Before;
import org.junit.runner.RunWith;
import static org.junit.Assert.assertFalse;
/**
* @author Markus Junginger, greenrobot
*/
@RunWith(AndroidJUnit4.class)
public abstract class AbstractAndroidEventBusTest extends AbstractEventBusTest {
private EventPostHandler mainPoster;
public AbstractAndroidEventBusTest() {
this(false);
}
public AbstractAndroidEventBusTest(boolean collectEventsReceived) {
super(collectEventsReceived);
}
@Before
public void setUpAndroid() throws Exception {
mainPoster = new EventPostHandler(Looper.getMainLooper());
assertFalse(Looper.getMainLooper().getThread().equals(Thread.currentThread()));
}
protected void postInMainThread(Object event) {
mainPoster.post(event);
}
@SuppressLint("HandlerLeak")
class EventPostHandler extends Handler {
public EventPostHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
eventBus.post(msg.obj);
}
void post(Object event) {
sendMessage(obtainMessage(0, event));
}
}
}
================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/AndroidComponentsAvailabilityTest.java
================================================
package org.greenrobot.eventbus;
import org.greenrobot.eventbus.android.AndroidComponents;
import org.junit.Test;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
public class AndroidComponentsAvailabilityTest {
@Test
public void shouldBeAvailable() {
assertTrue(AndroidComponents.areAvailable());
assertNotNull(AndroidComponents.get());
}
}
================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/ClassMapPerfTest.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Map;
/**
* Just to verify testHashMapClassObject is fastest. Ignore this test.
*/
public class ClassMapPerfTest /* extends TestCase */ {
static final int COUNT = 10000000;
static final Class CLAZZ = ClassMapPerfTest.class;
public void testHashMapClassObject() {
Map map = new HashMap();
for (int i = 0; i < COUNT; i++) {
Class oldValue = map.put(CLAZZ, CLAZZ);
Class value = map.get(CLAZZ);
}
}
public void testIdentityHashMapClassObject() {
Map map = new IdentityHashMap();
for (int i = 0; i < COUNT; i++) {
Class oldValue = map.put(CLAZZ, CLAZZ);
Class value = map.get(CLAZZ);
}
}
public void testHashMapClassName() {
Map map = new HashMap();
for (int i = 0; i < COUNT; i++) {
Class oldValue = map.put(CLAZZ.getName(), CLAZZ);
Class value = map.get(CLAZZ.getName());
}
}
}
================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidActivityTest.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus;
import android.app.Activity;
import android.support.test.annotation.UiThreadTest;
import android.support.test.rule.UiThreadTestRule;
import android.util.Log;
import org.junit.Rule;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
/**
* @author Markus Junginger, greenrobot
*/
// Do not extend from AbstractAndroidEventBusTest, because it asserts test may not be in main thread
public class EventBusAndroidActivityTest extends AbstractEventBusTest {
public static class WithIndex extends EventBusBasicTest {
@Test
public void dummy() {
}
}
@Rule
public final UiThreadTestRule uiThreadTestRule = new UiThreadTestRule();
@Test
@UiThreadTest
public void testRegisterAndPost() {
// Use an activity to test real life performance
TestActivity testActivity = new TestActivity();
String event = "Hello";
long start = System.currentTimeMillis();
eventBus.register(testActivity);
long time = System.currentTimeMillis() - start;
Log.d(EventBus.TAG, "Registered in " + time + "ms");
eventBus.post(event);
assertEquals(event, testActivity.lastStringEvent);
}
public static class TestActivity extends Activity {
public String lastStringEvent;
@Subscribe
public void onEvent(String event) {
lastStringEvent = event;
}
}
}
================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidCancelEventDeliveryTest.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus;
import org.junit.Test;
import org.junit.runner.RunWith;
import android.support.test.runner.AndroidJUnit4;
import android.test.UiThreadTest;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@RunWith(AndroidJUnit4.class)
public class EventBusAndroidCancelEventDeliveryTest extends EventBusCancelEventDeliveryTest {
@UiThreadTest
@Test
public void testCancelInMainThread() {
SubscriberMainThread subscriber = new SubscriberMainThread();
eventBus.register(subscriber);
eventBus.post("42");
awaitLatch(subscriber.done, 10);
assertEquals(0, eventCount.intValue());
assertNotNull(failed);
}
}
================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidMultithreadedTest.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus;
import org.junit.Test;
import org.junit.runner.RunWith;
import android.os.Looper;
import android.support.test.runner.AndroidJUnit4;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
@RunWith(AndroidJUnit4.class)
public class EventBusAndroidMultithreadedTest extends EventBusMultithreadedTest {
@Test
public void testSubscribeUnSubscribeAndPostMixedEventType() throws InterruptedException {
List threads = new ArrayList();
// Debug.startMethodTracing("testSubscribeUnSubscribeAndPostMixedEventType");
for (int i = 0; i < 5; i++) {
SubscribeUnsubscribeThread thread = new SubscribeUnsubscribeThread();
thread.start();
threads.add(thread);
}
// This test takes a bit longer, so just use fraction the regular count
runThreadsMixedEventType(COUNT / 4, 5);
for (SubscribeUnsubscribeThread thread : threads) {
thread.shutdown();
}
for (SubscribeUnsubscribeThread thread : threads) {
thread.join();
}
// Debug.stopMethodTracing();
}
public class SubscribeUnsubscribeThread extends Thread {
boolean running = true;
public void shutdown() {
running = false;
}
@Override
public void run() {
try {
while (running) {
eventBus.register(this);
double random = Math.random();
if (random > 0.6d) {
Thread.sleep(0, (int) (1000000 * Math.random()));
} else if (random > 0.3d) {
Thread.yield();
}
eventBus.unregister(this);
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(String event) {
assertSame(Looper.getMainLooper(), Looper.myLooper());
}
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onEventBackgroundThread(Integer event) {
assertNotSame(Looper.getMainLooper(), Looper.myLooper());
}
@Subscribe
public void onEvent(Object event) {
assertNotSame(Looper.getMainLooper(), Looper.myLooper());
}
@Subscribe(threadMode = ThreadMode.ASYNC)
public void onEventAsync(Object event) {
assertNotSame(Looper.getMainLooper(), Looper.myLooper());
}
}
}
================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidOrderTest.java
================================================
package org.greenrobot.eventbus;
import android.os.Handler;
import android.os.Looper;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class EventBusAndroidOrderTest extends AbstractAndroidEventBusTest {
private TestBackgroundPoster backgroundPoster;
private Handler handler;
@Before
public void setUp() throws Exception {
handler = new Handler(Looper.getMainLooper());
backgroundPoster = new TestBackgroundPoster(eventBus);
backgroundPoster.start();
}
@After
public void tearDown() throws Exception {
backgroundPoster.shutdown();
backgroundPoster.join();
}
@Test
public void backgroundAndMainUnordered() {
eventBus.register(this);
handler.post(new Runnable() {
@Override
public void run() {
// post from non-main thread
backgroundPoster.post("non-main");
// post from main thread
eventBus.post("main");
}
});
waitForEventCount(2, 1000);
// observe that event from *main* thread is posted FIRST
// NOT in posting order
assertEquals("non-main", lastEvent);
}
@Test
public void backgroundAndMainOrdered() {
eventBus.register(this);
handler.post(new Runnable() {
@Override
public void run() {
// post from non-main thread
backgroundPoster.post(new OrderedEvent("non-main"));
// post from main thread
eventBus.post(new OrderedEvent("main"));
}
});
waitForEventCount(2, 1000);
// observe that event from *main* thread is posted LAST
// IN posting order
assertEquals("main", ((OrderedEvent) lastEvent).thread);
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent(String event) {
trackEvent(event);
}
@Subscribe(threadMode = ThreadMode.MAIN_ORDERED)
public void onEvent(OrderedEvent event) {
trackEvent(event);
}
static class OrderedEvent {
String thread;
OrderedEvent(String thread) {
this.thread = thread;
}
}
}
================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/EventBusBackgroundThreadTest.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus;
import android.os.Looper;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
/**
* @author Markus Junginger, greenrobot
*/
public class EventBusBackgroundThreadTest extends AbstractAndroidEventBusTest {
@Test
public void testPostInCurrentThread() throws InterruptedException {
eventBus.register(this);
eventBus.post("Hello");
waitForEventCount(1, 1000);
assertEquals("Hello", lastEvent);
assertEquals(Thread.currentThread(), lastThread);
}
@Test
public void testPostFromMain() throws InterruptedException {
eventBus.register(this);
postInMainThread("Hello");
waitForEventCount(1, 1000);
assertEquals("Hello", lastEvent);
assertFalse(lastThread.equals(Thread.currentThread()));
assertFalse(lastThread.equals(Looper.getMainLooper().getThread()));
}
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onEventBackgroundThread(String event) {
trackEvent(event);
}
}
================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/EventBusMainThreadRacingTest.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus;
import android.os.Handler;
import android.os.Looper;
import org.junit.Test;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
/**
* @author Markus Junginger, greenrobot
*/
public class EventBusMainThreadRacingTest extends AbstractAndroidEventBusTest {
private static final int ITERATIONS = LONG_TESTS ? 100000 : 1000;
protected boolean unregistered;
private CountDownLatch startLatch;
private volatile RuntimeException failed;
@Test
public void testRacingThreads() throws InterruptedException {
Runnable register = new Runnable() {
@Override
public void run() {
eventBus.register(EventBusMainThreadRacingTest.this);
unregistered = false;
}
};
Runnable unregister = new Runnable() {
@Override
public void run() {
eventBus.unregister(EventBusMainThreadRacingTest.this);
unregistered = true;
}
};
startLatch = new CountDownLatch(2);
BackgroundPoster backgroundPoster = new BackgroundPoster();
backgroundPoster.start();
try {
Handler handler = new Handler(Looper.getMainLooper());
Random random = new Random();
countDownAndAwaitLatch(startLatch, 10);
for (int i = 0; i < ITERATIONS; i++) {
handler.post(register);
Thread.sleep(0, random.nextInt(300)); // Sleep just some nanoseconds, timing is crucial here
handler.post(unregister);
if (failed != null) {
throw new RuntimeException("Failed in iteration " + i, failed);
}
// Don't let the queue grow to avoid out-of-memory scenarios
waitForHandler(handler);
}
} finally {
backgroundPoster.running = false;
backgroundPoster.join();
}
}
protected void waitForHandler(Handler handler) {
final CountDownLatch doneLatch = new CountDownLatch(1);
handler.post(new Runnable() {
@Override
public void run() {
doneLatch.countDown();
}
});
awaitLatch(doneLatch, 10);
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(String event) {
trackEvent(event);
if (unregistered) {
failed = new RuntimeException("Main thread event delivered while unregistered on received event #"
+ eventCount);
}
}
class BackgroundPoster extends Thread {
volatile boolean running = true;
public BackgroundPoster() {
super("BackgroundPoster");
}
@Override
public void run() {
countDownAndAwaitLatch(startLatch, 10);
while (running) {
eventBus.post("Posted in background");
if (Math.random() > 0.9f) {
// Single cores would take very long without yielding
Thread.yield();
}
}
}
}
}
================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/EventBusMainThreadTest.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus;
import android.os.Looper;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
/**
* @author Markus Junginger, greenrobot
*/
public class EventBusMainThreadTest extends AbstractAndroidEventBusTest {
@Test
public void testPost() throws InterruptedException {
eventBus.register(this);
eventBus.post("Hello");
waitForEventCount(1, 1000);
assertEquals("Hello", lastEvent);
assertEquals(Looper.getMainLooper().getThread(), lastThread);
}
@Test
public void testPostInBackgroundThread() throws InterruptedException {
TestBackgroundPoster backgroundPoster = new TestBackgroundPoster(eventBus);
backgroundPoster.start();
eventBus.register(this);
backgroundPoster.post("Hello");
waitForEventCount(1, 1000);
assertEquals("Hello", lastEvent);
assertEquals(Looper.getMainLooper().getThread(), lastThread);
backgroundPoster.shutdown();
backgroundPoster.join();
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(String event) {
trackEvent(event);
}
}
================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/EventBusMethodModifiersTest.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus;
import android.os.Looper;
import org.junit.Test;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
/**
* @author Markus Junginger, greenrobot
*/
public class EventBusMethodModifiersTest extends AbstractAndroidEventBusTest {
@Test
public void testRegisterForEventTypeAndPost() throws InterruptedException {
eventBus.register(this);
String event = "Hello";
eventBus.post(event);
waitForEventCount(4, 1000);
}
@Subscribe
public void onEvent(String event) {
trackEvent(event);
assertNotSame(Looper.getMainLooper(), Looper.myLooper());
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(String event) {
trackEvent(event);
assertSame(Looper.getMainLooper(), Looper.myLooper());
}
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onEventBackgroundThread(String event) {
trackEvent(event);
assertNotSame(Looper.getMainLooper(), Looper.myLooper());
}
@Subscribe(threadMode = ThreadMode.ASYNC)
public void onEventAsync(String event) {
trackEvent(event);
assertNotSame(Looper.getMainLooper(), Looper.myLooper());
}
}
================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/TestBackgroundPoster.java
================================================
package org.greenrobot.eventbus;
import java.util.ArrayList;
import java.util.List;
public class TestBackgroundPoster extends Thread {
private final EventBus eventBus;
volatile boolean running = true;
private final List eventQ = new ArrayList<>();
private final List eventsDone = new ArrayList<>();
TestBackgroundPoster(EventBus eventBus) {
super("BackgroundPoster");
this.eventBus = eventBus;
}
@Override
public void run() {
while (running) {
Object event = pollEvent();
if (event != null) {
eventBus.post(event);
synchronized (eventsDone) {
eventsDone.add(event);
eventsDone.notifyAll();
}
}
}
}
private synchronized Object pollEvent() {
Object event = null;
synchronized (eventQ) {
if (eventQ.isEmpty()) {
try {
eventQ.wait(1000);
} catch (InterruptedException ignored) {
}
}
if(!eventQ.isEmpty()) {
event = eventQ.remove(0);
}
}
return event;
}
void shutdown() {
running = false;
synchronized (eventQ) {
eventQ.notifyAll();
}
}
void post(Object event) {
synchronized (eventQ) {
eventQ.add(event);
eventQ.notifyAll();
}
synchronized (eventsDone) {
while (!eventsDone.remove(event)) {
try {
eventsDone.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
}
================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusAndroidOrderTestWithIndex.java
================================================
package org.greenrobot.eventbus.indexed;
import org.greenrobot.eventbus.EventBusAndroidOrderTest;
public class EventBusAndroidOrderTestWithIndex extends EventBusAndroidOrderTest {
@Override
public void setUp() throws Exception {
eventBus = Indexed.build();
super.setUp();
}
}
================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusBackgroundThreadTestWithIndex.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus.indexed;
import org.greenrobot.eventbus.EventBusBackgroundThreadTest;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertTrue;
public class EventBusBackgroundThreadTestWithIndex extends EventBusBackgroundThreadTest {
@Before
public void overwriteEventBus() throws Exception {
eventBus = Indexed.build();
}
@Test
public void testIndex() {
assertTrue(eventBus.toString().contains("indexCount=2"));
}
}
================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusBasicTestWithIndex.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus.indexed;
import org.greenrobot.eventbus.EventBusBasicTest;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertTrue;
public class EventBusBasicTestWithIndex extends EventBusBasicTest {
@Before
public void overwriteEventBus() throws Exception {
eventBus = Indexed.build();
}
@Test
public void testIndex() {
assertTrue(eventBus.toString().contains("indexCount=2"));
}
}
================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusCancelEventDeliveryTestWithIndex.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus.indexed;
import org.greenrobot.eventbus.EventBusCancelEventDeliveryTest;
import org.junit.Before;
public class EventBusCancelEventDeliveryTestWithIndex extends EventBusCancelEventDeliveryTest {
@Before
public void overwriteEventBus() throws Exception {
eventBus = Indexed.build();
}
}
================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusFallbackToReflectionTestWithIndex.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus.indexed;
import org.junit.Before;
import org.greenrobot.eventbus.EventBusFallbackToReflectionTest;
public class EventBusFallbackToReflectionTestWithIndex extends EventBusFallbackToReflectionTest {
@Before
public void overwriteEventBus() throws Exception {
eventBus = Indexed.build();
}
}
================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusGenericsTestWithIndex.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus.indexed;
import org.junit.Before;
import org.greenrobot.eventbus.EventBusGenericsTest;
public class EventBusGenericsTestWithIndex extends EventBusGenericsTest {
@Before
public void overwriteEventBus() throws Exception {
eventBus = Indexed.build();
}
}
================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusInheritanceDisabledTestWithIndex.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus.indexed;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.EventBusTestsIndex;
import org.junit.Before;
import org.greenrobot.eventbus.EventBusInheritanceDisabledTest;
public class EventBusInheritanceDisabledTestWithIndex extends EventBusInheritanceDisabledTest {
@Before
public void setUp() throws Exception {
eventBus = EventBus.builder().eventInheritance(false).addIndex(new EventBusTestsIndex()).build();
}
}
================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusInheritanceTestWithIndex.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus.indexed;
import org.greenrobot.eventbus.EventBusInheritanceTest;
import org.junit.Before;
public class EventBusInheritanceTestWithIndex extends EventBusInheritanceTest {
@Before
public void overwriteEventBus() throws Exception {
eventBus = Indexed.build();
}
}
================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusMainThreadRacingTestWithIndex.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus.indexed;
import org.junit.Before;
import org.greenrobot.eventbus.EventBusMainThreadRacingTest;
public class EventBusMainThreadRacingTestWithIndex extends EventBusMainThreadRacingTest {
@Before
public void overwriteEventBus() throws Exception {
eventBus = Indexed.build();
}
}
================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusMainThreadTestWithIndex.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus.indexed;
import org.junit.Before;
import org.greenrobot.eventbus.EventBusMainThreadTest;
public class EventBusMainThreadTestWithIndex extends EventBusMainThreadTest {
@Before
public void overwriteEventBus() throws Exception {
eventBus = Indexed.build();
}
}
================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusMethodModifiersTestWithIndex.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus.indexed;
import org.greenrobot.eventbus.EventBusMethodModifiersTest;
import org.junit.Before;
public class EventBusMethodModifiersTestWithIndex extends EventBusMethodModifiersTest {
@Before
public void overwriteEventBus() throws Exception {
eventBus = Indexed.build();
}
}
================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusMultithreadedTestWithIndex.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus.indexed;
import org.greenrobot.eventbus.EventBusMultithreadedTest;
import org.junit.Before;
public class EventBusMultithreadedTestWithIndex extends EventBusMultithreadedTest {
@Before
public void overwriteEventBus() throws Exception {
eventBus = Indexed.build();
}
}
================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusNoSubscriberEventTestWithIndex.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus.indexed;
import org.greenrobot.eventbus.EventBusNoSubscriberEventTest;
import org.junit.Before;
public class EventBusNoSubscriberEventTestWithIndex extends EventBusNoSubscriberEventTest {
@Before
public void overwriteEventBus() throws Exception {
eventBus = Indexed.build();
}
}
================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusOrderedSubscriptionsTestWithIndex.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus.indexed;
import org.greenrobot.eventbus.EventBusOrderedSubscriptionsTest;
import org.junit.Before;
public class EventBusOrderedSubscriptionsTestWithIndex extends EventBusOrderedSubscriptionsTest {
@Before
public void overwriteEventBus() throws Exception {
eventBus = Indexed.build();
}
}
================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusRegistrationRacingTestWithIndex.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus.indexed;
import org.junit.Before;
import org.greenrobot.eventbus.EventBusRegistrationRacingTest;
public class EventBusRegistrationRacingTestWithIndex extends EventBusRegistrationRacingTest {
@Before
public void overwriteEventBus() throws Exception {
eventBus = Indexed.build();
}
}
================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusStickyEventTestWithIndex.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus.indexed;
import org.greenrobot.eventbus.EventBusStickyEventTest;
import org.junit.Before;
public class EventBusStickyEventTestWithIndex extends EventBusStickyEventTest {
@Before
public void overwriteEventBus() throws Exception {
eventBus = Indexed.build();
}
}
================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusSubscriberExceptionTestWithIndex.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus.indexed;
import org.junit.Before;
import org.greenrobot.eventbus.EventBusSubscriberExceptionTest;
public class EventBusSubscriberExceptionTestWithIndex extends EventBusSubscriberExceptionTest {
@Before
public void overwriteEventBus() throws Exception {
eventBus = Indexed.build();
}
}
================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusSubscriberInJarTestWithIndex.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus.indexed;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.EventBusSubscriberInJarTest;
import org.greenrobot.eventbus.InJarIndex;
import org.junit.Before;
public class EventBusSubscriberInJarTestWithIndex extends EventBusSubscriberInJarTest {
@Before
public void overwriteEventBus() throws Exception {
eventBus = EventBus.builder().addIndex(new InJarIndex()).build();
}
}
================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/Indexed.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus.indexed;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.EventBusJavaTestsIndex;
import org.greenrobot.eventbus.EventBusTestsIndex;
public class Indexed {
static EventBus build() {
return EventBus.builder()
.addIndex(new EventBusTestsIndex())
.addIndex(new EventBusJavaTestsIndex())
.build();
}
}
================================================
FILE: EventBusTestJava/build.gradle
================================================
apply plugin: "java-library"
java.sourceCompatibility = JavaVersion.VERSION_1_8
java.targetCompatibility = JavaVersion.VERSION_1_8
// we have tests in the main source set so they can be shared with the Android test module
// to make Gradle pick them up, add the dir to the test source set
sourceSets {
test {
java {
srcDirs += ["src/main/java"]
}
}
}
dependencies {
implementation fileTree(dir: "libs", include: "*.jar")
implementation(project(":eventbus-java"))
annotationProcessor project(":eventbus-annotation-processor")
implementation "junit:junit:4.13.2"
}
tasks.withType(JavaCompile) {
options.compilerArgs += [ "-AeventBusIndex=org.greenrobot.eventbus.EventBusJavaTestsIndex" ]
}
================================================
FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/AbstractEventBusTest.java
================================================
/*
* Copyright (C) 2012-2017 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus;
import org.junit.Before;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* @author Markus Junginger, greenrobot
*/
public abstract class AbstractEventBusTest {
/** Activates long(er) running tests e.g. testing multi-threading more thoroughly. */
protected static final boolean LONG_TESTS = false;
protected EventBus eventBus;
protected final AtomicInteger eventCount = new AtomicInteger();
protected final List eventsReceived;
protected volatile Object lastEvent;
protected volatile Thread lastThread;
public AbstractEventBusTest() {
this(false);
}
public AbstractEventBusTest(boolean collectEventsReceived) {
if (collectEventsReceived) {
eventsReceived = new CopyOnWriteArrayList();
} else {
eventsReceived = null;
}
}
@Before
public void setUpBase() throws Exception {
EventBus.clearCaches();
eventBus = new EventBus();
}
protected void waitForEventCount(int expectedCount, int maxMillis) {
for (int i = 0; i < maxMillis; i++) {
int currentCount = eventCount.get();
if (currentCount == expectedCount) {
break;
} else if (currentCount > expectedCount) {
fail("Current count (" + currentCount + ") is already higher than expected count (" + expectedCount
+ ")");
} else {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
assertEquals(expectedCount, eventCount.get());
}
protected void trackEvent(Object event) {
lastEvent = event;
lastThread = Thread.currentThread();
if (eventsReceived != null) {
eventsReceived.add(event);
}
// Must the the last one because we wait for this
eventCount.incrementAndGet();
}
protected void assertEventCount(int expectedEventCount) {
assertEquals(expectedEventCount, eventCount.intValue());
}
protected void countDownAndAwaitLatch(CountDownLatch latch, long seconds) {
latch.countDown();
awaitLatch(latch, seconds);
}
protected void awaitLatch(CountDownLatch latch, long seconds) {
try {
assertTrue(latch.await(seconds, TimeUnit.SECONDS));
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
protected void log(String msg) {
eventBus.getLogger().log(Level.FINE, msg);
}
protected void log(String msg, Throwable e) {
eventBus.getLogger().log(Level.FINE, msg, e);
}
}
================================================
FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusBasicTest.java
================================================
/*
* Copyright (C) 2012-2017 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* @author Markus Junginger, greenrobot
*/
@SuppressWarnings({"WeakerAccess", "UnusedParameters", "unused"})
public class EventBusBasicTest extends AbstractEventBusTest {
public static class WithIndex extends EventBusBasicTest {
@Test
public void dummy() {
}
}
private String lastStringEvent;
private int countStringEvent;
private int countIntEvent;
private int lastIntEvent;
private int countMyEventExtended;
private int countMyEvent;
private int countMyEvent2;
@Test
public void testRegisterAndPost() {
// Use an activity to test real life performance
StringEventSubscriber stringEventSubscriber = new StringEventSubscriber();
String event = "Hello";
long start = System.currentTimeMillis();
eventBus.register(stringEventSubscriber);
long time = System.currentTimeMillis() - start;
log("Registered in " + time + "ms");
eventBus.post(event);
assertEquals(event, stringEventSubscriber.lastStringEvent);
}
@Test
public void testPostWithoutSubscriber() {
eventBus.post("Hello");
}
@Test
public void testUnregisterWithoutRegister() {
// Results in a warning without throwing
eventBus.unregister(this);
}
// This will throw "out of memory" if subscribers are leaked
@Test
public void testUnregisterNotLeaking() {
int heapMBytes = (int) (Runtime.getRuntime().maxMemory() / (1024L * 1024L));
for (int i = 0; i < heapMBytes * 2; i++) {
@SuppressWarnings("unused")
EventBusBasicTest subscriber = new EventBusBasicTest() {
byte[] expensiveObject = new byte[1024 * 1024];
};
eventBus.register(subscriber);
eventBus.unregister(subscriber);
log("Iteration " + i + " / max heap: " + heapMBytes);
}
}
@Test
public void testRegisterTwice() {
eventBus.register(this);
try {
eventBus.register(this);
fail("Did not throw");
} catch (RuntimeException expected) {
// OK
}
}
@Test
public void testIsRegistered() {
assertFalse(eventBus.isRegistered(this));
eventBus.register(this);
assertTrue(eventBus.isRegistered(this));
eventBus.unregister(this);
assertFalse(eventBus.isRegistered(this));
}
@Test
public void testPostWithTwoSubscriber() {
EventBusBasicTest test2 = new EventBusBasicTest();
eventBus.register(this);
eventBus.register(test2);
String event = "Hello";
eventBus.post(event);
assertEquals(event, lastStringEvent);
assertEquals(event, test2.lastStringEvent);
}
@Test
public void testPostMultipleTimes() {
eventBus.register(this);
MyEvent event = new MyEvent();
int count = 1000;
long start = System.currentTimeMillis();
// Debug.startMethodTracing("testPostMultipleTimes" + count);
for (int i = 0; i < count; i++) {
eventBus.post(event);
}
// Debug.stopMethodTracing();
long time = System.currentTimeMillis() - start;
log("Posted " + count + " events in " + time + "ms");
assertEquals(count, countMyEvent);
}
@Test
public void testMultipleSubscribeMethodsForEvent() {
eventBus.register(this);
MyEvent event = new MyEvent();
eventBus.post(event);
assertEquals(1, countMyEvent);
assertEquals(1, countMyEvent2);
}
@Test
public void testPostAfterUnregister() {
eventBus.register(this);
eventBus.unregister(this);
eventBus.post("Hello");
assertNull(lastStringEvent);
}
@Test
public void testRegisterAndPostTwoTypes() {
eventBus.register(this);
eventBus.post(42);
eventBus.post("Hello");
assertEquals(1, countIntEvent);
assertEquals(1, countStringEvent);
assertEquals(42, lastIntEvent);
assertEquals("Hello", lastStringEvent);
}
@Test
public void testRegisterUnregisterAndPostTwoTypes() {
eventBus.register(this);
eventBus.unregister(this);
eventBus.post(42);
eventBus.post("Hello");
assertEquals(0, countIntEvent);
assertEquals(0, lastIntEvent);
assertEquals(0, countStringEvent);
}
@Test
public void testPostOnDifferentEventBus() {
eventBus.register(this);
new EventBus().post("Hello");
assertEquals(0, countStringEvent);
}
@Test
public void testPostInEventHandler() {
RepostInteger reposter = new RepostInteger();
eventBus.register(reposter);
eventBus.register(this);
eventBus.post(1);
assertEquals(10, countIntEvent);
assertEquals(10, lastIntEvent);
assertEquals(10, reposter.countEvent);
assertEquals(10, reposter.lastEvent);
}
@Test
public void testHasSubscriberForEvent() {
assertFalse(eventBus.hasSubscriberForEvent(String.class));
eventBus.register(this);
assertTrue(eventBus.hasSubscriberForEvent(String.class));
eventBus.unregister(this);
assertFalse(eventBus.hasSubscriberForEvent(String.class));
}
@Test
public void testHasSubscriberForEventSuperclass() {
assertFalse(eventBus.hasSubscriberForEvent(String.class));
Object subscriber = new ObjectSubscriber();
eventBus.register(subscriber);
assertTrue(eventBus.hasSubscriberForEvent(String.class));
eventBus.unregister(subscriber);
assertFalse(eventBus.hasSubscriberForEvent(String.class));
}
@Test
public void testHasSubscriberForEventImplementedInterface() {
assertFalse(eventBus.hasSubscriberForEvent(String.class));
Object subscriber = new CharSequenceSubscriber();
eventBus.register(subscriber);
assertTrue(eventBus.hasSubscriberForEvent(CharSequence.class));
assertTrue(eventBus.hasSubscriberForEvent(String.class));
eventBus.unregister(subscriber);
assertFalse(eventBus.hasSubscriberForEvent(CharSequence.class));
assertFalse(eventBus.hasSubscriberForEvent(String.class));
}
@Subscribe
public void onEvent(String event) {
lastStringEvent = event;
countStringEvent++;
}
@Subscribe
public void onEvent(Integer event) {
lastIntEvent = event;
countIntEvent++;
}
@Subscribe
public void onEvent(MyEvent event) {
countMyEvent++;
}
@Subscribe
public void onEvent2(MyEvent event) {
countMyEvent2++;
}
@Subscribe
public void onEvent(MyEventExtended event) {
countMyEventExtended++;
}
public static class StringEventSubscriber {
public String lastStringEvent;
@Subscribe
public void onEvent(String event) {
lastStringEvent = event;
}
}
public static class CharSequenceSubscriber {
@Subscribe
public void onEvent(CharSequence event) {
}
}
public static class ObjectSubscriber {
@Subscribe
public void onEvent(Object event) {
}
}
public class MyEvent {
}
public class MyEventExtended extends MyEvent {
}
public class RepostInteger {
public int lastEvent;
public int countEvent;
@Subscribe
public void onEvent(Integer event) {
lastEvent = event;
countEvent++;
assertEquals(countEvent, event.intValue());
if (event < 10) {
int countIntEventBefore = countEvent;
eventBus.post(event + 1);
// All our post calls will just enqueue the event, so check count is unchanged
assertEquals(countIntEventBefore, countIntEventBefore);
}
}
}
}
================================================
FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusBuilderTest.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus;
import org.junit.Assert;
import org.junit.Test;
import static org.junit.Assert.fail;
/**
* @author Markus Junginger, greenrobot
*/
public class EventBusBuilderTest extends AbstractEventBusTest {
@Test
public void testThrowSubscriberException() {
eventBus = EventBus.builder().throwSubscriberException(true).build();
eventBus.register(new SubscriberExceptionEventTracker());
eventBus.register(new ThrowingSubscriber());
try {
eventBus.post("Foo");
fail("Should have thrown");
} catch (EventBusException e) {
// Expected
}
}
@Test
public void testDoNotSendSubscriberExceptionEvent() {
eventBus = EventBus.builder().logSubscriberExceptions(false).sendSubscriberExceptionEvent(false).build();
eventBus.register(new SubscriberExceptionEventTracker());
eventBus.register(new ThrowingSubscriber());
eventBus.post("Foo");
assertEventCount(0);
}
@Test
public void testDoNotSendNoSubscriberEvent() {
eventBus = EventBus.builder().logNoSubscriberMessages(false).sendNoSubscriberEvent(false).build();
eventBus.register(new NoSubscriberEventTracker());
eventBus.post("Foo");
assertEventCount(0);
}
@Test
public void testInstallDefaultEventBus() {
EventBusBuilder builder = EventBus.builder();
try {
// Either this should throw when another unit test got the default event bus...
eventBus = builder.installDefaultEventBus();
Assert.assertEquals(eventBus, EventBus.getDefault());
// ...or this should throw
eventBus = builder.installDefaultEventBus();
fail("Should have thrown");
} catch (EventBusException e) {
// Expected
}
}
@Test
public void testEventInheritance() {
eventBus = EventBus.builder().eventInheritance(false).build();
eventBus.register(new ThrowingSubscriber());
eventBus.post("Foo");
}
public class SubscriberExceptionEventTracker {
@Subscribe
public void onEvent(SubscriberExceptionEvent event) {
trackEvent(event);
}
}
public class NoSubscriberEventTracker {
@Subscribe
public void onEvent(NoSubscriberEvent event) {
trackEvent(event);
}
}
public class ThrowingSubscriber {
@Subscribe
public void onEvent(Object event) {
throw new RuntimeException();
}
}
}
================================================
FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusCancelEventDeliveryTest.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus;
import org.junit.Test;
import java.util.concurrent.CountDownLatch;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
public class EventBusCancelEventDeliveryTest extends AbstractEventBusTest {
Throwable failed;
@Test
public void testCancel() {
Subscriber canceler = new Subscriber(1, true);
eventBus.register(new Subscriber(0, false));
eventBus.register(canceler);
eventBus.register(new Subscriber(0, false));
eventBus.post("42");
assertEquals(1, eventCount.intValue());
eventBus.unregister(canceler);
eventBus.post("42");
assertEquals(1 + 2, eventCount.intValue());
}
@Test
public void testCancelInBetween() {
eventBus.register(new Subscriber(2, true));
eventBus.register(new Subscriber(1, false));
eventBus.register(new Subscriber(3, false));
eventBus.post("42");
assertEquals(2, eventCount.intValue());
}
@Test
public void testCancelOutsideEventHandler() {
try {
eventBus.cancelEventDelivery(this);
fail("Should have thrown");
} catch (EventBusException e) {
// Expected
}
}
@Test
public void testCancelWrongEvent() {
eventBus.register(new SubscriberCancelOtherEvent());
eventBus.post("42");
assertEquals(0, eventCount.intValue());
assertNotNull(failed);
}
public class Subscriber {
private final int prio;
private final boolean cancel;
public Subscriber(int prio, boolean cancel) {
this.prio = prio;
this.cancel = cancel;
}
@Subscribe
public void onEvent(String event) {
handleEvent(event, 0);
}
@Subscribe(priority = 1)
public void onEvent1(String event) {
handleEvent(event, 1);
}
@Subscribe(priority = 2)
public void onEvent2(String event) {
handleEvent(event, 2);
}
@Subscribe(priority = 3)
public void onEvent3(String event) {
handleEvent(event, 3);
}
private void handleEvent(String event, int prio) {
if(this.prio == prio) {
trackEvent(event);
if (cancel) {
eventBus.cancelEventDelivery(event);
}
}
}
}
public class SubscriberCancelOtherEvent {
@Subscribe
public void onEvent(String event) {
try {
eventBus.cancelEventDelivery(this);
} catch (EventBusException e) {
failed = e;
}
}
}
public class SubscriberMainThread {
final CountDownLatch done = new CountDownLatch(1);
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(String event) {
try {
eventBus.cancelEventDelivery(event);
} catch (EventBusException e) {
failed = e;
}
done.countDown();
}
}
}
================================================
FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusFallbackToReflectionTest.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class EventBusFallbackToReflectionTest extends AbstractEventBusTest {
private class PrivateEvent {
}
public class PublicClass {
@Subscribe
public void onEvent(Object any) {
trackEvent(any);
}
}
private class PrivateClass {
@Subscribe
public void onEvent(Object any) {
trackEvent(any);
}
}
public class PublicWithPrivateSuperClass extends PrivateClass {
@Subscribe
public void onEvent(String any) {
trackEvent(any);
}
}
public class PublicClassWithPrivateEvent {
@Subscribe
public void onEvent(PrivateEvent any) {
trackEvent(any);
}
}
public class PublicClassWithPublicAndPrivateEvent {
@Subscribe
public void onEvent(String any) {
trackEvent(any);
}
@Subscribe
public void onEvent(PrivateEvent any) {
trackEvent(any);
}
}
public class PublicWithPrivateEventInSuperclass extends PublicClassWithPrivateEvent {
@Subscribe
public void onEvent(Object any) {
trackEvent(any);
}
}
public EventBusFallbackToReflectionTest() {
super(true);
}
@Test
public void testAnonymousSubscriberClass() {
Object subscriber = new Object() {
@Subscribe
public void onEvent(String event) {
trackEvent(event);
}
};
eventBus.register(subscriber);
eventBus.post("Hello");
assertEquals("Hello", lastEvent);
assertEquals(1, eventsReceived.size());
}
@Test
public void testAnonymousSubscriberClassWithPublicSuperclass() {
Object subscriber = new PublicClass() {
@Subscribe
public void onEvent(String event) {
trackEvent(event);
}
};
eventBus.register(subscriber);
eventBus.post("Hello");
assertEquals("Hello", lastEvent);
assertEquals(2, eventsReceived.size());
}
@Test
public void testAnonymousSubscriberClassWithPrivateSuperclass() {
eventBus.register(new PublicWithPrivateSuperClass());
eventBus.post("Hello");
assertEquals("Hello", lastEvent);
assertEquals(2, eventsReceived.size());
}
@Test
public void testSubscriberClassWithPrivateEvent() {
eventBus.register(new PublicClassWithPrivateEvent());
PrivateEvent privateEvent = new PrivateEvent();
eventBus.post(privateEvent);
assertEquals(privateEvent, lastEvent);
assertEquals(1, eventsReceived.size());
}
@Test
public void testSubscriberClassWithPublicAndPrivateEvent() {
eventBus.register(new PublicClassWithPublicAndPrivateEvent());
eventBus.post("Hello");
assertEquals("Hello", lastEvent);
assertEquals(1, eventsReceived.size());
PrivateEvent privateEvent = new PrivateEvent();
eventBus.post(privateEvent);
assertEquals(privateEvent, lastEvent);
assertEquals(2, eventsReceived.size());
}
@Test
public void testSubscriberExtendingClassWithPrivateEvent() {
eventBus.register(new PublicWithPrivateEventInSuperclass());
PrivateEvent privateEvent = new PrivateEvent();
eventBus.post(privateEvent);
assertEquals(privateEvent, lastEvent);
assertEquals(2, eventsReceived.size());
}
}
================================================
FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusGenericsTest.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus;
import org.junit.Test;
public class EventBusGenericsTest extends AbstractEventBusTest {
public static class GenericEvent {
T value;
}
public class GenericEventSubscriber {
@Subscribe
public void onGenericEvent(GenericEvent event) {
trackEvent(event);
}
}
public class FullGenericEventSubscriber {
@Subscribe
public void onGenericEvent(T event) {
trackEvent(event);
}
}
public class GenericNumberEventSubscriber {
@Subscribe
public void onGenericEvent(T event) {
trackEvent(event);
}
}
public class GenericFloatEventSubscriber extends GenericNumberEventSubscriber {
}
@Test
public void testGenericEventAndSubscriber() {
GenericEventSubscriber genericSubscriber = new GenericEventSubscriber();
eventBus.register(genericSubscriber);
eventBus.post(new GenericEvent());
assertEventCount(1);
}
@Test
public void testGenericEventAndSubscriber_TypeErasure() {
FullGenericEventSubscriber genericSubscriber = new FullGenericEventSubscriber();
eventBus.register(genericSubscriber);
eventBus.post(new IntTestEvent(42));
eventBus.post("Type erasure!");
assertEventCount(2);
}
@Test
public void testGenericEventAndSubscriber_BaseType() {
GenericNumberEventSubscriber genericSubscriber = new GenericNumberEventSubscriber<>();
eventBus.register(genericSubscriber);
eventBus.post(new Float(42));
eventBus.post(new Double(23));
assertEventCount(2);
eventBus.post("Not the same base type");
assertEventCount(2);
}
@Test
public void testGenericEventAndSubscriber_Subclass() {
GenericFloatEventSubscriber genericSubscriber = new GenericFloatEventSubscriber();
eventBus.register(genericSubscriber);
eventBus.post(new Float(42));
eventBus.post(new Double(77));
assertEventCount(2);
eventBus.post("Not the same base type");
assertEventCount(2);
}
}
================================================
FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusIndexTest.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus;
import org.greenrobot.eventbus.meta.SimpleSubscriberInfo;
import org.greenrobot.eventbus.meta.SubscriberInfo;
import org.greenrobot.eventbus.meta.SubscriberInfoIndex;
import org.greenrobot.eventbus.meta.SubscriberMethodInfo;
import org.junit.Assert;
import org.junit.Test;
public class EventBusIndexTest {
private String value;
/** Ensures the index is actually used and no reflection fall-back kicks in. */
@Test
public void testManualIndexWithoutAnnotation() {
SubscriberInfoIndex index = new SubscriberInfoIndex() {
@Override
public SubscriberInfo getSubscriberInfo(Class> subscriberClass) {
Assert.assertEquals(EventBusIndexTest.class, subscriberClass);
SubscriberMethodInfo[] methodInfos = {
new SubscriberMethodInfo("someMethodWithoutAnnotation", String.class)
};
return new SimpleSubscriberInfo(EventBusIndexTest.class, false, methodInfos);
}
};
EventBus eventBus = EventBus.builder().addIndex(index).build();
eventBus.register(this);
eventBus.post("Yepp");
eventBus.unregister(this);
Assert.assertEquals("Yepp", value);
}
public void someMethodWithoutAnnotation(String value) {
this.value = value;
}
}
================================================
FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceDisabledSubclassNoMethod.java
================================================
package org.greenrobot.eventbus;
// Need to use upper class or Android test runner does not pick it up
public class EventBusInheritanceDisabledSubclassNoMethod extends EventBusInheritanceDisabledTest {
}
================================================
FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceDisabledSubclassTest.java
================================================
package org.greenrobot.eventbus;
import org.junit.Ignore;
// Need to use upper class or Android test runner does not pick it up
public class EventBusInheritanceDisabledSubclassTest extends EventBusInheritanceDisabledTest {
int countMyEventOverwritten;
@Subscribe
public void onEvent(MyEvent event) {
countMyEventOverwritten++;
}
@Override
@Ignore
public void testEventClassHierarchy() {
// TODO fix test in super, then remove this
}
}
================================================
FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceDisabledTest.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus;
import org.junit.Before;
import org.junit.Test;
import static junit.framework.Assert.assertEquals;
/**
* @author Markus Junginger, greenrobot
*/
public class EventBusInheritanceDisabledTest {
protected EventBus eventBus;
protected int countMyEventExtended;
protected int countMyEvent;
protected int countObjectEvent;
private int countMyEventInterface;
private int countMyEventInterfaceExtended;
@Before
public void setUp() throws Exception {
eventBus = EventBus.builder().eventInheritance(false).build();
}
@Test
public void testEventClassHierarchy() {
eventBus.register(this);
eventBus.post("Hello");
assertEquals(0, countObjectEvent);
eventBus.post(new MyEvent());
assertEquals(0, countObjectEvent);
assertEquals(1, countMyEvent);
eventBus.post(new MyEventExtended());
assertEquals(0, countObjectEvent);
assertEquals(1, countMyEvent);
assertEquals(1, countMyEventExtended);
}
@Test
public void testEventClassHierarchySticky() {
eventBus.postSticky("Hello");
eventBus.postSticky(new MyEvent());
eventBus.postSticky(new MyEventExtended());
eventBus.register(new StickySubscriber());
assertEquals(1, countMyEventExtended);
assertEquals(1, countMyEvent);
assertEquals(0, countObjectEvent);
}
@Test
public void testEventInterfaceHierarchy() {
eventBus.register(this);
eventBus.post(new MyEvent());
assertEquals(0, countMyEventInterface);
eventBus.post(new MyEventExtended());
assertEquals(0, countMyEventInterface);
assertEquals(0, countMyEventInterfaceExtended);
}
@Test
public void testEventSuperInterfaceHierarchy() {
eventBus.register(this);
eventBus.post(new MyEventInterfaceExtended() {
});
assertEquals(0, countMyEventInterface);
assertEquals(0, countMyEventInterfaceExtended);
}
@Test
public void testSubscriberClassHierarchy() {
EventBusInheritanceDisabledSubclassTest
subscriber = new EventBusInheritanceDisabledSubclassTest();
eventBus.register(subscriber);
eventBus.post("Hello");
assertEquals(0, subscriber.countObjectEvent);
eventBus.post(new MyEvent());
assertEquals(0, subscriber.countObjectEvent);
assertEquals(0, subscriber.countMyEvent);
assertEquals(1, subscriber.countMyEventOverwritten);
eventBus.post(new MyEventExtended());
assertEquals(0, subscriber.countObjectEvent);
assertEquals(0, subscriber.countMyEvent);
assertEquals(1, subscriber.countMyEventExtended);
assertEquals(1, subscriber.countMyEventOverwritten);
}
@Test
public void testSubscriberClassHierarchyWithoutNewSubscriberMethod() {
EventBusInheritanceDisabledSubclassNoMethod
subscriber = new EventBusInheritanceDisabledSubclassNoMethod();
eventBus.register(subscriber);
eventBus.post("Hello");
assertEquals(0, subscriber.countObjectEvent);
eventBus.post(new MyEvent());
assertEquals(0, subscriber.countObjectEvent);
assertEquals(1, subscriber.countMyEvent);
eventBus.post(new MyEventExtended());
assertEquals(0, subscriber.countObjectEvent);
assertEquals(1, subscriber.countMyEvent);
assertEquals(1, subscriber.countMyEventExtended);
}
@Subscribe
public void onEvent(Object event) {
countObjectEvent++;
}
@Subscribe
public void onEvent(MyEvent event) {
countMyEvent++;
}
@Subscribe
public void onEvent(MyEventExtended event) {
countMyEventExtended++;
}
@Subscribe
public void onEvent(MyEventInterface event) {
countMyEventInterface++;
}
@Subscribe
public void onEvent(MyEventInterfaceExtended event) {
countMyEventInterfaceExtended++;
}
public static interface MyEventInterface {
}
public static class MyEvent implements MyEventInterface {
}
public static interface MyEventInterfaceExtended extends MyEventInterface {
}
public static class MyEventExtended extends MyEvent implements MyEventInterfaceExtended {
}
public class StickySubscriber {
@Subscribe(sticky = true)
public void onEvent(Object event) {
countObjectEvent++;
}
@Subscribe(sticky = true)
public void onEvent(MyEvent event) {
countMyEvent++;
}
@Subscribe(sticky = true)
public void onEvent(MyEventExtended event) {
countMyEventExtended++;
}
@Subscribe(sticky = true)
public void onEvent(MyEventInterface event) {
countMyEventInterface++;
}
@Subscribe(sticky = true)
public void onEvent(MyEventInterfaceExtended event) {
countMyEventInterfaceExtended++;
}
}
}
================================================
FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceSubclassNoMethodTest.java
================================================
package org.greenrobot.eventbus;
// Need to use upper class or Android test runner does not pick it up
public class EventBusInheritanceSubclassNoMethodTest extends EventBusInheritanceTest {
}
================================================
FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceSubclassTest.java
================================================
package org.greenrobot.eventbus;
import org.junit.Ignore;
// Need to use upper class or Android test runner does not pick it up
public class EventBusInheritanceSubclassTest extends EventBusInheritanceTest {
int countMyEventOverwritten;
@Subscribe
public void onEvent(MyEvent event) {
countMyEventOverwritten++;
}
@Override
@Ignore
public void testEventClassHierarchy() {
// TODO fix test in super, then remove this
}
}
================================================
FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceTest.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
/**
* @author Markus Junginger, greenrobot
*/
public class EventBusInheritanceTest {
protected EventBus eventBus;
protected int countMyEventExtended;
protected int countMyEvent;
protected int countObjectEvent;
private int countMyEventInterface;
private int countMyEventInterfaceExtended;
@Before
public void setUp() throws Exception {
eventBus = new EventBus();
}
@Test
public void testEventClassHierarchy() {
eventBus.register(this);
eventBus.post("Hello");
assertEquals(1, countObjectEvent);
eventBus.post(new MyEvent());
assertEquals(2, countObjectEvent);
assertEquals(1, countMyEvent);
eventBus.post(new MyEventExtended());
assertEquals(3, countObjectEvent);
assertEquals(2, countMyEvent);
assertEquals(1, countMyEventExtended);
}
@Test
public void testEventClassHierarchySticky() {
eventBus.postSticky("Hello");
eventBus.postSticky(new MyEvent());
eventBus.postSticky(new MyEventExtended());
eventBus.register(new StickySubscriber());
assertEquals(1, countMyEventExtended);
assertEquals(2, countMyEvent);
assertEquals(3, countObjectEvent);
}
@Test
public void testEventInterfaceHierarchy() {
eventBus.register(this);
eventBus.post(new MyEvent());
assertEquals(1, countMyEventInterface);
eventBus.post(new MyEventExtended());
assertEquals(2, countMyEventInterface);
assertEquals(1, countMyEventInterfaceExtended);
}
@Test
public void testEventSuperInterfaceHierarchy() {
eventBus.register(this);
eventBus.post(new MyEventInterfaceExtended() {
});
assertEquals(1, countMyEventInterface);
assertEquals(1, countMyEventInterfaceExtended);
}
@Test
public void testSubscriberClassHierarchy() {
EventBusInheritanceSubclassTest subscriber = new EventBusInheritanceSubclassTest();
eventBus.register(subscriber);
eventBus.post("Hello");
assertEquals(1, subscriber.countObjectEvent);
eventBus.post(new MyEvent());
assertEquals(2, subscriber.countObjectEvent);
assertEquals(0, subscriber.countMyEvent);
assertEquals(1, subscriber.countMyEventOverwritten);
eventBus.post(new MyEventExtended());
assertEquals(3, subscriber.countObjectEvent);
assertEquals(0, subscriber.countMyEvent);
assertEquals(1, subscriber.countMyEventExtended);
assertEquals(2, subscriber.countMyEventOverwritten);
}
@Test
public void testSubscriberClassHierarchyWithoutNewSubscriberMethod() {
EventBusInheritanceSubclassNoMethodTest
subscriber = new EventBusInheritanceSubclassNoMethodTest();
eventBus.register(subscriber);
eventBus.post("Hello");
assertEquals(1, subscriber.countObjectEvent);
eventBus.post(new MyEvent());
assertEquals(2, subscriber.countObjectEvent);
assertEquals(1, subscriber.countMyEvent);
eventBus.post(new MyEventExtended());
assertEquals(3, subscriber.countObjectEvent);
assertEquals(2, subscriber.countMyEvent);
assertEquals(1, subscriber.countMyEventExtended);
}
@Subscribe
public void onEvent(Object event) {
countObjectEvent++;
}
@Subscribe
public void onEvent(MyEvent event) {
countMyEvent++;
}
@Subscribe
public void onEvent(MyEventExtended event) {
countMyEventExtended++;
}
@Subscribe
public void onEvent(MyEventInterface event) {
countMyEventInterface++;
}
@Subscribe
public void onEvent(MyEventInterfaceExtended event) {
countMyEventInterfaceExtended++;
}
public static interface MyEventInterface {
}
public static class MyEvent implements MyEventInterface {
}
public static interface MyEventInterfaceExtended extends MyEventInterface {
}
public static class MyEventExtended extends MyEvent implements MyEventInterfaceExtended {
}
public class StickySubscriber {
@Subscribe(sticky = true)
public void onEvent(Object event) {
countObjectEvent++;
}
@Subscribe(sticky = true)
public void onEvent(MyEvent event) {
countMyEvent++;
}
@Subscribe(sticky = true)
public void onEvent(MyEventExtended event) {
countMyEventExtended++;
}
@Subscribe(sticky = true)
public void onEvent(MyEventInterface event) {
countMyEventInterface++;
}
@Subscribe(sticky = true)
public void onEvent(MyEventInterfaceExtended event) {
countMyEventInterfaceExtended++;
}
}
}
================================================
FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusMultithreadedTest.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import static org.junit.Assert.assertEquals;
public class EventBusMultithreadedTest extends AbstractEventBusTest {
static final int COUNT = LONG_TESTS ? 100000 : 1000;
final AtomicInteger countStringEvent = new AtomicInteger();
final AtomicInteger countIntegerEvent = new AtomicInteger();
final AtomicInteger countObjectEvent = new AtomicInteger();
final AtomicInteger countIntTestEvent = new AtomicInteger();
String lastStringEvent;
Integer lastIntegerEvent;
IntTestEvent lastIntTestEvent;
@Test
public void testPost01Thread() throws InterruptedException {
runThreadsSingleEventType(1);
}
@Test
public void testPost04Threads() throws InterruptedException {
runThreadsSingleEventType(4);
}
@Test
public void testPost40Threads() throws InterruptedException {
runThreadsSingleEventType(40);
}
@Test
public void testPostMixedEventType01Thread() throws InterruptedException {
runThreadsMixedEventType(1);
}
@Test
public void testPostMixedEventType04Threads() throws InterruptedException {
runThreadsMixedEventType(4);
}
@Test
public void testPostMixedEventType40Threads() throws InterruptedException {
runThreadsMixedEventType(40);
}
private void runThreadsSingleEventType(int threadCount) throws InterruptedException {
int iterations = COUNT / threadCount;
eventBus.register(this);
CountDownLatch latch = new CountDownLatch(threadCount + 1);
List threads = startThreads(latch, threadCount, iterations, "Hello");
long time = triggerAndWaitForThreads(threads, latch);
log(threadCount + " threads posted " + iterations + " events each in " + time + "ms");
waitForEventCount(COUNT * 2, 5000);
assertEquals("Hello", lastStringEvent);
int expectedCount = threadCount * iterations;
assertEquals(expectedCount, countStringEvent.intValue());
assertEquals(expectedCount, countObjectEvent.intValue());
}
private void runThreadsMixedEventType(int threadCount) throws InterruptedException {
runThreadsMixedEventType(COUNT, threadCount);
}
void runThreadsMixedEventType(int count, int threadCount) throws InterruptedException {
eventBus.register(this);
int eventTypeCount = 3;
int iterations = count / threadCount / eventTypeCount;
CountDownLatch latch = new CountDownLatch(eventTypeCount * threadCount + 1);
List threadsString = startThreads(latch, threadCount, iterations, "Hello");
List threadsInteger = startThreads(latch, threadCount, iterations, 42);
List threadsIntTestEvent = startThreads(latch, threadCount, iterations, new IntTestEvent(7));
List threads = new ArrayList();
threads.addAll(threadsString);
threads.addAll(threadsInteger);
threads.addAll(threadsIntTestEvent);
long time = triggerAndWaitForThreads(threads, latch);
log(threadCount * eventTypeCount + " mixed threads posted " + iterations + " events each in "
+ time + "ms");
int expectedCountEach = threadCount * iterations;
int expectedCountTotal = expectedCountEach * eventTypeCount * 2;
waitForEventCount(expectedCountTotal, 5000);
assertEquals("Hello", lastStringEvent);
assertEquals(42, lastIntegerEvent.intValue());
assertEquals(7, lastIntTestEvent.value);
assertEquals(expectedCountEach, countStringEvent.intValue());
assertEquals(expectedCountEach, countIntegerEvent.intValue());
assertEquals(expectedCountEach, countIntTestEvent.intValue());
assertEquals(expectedCountEach * eventTypeCount, countObjectEvent.intValue());
}
private long triggerAndWaitForThreads(List threads, CountDownLatch latch) throws InterruptedException {
while (latch.getCount() != 1) {
// Let all other threads prepare and ensure this one is the last
Thread.sleep(1);
}
long start = System.currentTimeMillis();
latch.countDown();
for (PosterThread thread : threads) {
thread.join();
}
return System.currentTimeMillis() - start;
}
private List startThreads(CountDownLatch latch, int threadCount, int iterations, Object eventToPost) {
List threads = new ArrayList(threadCount);
for (int i = 0; i < threadCount; i++) {
PosterThread thread = new PosterThread(latch, iterations, eventToPost);
thread.start();
threads.add(thread);
}
return threads;
}
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onEventBackgroundThread(String event) {
lastStringEvent = event;
countStringEvent.incrementAndGet();
trackEvent(event);
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(Integer event) {
lastIntegerEvent = event;
countIntegerEvent.incrementAndGet();
trackEvent(event);
}
@Subscribe(threadMode = ThreadMode.ASYNC)
public void onEventAsync(IntTestEvent event) {
countIntTestEvent.incrementAndGet();
lastIntTestEvent = event;
trackEvent(event);
}
@Subscribe
public void onEvent(Object event) {
countObjectEvent.incrementAndGet();
trackEvent(event);
}
class PosterThread extends Thread {
private final CountDownLatch startLatch;
private final int iterations;
private final Object eventToPost;
public PosterThread(CountDownLatch latch, int iterations, Object eventToPost) {
this.startLatch = latch;
this.iterations = iterations;
this.eventToPost = eventToPost;
}
@Override
public void run() {
startLatch.countDown();
try {
startLatch.await();
} catch (InterruptedException e) {
log("Unexpected interrupt", e);
}
for (int i = 0; i < iterations; i++) {
eventBus.post(eventToPost);
}
}
}
}
================================================
FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusNoSubscriberEventTest.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
/**
* @author Markus Junginger, greenrobot
*/
public class EventBusNoSubscriberEventTest extends AbstractEventBusTest {
@Test
public void testNoSubscriberEvent() {
eventBus.register(this);
eventBus.post("Foo");
assertEventCount(1);
assertEquals(NoSubscriberEvent.class, lastEvent.getClass());
NoSubscriberEvent noSub = (NoSubscriberEvent) lastEvent;
assertEquals("Foo", noSub.originalEvent);
assertSame(eventBus, noSub.eventBus);
}
@Test
public void testNoSubscriberEventAfterUnregister() {
Object subscriber = new DummySubscriber();
eventBus.register(subscriber);
eventBus.unregister(subscriber);
testNoSubscriberEvent();
}
@Test
public void testBadNoSubscriberSubscriber() {
eventBus = EventBus.builder().logNoSubscriberMessages(false).build();
eventBus.register(this);
eventBus.register(new BadNoSubscriberSubscriber());
eventBus.post("Foo");
assertEventCount(2);
assertEquals(SubscriberExceptionEvent.class, lastEvent.getClass());
NoSubscriberEvent noSub = (NoSubscriberEvent) ((SubscriberExceptionEvent) lastEvent).causingEvent;
assertEquals("Foo", noSub.originalEvent);
}
@Subscribe
public void onEvent(NoSubscriberEvent event) {
trackEvent(event);
}
@Subscribe
public void onEvent(SubscriberExceptionEvent event) {
trackEvent(event);
}
public static class DummySubscriber {
@SuppressWarnings("unused")
@Subscribe
public void onEvent(String dummy) {
}
}
public class BadNoSubscriberSubscriber {
@Subscribe
public void onEvent(NoSubscriberEvent event) {
throw new RuntimeException("I'm bad");
}
}
}
================================================
FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusOrderedSubscriptionsTest.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.assertEquals;
/**
* @author Markus Junginger, greenrobot
*/
public class EventBusOrderedSubscriptionsTest extends AbstractEventBusTest {
int lastPrio = Integer.MAX_VALUE;
final List registered = new ArrayList();
private String fail;
@Test
public void testOrdered() {
runTestOrdered("42", false, 5);
}
@Test
public void testOrderedMainThread() {
runTestOrdered(new IntTestEvent(42), false, 3);
}
@Test
public void testOrderedBackgroundThread() {
runTestOrdered(Integer.valueOf(42), false, 3);
}
@Test
public void testOrderedSticky() {
runTestOrdered("42", true, 5);
}
@Test
public void testOrderedMainThreadSticky() {
runTestOrdered(new IntTestEvent(42), true, 3);
}
@Test
public void testOrderedBackgroundThreadSticky() {
runTestOrdered(Integer.valueOf(42), true, 3);
}
protected void runTestOrdered(Object event, boolean sticky, int expectedEventCount) {
Object subscriber = sticky ? new PrioSubscriberSticky() : new PrioSubscriber();
eventBus.register(subscriber);
eventBus.post(event);
waitForEventCount(expectedEventCount, 10000);
assertEquals(null, fail);
eventBus.unregister(subscriber);
}
public final class PrioSubscriber {
@Subscribe(priority = 1)
public void onEventP1(String event) {
handleEvent(1, event);
}
@Subscribe(priority = -1)
public void onEventM1(String event) {
handleEvent(-1, event);
}
@Subscribe(priority = 0)
public void onEventP0(String event) {
handleEvent(0, event);
}
@Subscribe(priority = 10)
public void onEventP10(String event) {
handleEvent(10, event);
}
@Subscribe(priority = -100)
public void onEventM100(String event) {
handleEvent(-100, event);
}
@Subscribe(threadMode = ThreadMode.MAIN, priority = -1)
public void onEventMainThreadM1(IntTestEvent event) {
handleEvent(-1, event);
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThreadP0(IntTestEvent event) {
handleEvent(0, event);
}
@Subscribe(threadMode = ThreadMode.MAIN, priority = 1)
public void onEventMainThreadP1(IntTestEvent event) {
handleEvent(1, event);
}
@Subscribe(threadMode = ThreadMode.BACKGROUND, priority = 1)
public void onEventBackgroundThreadP1(Integer event) {
handleEvent(1, event);
}
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onEventBackgroundThreadP0(Integer event) {
handleEvent(0, event);
}
@Subscribe(threadMode = ThreadMode.BACKGROUND, priority = -1)
public void onEventBackgroundThreadM1(Integer event) {
handleEvent(-1, event);
}
protected void handleEvent(int prio, Object event) {
if (prio > lastPrio) {
fail = "Called prio " + prio + " after " + lastPrio;
}
lastPrio = prio;
log("Subscriber " + prio + " got: " + event);
trackEvent(event);
}
}
public final class PrioSubscriberSticky {
@Subscribe(priority = 1, sticky = true)
public void onEventP1(String event) {
handleEvent(1, event);
}
@Subscribe(priority = -1, sticky = true)
public void onEventM1(String event) {
handleEvent(-1, event);
}
@Subscribe(priority = 0, sticky = true)
public void onEventP0(String event) {
handleEvent(0, event);
}
@Subscribe(priority = 10, sticky = true)
public void onEventP10(String event) {
handleEvent(10, event);
}
@Subscribe(priority = -100, sticky = true)
public void onEventM100(String event) {
handleEvent(-100, event);
}
@Subscribe(threadMode = ThreadMode.MAIN, priority = -1, sticky = true)
public void onEventMainThreadM1(IntTestEvent event) {
handleEvent(-1, event);
}
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
public void onEventMainThreadP0(IntTestEvent event) {
handleEvent(0, event);
}
@Subscribe(threadMode = ThreadMode.MAIN, priority = 1, sticky = true)
public void onEventMainThreadP1(IntTestEvent event) {
handleEvent(1, event);
}
@Subscribe(threadMode = ThreadMode.BACKGROUND, priority = 1, sticky = true)
public void onEventBackgroundThreadP1(Integer event) {
handleEvent(1, event);
}
@Subscribe(threadMode = ThreadMode.BACKGROUND, sticky = true)
public void onEventBackgroundThreadP0(Integer event) {
handleEvent(0, event);
}
@Subscribe(threadMode = ThreadMode.BACKGROUND, priority = -1, sticky = true)
public void onEventBackgroundThreadM1(Integer event) {
handleEvent(-1, event);
}
protected void handleEvent(int prio, Object event) {
if (prio > lastPrio) {
fail = "Called prio " + prio + " after " + lastPrio;
}
lastPrio = prio;
log("Subscriber " + prio + " got: " + event);
trackEvent(event);
}
}
}
================================================
FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusRegistrationRacingTest.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import static org.junit.Assert.fail;
/**
* @author Markus Junginger, greenrobot
*/
public class EventBusRegistrationRacingTest extends AbstractEventBusTest {
// On a Nexus 5, bad synchronization always failed on the first iteration or went well completely.
// So a high number of iterations do not guarantee a better probability of finding bugs.
private static final int ITERATIONS = LONG_TESTS ? 1000 : 10;
private static final int THREAD_COUNT = 16;
volatile CountDownLatch startLatch;
volatile CountDownLatch registeredLatch;
volatile CountDownLatch canUnregisterLatch;
volatile CountDownLatch unregisteredLatch;
final Executor threadPool = Executors.newCachedThreadPool();
@Test
public void testRacingRegistrations() throws InterruptedException {
for (int i = 0; i < ITERATIONS; i++) {
startLatch = new CountDownLatch(THREAD_COUNT);
registeredLatch = new CountDownLatch(THREAD_COUNT);
canUnregisterLatch = new CountDownLatch(1);
unregisteredLatch = new CountDownLatch(THREAD_COUNT);
List threads = startThreads();
registeredLatch.await();
eventBus.post("42");
canUnregisterLatch.countDown();
for (int t = 0; t < THREAD_COUNT; t++) {
int eventCount = threads.get(t).eventCount;
if (eventCount != 1) {
fail("Failed in iteration " + i + ": thread #" + t + " has event count of " + eventCount);
}
}
// Wait for threads to be done
unregisteredLatch.await();
}
}
private List startThreads() {
List threads = new ArrayList(THREAD_COUNT);
for (int i = 0; i < THREAD_COUNT; i++) {
SubscriberThread thread = new SubscriberThread();
threadPool.execute(thread);
threads.add(thread);
}
return threads;
}
public class SubscriberThread implements Runnable {
volatile int eventCount;
@Override
public void run() {
countDownAndAwaitLatch(startLatch, 10);
eventBus.register(this);
registeredLatch.countDown();
try {
canUnregisterLatch.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
eventBus.unregister(this);
unregisteredLatch.countDown();
}
@Subscribe
public void onEvent(String event) {
eventCount++;
}
}
}
================================================
FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusStickyEventTest.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* @author Markus Junginger, greenrobot
*/
public class EventBusStickyEventTest extends AbstractEventBusTest {
@Test
public void testPostSticky() throws InterruptedException {
eventBus.postSticky("Sticky");
eventBus.register(this);
assertEquals("Sticky", lastEvent);
assertEquals(Thread.currentThread(), lastThread);
}
@Test
public void testPostStickyTwoEvents() throws InterruptedException {
eventBus.postSticky("Sticky");
eventBus.postSticky(new IntTestEvent(7));
eventBus.register(this);
assertEquals(2, eventCount.intValue());
}
@Test
public void testPostStickyTwoSubscribers() throws InterruptedException {
eventBus.postSticky("Sticky");
eventBus.postSticky(new IntTestEvent(7));
eventBus.register(this);
StickyIntTestSubscriber subscriber2 = new StickyIntTestSubscriber();
eventBus.register(subscriber2);
assertEquals(3, eventCount.intValue());
eventBus.postSticky("Sticky");
assertEquals(4, eventCount.intValue());
eventBus.postSticky(new IntTestEvent(8));
assertEquals(6, eventCount.intValue());
}
@Test
public void testPostStickyRegisterNonSticky() throws InterruptedException {
eventBus.postSticky("Sticky");
eventBus.register(new NonStickySubscriber());
assertNull(lastEvent);
assertEquals(0, eventCount.intValue());
}
@Test
public void testPostNonStickyRegisterSticky() throws InterruptedException {
eventBus.post("NonSticky");
eventBus.register(this);
assertNull(lastEvent);
assertEquals(0, eventCount.intValue());
}
@Test
public void testPostStickyTwice() throws InterruptedException {
eventBus.postSticky("Sticky");
eventBus.postSticky("NewSticky");
eventBus.register(this);
assertEquals("NewSticky", lastEvent);
}
@Test
public void testPostStickyThenPostNormal() throws InterruptedException {
eventBus.postSticky("Sticky");
eventBus.post("NonSticky");
eventBus.register(this);
assertEquals("Sticky", lastEvent);
}
@Test
public void testPostStickyWithRegisterAndUnregister() throws InterruptedException {
eventBus.register(this);
eventBus.postSticky("Sticky");
assertEquals("Sticky", lastEvent);
eventBus.unregister(this);
eventBus.register(this);
assertEquals("Sticky", lastEvent);
assertEquals(2, eventCount.intValue());
eventBus.postSticky("NewSticky");
assertEquals(3, eventCount.intValue());
assertEquals("NewSticky", lastEvent);
eventBus.unregister(this);
eventBus.register(this);
assertEquals(4, eventCount.intValue());
assertEquals("NewSticky", lastEvent);
}
@Test
public void testPostStickyAndGet() throws InterruptedException {
eventBus.postSticky("Sticky");
assertEquals("Sticky", eventBus.getStickyEvent(String.class));
}
@Test
public void testPostStickyRemoveClass() throws InterruptedException {
eventBus.postSticky("Sticky");
eventBus.removeStickyEvent(String.class);
assertNull(eventBus.getStickyEvent(String.class));
eventBus.register(this);
assertNull(lastEvent);
assertEquals(0, eventCount.intValue());
}
@Test
public void testPostStickyRemoveEvent() throws InterruptedException {
eventBus.postSticky("Sticky");
assertTrue(eventBus.removeStickyEvent("Sticky"));
assertNull(eventBus.getStickyEvent(String.class));
eventBus.register(this);
assertNull(lastEvent);
assertEquals(0, eventCount.intValue());
}
@Test
public void testPostStickyRemoveAll() throws InterruptedException {
eventBus.postSticky("Sticky");
eventBus.postSticky(new IntTestEvent(77));
eventBus.removeAllStickyEvents();
assertNull(eventBus.getStickyEvent(String.class));
assertNull(eventBus.getStickyEvent(IntTestEvent.class));
eventBus.register(this);
assertNull(lastEvent);
assertEquals(0, eventCount.intValue());
}
@Test
public void testRemoveStickyEventInSubscriber() throws InterruptedException {
eventBus.register(new RemoveStickySubscriber());
eventBus.postSticky("Sticky");
eventBus.register(this);
assertNull(lastEvent);
assertEquals(0, eventCount.intValue());
assertNull(eventBus.getStickyEvent(String.class));
}
@Subscribe(sticky = true)
public void onEvent(String event) {
trackEvent(event);
}
@Subscribe(sticky = true)
public void onEvent(IntTestEvent event) {
trackEvent(event);
}
public class RemoveStickySubscriber {
@SuppressWarnings("unused")
@Subscribe(sticky = true)
public void onEvent(String event) {
eventBus.removeStickyEvent(event);
}
}
public class NonStickySubscriber {
@Subscribe
public void onEvent(String event) {
trackEvent(event);
}
@Subscribe
public void onEvent(IntTestEvent event) {
trackEvent(event);
}
}
public class StickyIntTestSubscriber {
@Subscribe(sticky = true)
public void onEvent(IntTestEvent event) {
trackEvent(event);
}
}
}
================================================
FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusSubscriberExceptionTest.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
/**
* @author Markus Junginger, greenrobot
*/
public class EventBusSubscriberExceptionTest extends AbstractEventBusTest {
@Test
public void testSubscriberExceptionEvent() {
eventBus = EventBus.builder().logSubscriberExceptions(false).build();
eventBus.register(this);
eventBus.post("Foo");
assertEventCount(1);
assertEquals(SubscriberExceptionEvent.class, lastEvent.getClass());
SubscriberExceptionEvent exEvent = (SubscriberExceptionEvent) lastEvent;
assertEquals("Foo", exEvent.causingEvent);
assertSame(this, exEvent.causingSubscriber);
assertEquals("Bar", exEvent.throwable.getMessage());
}
@Test
public void testBadExceptionSubscriber() {
eventBus = EventBus.builder().logSubscriberExceptions(false).build();
eventBus.register(this);
eventBus.register(new BadExceptionSubscriber());
eventBus.post("Foo");
assertEventCount(1);
}
@Subscribe
public void onEvent(String event) {
throw new RuntimeException("Bar");
}
@Subscribe
public void onEvent(SubscriberExceptionEvent event) {
trackEvent(event);
}
public class BadExceptionSubscriber {
@Subscribe
public void onEvent(SubscriberExceptionEvent event) {
throw new RuntimeException("Bad");
}
}
}
================================================
FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusSubscriberInJarTest.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus;
import org.junit.Assert;
import org.junit.Test;
public class EventBusSubscriberInJarTest {
protected EventBus eventBus = EventBus.builder().build();
@Test
public void testSubscriberInJar() {
SubscriberInJar subscriber = new SubscriberInJar();
eventBus.register(subscriber);
eventBus.post("Hi Jar");
eventBus.post(42);
Assert.assertEquals(1, subscriber.getCollectedStrings().size());
Assert.assertEquals("Hi Jar", subscriber.getCollectedStrings().get(0));
}
}
================================================
FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusSubscriberLegalTest.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
/**
* @author Markus Junginger, greenrobot
*/
public class EventBusSubscriberLegalTest extends AbstractEventBusTest {
@Test
public void testSubscriberLegal() {
eventBus.register(this);
eventBus.post("42");
eventBus.unregister(this);
assertEquals(1, eventCount.intValue());
}
// With build time verification, some of these tests are obsolete (and cause problems during build)
// public void testSubscriberNotPublic() {
// try {
// eventBus.register(new NotPublic());
// fail("Registration of ilegal subscriber successful");
// } catch (EventBusException e) {
// // Expected
// }
// }
// public void testSubscriberStatic() {
// try {
// eventBus.register(new Static());
// fail("Registration of ilegal subscriber successful");
// } catch (EventBusException e) {
// // Expected
// }
// }
public void testSubscriberLegalAbstract() {
eventBus.register(new AbstractImpl());
eventBus.post("42");
assertEquals(1, eventCount.intValue());
}
@Subscribe
public void onEvent(String event) {
trackEvent(event);
}
// public static class NotPublic {
// @Subscribe
// void onEvent(String event) {
// }
// }
public static abstract class Abstract {
@Subscribe
public abstract void onEvent(String event);
}
public class AbstractImpl extends Abstract {
@Override
@Subscribe
public void onEvent(String event) {
trackEvent(event);
}
}
// public static class Static {
// @Subscribe
// public static void onEvent(String event) {
// }
// }
}
================================================
FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/IntTestEvent.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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.
*/
/**
* Simple event storing an int value. More efficient than Integer because of the its flat hierarchy.
*/
package org.greenrobot.eventbus;
public class IntTestEvent {
public final int value;
public IntTestEvent(int value) {
this.value = value;
}
}
================================================
FILE: EventBusTestSubscriberInJar/build.gradle
================================================
apply plugin: "java-library"
group = "de.greenrobot"
version = "3.0.0"
java.sourceCompatibility = JavaVersion.VERSION_1_8
java.targetCompatibility = JavaVersion.VERSION_1_8
configurations {
provided
}
dependencies {
implementation project(":eventbus-java")
annotationProcessor project(":eventbus-annotation-processor")
}
sourceSets {
main {
compileClasspath += configurations.provided
java {
srcDir "src"
}
}
}
compileJava {
options.compilerArgs << "-AeventBusIndex=org.greenrobot.eventbus.InJarIndex"
options.fork = true
}
================================================
FILE: EventBusTestSubscriberInJar/src/org/greenrobot/eventbus/SubscriberInJar.java
================================================
package org.greenrobot.eventbus;
import java.util.ArrayList;
import java.util.List;
/** Helper class used by test inside a jar. */
public class SubscriberInJar {
List collectedStrings = new ArrayList();
@Subscribe
public void collectString(String string) {
collectedStrings.add(string);
}
public List getCollectedStrings() {
return collectedStrings;
}
}
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.
================================================
FILE: README.md
================================================
EventBus
========
[EventBus](https://greenrobot.org/eventbus/) is a publish/subscribe event bus for Android and Java.
[](https://github.com/greenrobot/EventBus/actions)
[](https://twitter.com/greenrobot_de)
EventBus...
* simplifies the communication between components
* decouples event senders and receivers
* performs well with Activities, Fragments, and background threads
* avoids complex and error-prone dependencies and life cycle issues
* makes your code simpler
* is fast
* is tiny (~60k jar)
* is proven in practice by apps with 1,000,000,000+ installs
* has advanced features like delivery threads, subscriber priorities, etc.
EventBus in 3 steps
-------------------
1. Define events:
```java
public static class MessageEvent { /* Additional fields if needed */ }
```
2. Prepare subscribers:
Declare and annotate your subscribing method, optionally specify a [thread mode](https://greenrobot.org/eventbus/documentation/delivery-threads-threadmode/):
```java
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
// Do something
}
```
Register and unregister your subscriber. For example on Android, activities and fragments should usually register according to their life cycle:
```java
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
```
3. Post events:
```java
EventBus.getDefault().post(new MessageEvent());
```
Read the full [getting started guide](https://greenrobot.org/eventbus/documentation/how-to-get-started/).
There are also some [examples](https://github.com/greenrobot-team/greenrobot-examples).
**Note:** we highly recommend the [EventBus annotation processor with its subscriber index](https://greenrobot.org/eventbus/documentation/subscriber-index/).
This will avoid some reflection related problems seen in the wild.
Add EventBus to your project
----------------------------
Available on Maven Central .
Android projects:
```groovy
implementation("org.greenrobot:eventbus:3.3.1")
```
Java projects:
```groovy
implementation("org.greenrobot:eventbus-java:3.3.1")
```
```xml
org.greenrobot
eventbus-java
3.3.1
```
R8, ProGuard
------------
If your project uses R8 or ProGuard this library ships [with embedded rules](/eventbus-android/consumer-rules.pro).
Homepage, Documentation, Links
------------------------------
For more details please check the [EventBus website](https://greenrobot.org/eventbus). Here are some direct links you may find useful:
[Features](https://greenrobot.org/eventbus/features/)
[Documentation](https://greenrobot.org/eventbus/documentation/)
[Changelog](https://github.com/greenrobot/EventBus/releases)
[FAQ](https://greenrobot.org/eventbus/documentation/faq/)
License
-------
Copyright (C) 2012-2021 Markus Junginger, greenrobot (https://greenrobot.org)
EventBus binaries and source code can be used according to the [Apache License, Version 2.0](LICENSE).
Other projects by greenrobot
============================
[__ObjectBox__](https://objectbox.io/) ([GitHub](https://github.com/objectbox/objectbox-java)) is a new superfast object-oriented database.
[__Essentials__](https://github.com/greenrobot/essentials) is a set of utility classes and hash functions for Android & Java projects.
================================================
FILE: build.gradle
================================================
buildscript {
ext {
_compileSdkVersion = 30 // Android 11 (R)
}
repositories {
mavenCentral()
maven { url "https://plugins.gradle.org/m2/" }
}
dependencies {
classpath "io.github.gradle-nexus:publish-plugin:1.1.0"
}
}
// Set group and version in root build.gradle so publish-plugin can detect them.
group = "org.greenrobot"
version = "3.3.1"
allprojects {
repositories {
mavenCentral()
google()
}
}
if (JavaVersion.current().isJava8Compatible()) {
allprojects {
tasks.withType(Javadoc) {
options.addStringOption('Xdoclint:none', '-quiet')
}
}
}
wrapper {
distributionType = Wrapper.DistributionType.ALL
}
// Plugin to publish to Central https://github.com/gradle-nexus/publish-plugin/
// This plugin ensures a separate, named staging repo is created for each build when publishing.
apply plugin: "io.github.gradle-nexus.publish-plugin"
nexusPublishing {
repositories {
sonatype {
if (project.hasProperty("sonatypeUsername") && project.hasProperty("sonatypePassword")) {
println('nexusPublishing credentials supplied.')
username = sonatypeUsername
password = sonatypePassword
} else {
println('nexusPublishing credentials NOT supplied.')
}
}
}
}
================================================
FILE: eventbus-android/.gitignore
================================================
/build
================================================
FILE: eventbus-android/README.md
================================================
# EventBus for Android
Despite its name this module is actually published as `org.greenrobot:eventbus` as an Android library (AAR).
It has a dependency on the Java-only artifact `org.greenrobot:eventbus-java` (JAR) previously available under the `eventbus` name.
Provides an `AndroidComponents` implementation to the Java library if it detects `AndroidComponentsImpl` on the classpath via reflection.
================================================
FILE: eventbus-android/build.gradle
================================================
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
// Note: IntelliJ IDEA 2021.1 only supports up to version 4.1
classpath 'com.android.tools.build:gradle:4.1.3'
}
}
apply plugin: 'com.android.library'
group = rootProject.group
version = rootProject.version
android {
compileSdkVersion _compileSdkVersion
defaultConfig {
minSdkVersion 7
targetSdkVersion 30 // Android 11 (R)
consumerProguardFiles "consumer-rules.pro"
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
api project(":eventbus-java")
}
task sourcesJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
archiveClassifier.set("sources")
}
apply from: rootProject.file("gradle/publish.gradle")
// Set project-specific properties
// https://developer.android.com/studio/build/maven-publish-plugin
// Because the Android components are created only during the afterEvaluate phase, you must
// configure your publications using the afterEvaluate() lifecycle method.
afterEvaluate {
publishing.publications {
mavenJava(MavenPublication) {
artifactId = "eventbus"
from components.release
artifact sourcesJar
pom {
name = "EventBus"
description = "EventBus is a publish/subscribe event bus optimized for Android."
packaging = "aar"
}
}
}
}
================================================
FILE: eventbus-android/consumer-rules.pro
================================================
-keepattributes *Annotation*
-keepclassmembers class * {
@org.greenrobot.eventbus.Subscribe ;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
# If using AsyncExecutord, keep required constructor of default event used.
# Adjust the class name if a custom failure event type is used.
-keepclassmembers class org.greenrobot.eventbus.util.ThrowableFailureEvent {
(java.lang.Throwable);
}
# Accessed via reflection, avoid renaming or removal
-keep class org.greenrobot.eventbus.android.AndroidComponentsImpl
================================================
FILE: eventbus-android/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
================================================
FILE: eventbus-android/src/main/AndroidManifest.xml
================================================
================================================
FILE: eventbus-android/src/main/java/org/greenrobot/eventbus/HandlerPoster.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
public class HandlerPoster extends Handler implements Poster {
private final PendingPostQueue queue;
private final int maxMillisInsideHandleMessage;
private final EventBus eventBus;
private boolean handlerActive;
public HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage) {
super(looper);
this.eventBus = eventBus;
this.maxMillisInsideHandleMessage = maxMillisInsideHandleMessage;
queue = new PendingPostQueue();
}
public void enqueue(Subscription subscription, Object event) {
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
synchronized (this) {
queue.enqueue(pendingPost);
if (!handlerActive) {
handlerActive = true;
if (!sendMessage(obtainMessage())) {
throw new EventBusException("Could not send handler message");
}
}
}
}
@Override
public void handleMessage(Message msg) {
boolean rescheduled = false;
try {
long started = SystemClock.uptimeMillis();
while (true) {
PendingPost pendingPost = queue.poll();
if (pendingPost == null) {
synchronized (this) {
// Check again, this time in synchronized
pendingPost = queue.poll();
if (pendingPost == null) {
handlerActive = false;
return;
}
}
}
eventBus.invokeSubscriber(pendingPost);
long timeInMethod = SystemClock.uptimeMillis() - started;
if (timeInMethod >= maxMillisInsideHandleMessage) {
if (!sendMessage(obtainMessage())) {
throw new EventBusException("Could not send handler message");
}
rescheduled = true;
return;
}
}
} finally {
handlerActive = rescheduled;
}
}
}
================================================
FILE: eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidComponentsImpl.java
================================================
package org.greenrobot.eventbus.android;
/**
* Used via reflection in the Java library by {@link AndroidDependenciesDetector}.
*/
public class AndroidComponentsImpl extends AndroidComponents {
public AndroidComponentsImpl() {
super(new AndroidLogger("EventBus"), new DefaultAndroidMainThreadSupport());
}
}
================================================
FILE: eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidLogger.java
================================================
/*
* Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
*
* 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 org.greenrobot.eventbus.android;
import android.util.Log;
import org.greenrobot.eventbus.Logger;
import java.util.logging.Level;
public class AndroidLogger implements Logger {
private final String tag;
public AndroidLogger(String tag) {
this.tag = tag;
}
public void log(Level level, String msg) {
if (level != Level.OFF) {
Log.println(mapLevel(level), tag, msg);
}
}
public void log(Level level, String msg, Throwable th) {
if (level != Level.OFF) {
// That's how Log does it internally
Log.println(mapLevel(level), tag, msg + "\n" + Log.getStackTraceString(th));
}
}
private int mapLevel(Level level) {
int value = level.intValue();
if (value < 800) { // below INFO
if (value < 500) { // below FINE
return Log.VERBOSE;
} else {
return Log.DEBUG;
}
} else if (value < 900) { // below WARNING
return Log.INFO;
} else if (value < 1000) { // below ERROR
return Log.WARN;
} else {
return Log.ERROR;
}
}
}
================================================
FILE: eventbus-android/src/main/java/org/greenrobot/eventbus/android/DefaultAndroidMainThreadSupport.java
================================================
package org.greenrobot.eventbus.android;
import android.os.Looper;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.HandlerPoster;
import org.greenrobot.eventbus.MainThreadSupport;
import org.greenrobot.eventbus.Poster;
public class DefaultAndroidMainThreadSupport implements MainThreadSupport {
@Override
public boolean isMainThread() {
return Looper.getMainLooper() == Looper.myLooper();
}
@Override
public Poster createPoster(EventBus eventBus) {
return new HandlerPoster(eventBus, Looper.getMainLooper(), 10);
}
}
================================================
FILE: gradle/publish.gradle
================================================
// Configures common publishing settings.
apply plugin: "maven-publish"
apply plugin: "signing"
publishing {
publications {
// Note: Sonatype repo created by publish-plugin, see root build.gradle.
mavenJava(MavenPublication) {
pom {
url = "https://greenrobot.org/eventbus/"
scm {
connection = "scm:git@github.com:greenrobot/EventBus.git"
developerConnection = "scm:git@github.com:greenrobot/EventBus.git"
url = "https://github.com/greenrobot/EventBus"
}
licenses {
license {
name = "The Apache Software License, Version 2.0"
url = "https://www.apache.org/licenses/LICENSE-2.0.txt"
distribution = "repo"
}
}
developers {
developer {
id = "greenrobot"
name = "greenrobot"
}
}
issueManagement {
system = "https://github.com/greenrobot/EventBus/issues"
url = "https://github.com/greenrobot/EventBus/issues"
}
organization {
name = "greenrobot"
url = "https://greenrobot.org"
}
}
}
}
}
// Note: ext to export to scripts applying this script.
ext {
// Signing: in-memory ascii-armored key (CI) or keyring file (dev machine), see https://docs.gradle.org/current/userguide/signing_plugin.html
hasSigningPropertiesKeyFile = {
return (project.hasProperty('signingKeyId')
&& project.hasProperty('signingKeyFile')
&& project.hasProperty('signingPassword'))
}
// Typically via ~/.gradle/gradle.properties; default properties for signing plugin.
hasSigningPropertiesKeyRing = {
return (project.hasProperty('signing.keyId')
&& project.hasProperty('signing.secretKeyRingFile')
&& project.hasProperty('signing.password'))
}
hasSigningProperties = {
return hasSigningPropertiesKeyFile() || hasSigningPropertiesKeyRing()
}
}
signing {
if (hasSigningProperties()) {
if (hasSigningPropertiesKeyFile()) {
println "Configured signing to use key file."
String signingKey = new File(signingKeyFile).text
useInMemoryPgpKeys(signingKeyId, signingKey, signingPassword)
} else if (hasSigningPropertiesKeyRing()) {
println "Configured signing to use key ring."
// Note: using expected property names (see above), no need to configure anything.
}
sign publishing.publications.mavenJava
} else {
println "WARNING: signing properties NOT set, will not sign artifacts."
}
}
================================================
FILE: gradle/wrapper/gradle-wrapper.properties
================================================
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
================================================
FILE: gradlew
================================================
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# 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
#
# https://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.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"
================================================
FILE: gradlew.bat
================================================
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
================================================
FILE: javadoc-style/stylesheet.css
================================================
/* Javadoc style sheet */
/*
Overall document style
*/
@import url('resources/fonts/dejavu.css');
body {
background-color:#ffffff;
color:#353833;
font-family:'DejaVu Sans', Arial, Helvetica, sans-serif;
font-size:14px;
margin:0;
}
a:link, a:visited {
text-decoration:none;
color:#4A6782;
}
a:hover, a:focus {
text-decoration:none;
color:#bb7a2a;
}
a:active {
text-decoration:none;
color:#4A6782;
}
a[name] {
color:#353833;
}
a[name]:hover {
text-decoration:none;
color:#353833;
}
pre {
font-family:'DejaVu Sans Mono', monospace;
font-size:14px;
}
h1 {
font-size:20px;
}
h2 {
font-size:18px;
}
h3 {
font-size:16px;
font-style:italic;
}
h4 {
font-size:13px;
}
h5 {
font-size:12px;
}
h6 {
font-size:11px;
}
ul {
list-style-type:disc;
}
code, tt {
font-family:'DejaVu Sans Mono', monospace;
font-size:14px;
padding-top:4px;
margin-top:8px;
line-height:1.4em;
}
dt code {
font-family:'DejaVu Sans Mono', monospace;
font-size:14px;
padding-top:4px;
}
table tr td dt code {
font-family:'DejaVu Sans Mono', monospace;
font-size:14px;
vertical-align:top;
padding-top:4px;
}
sup {
font-size:8px;
}
/*
Document title and Copyright styles
*/
.clear {
clear:both;
height:0px;
overflow:hidden;
}
.aboutLanguage {
float:right;
padding:0px 21px;
font-size:11px;
z-index:200;
margin-top:-9px;
}
.legalCopy {
margin-left:.5em;
}
.bar a, .bar a:link, .bar a:visited, .bar a:active {
color:#FFFFFF;
text-decoration:none;
}
.bar a:hover, .bar a:focus {
color:#bb7a2a;
}
.tab {
background-color:#0066FF;
color:#ffffff;
padding:8px;
width:5em;
font-weight:bold;
}
/*
Navigation bar styles
*/
.bar {
background-color:#4D974D;
color:#FFFFFF;
padding:.8em .5em .4em .8em;
height:auto;/*height:1.8em;*/
font-size:11px;
margin:0;
}
.topNav {
background-color:#4D974D;
color:#FFFFFF;
float:left;
padding:0;
width:100%;
clear:right;
height:2.8em;
padding-top:10px;
overflow:hidden;
font-size:12px;
}
.bottomNav {
margin-top:10px;
background-color:#4D974D;
color:#FFFFFF;
float:left;
padding:0;
width:100%;
clear:right;
height:2.8em;
padding-top:10px;
overflow:hidden;
font-size:12px;
}
.subNav {
background-color:#dee3e9;
float:left;
width:100%;
overflow:hidden;
font-size:12px;
}
.subNav div {
clear:left;
float:left;
padding:0 0 5px 6px;
text-transform:uppercase;
}
ul.navList, ul.subNavList {
float:left;
margin:0 25px 0 0;
padding:0;
}
ul.navList li{
list-style:none;
float:left;
padding: 5px 6px;
text-transform:uppercase;
}
ul.subNavList li{
list-style:none;
float:left;
}
.topNav a:link, .topNav a:active, .topNav a:visited, .bottomNav a:link, .bottomNav a:active, .bottomNav a:visited {
color:#FFFFFF;
text-decoration:none;
text-transform:uppercase;
}
.topNav a:hover, .bottomNav a:hover {
text-decoration:none;
color:#bb7a2a;
text-transform:uppercase;
}
.navBarCell1Rev {
background-color:#F8981D;
color:#253441;
margin: auto 5px;
}
.skipNav {
position:absolute;
top:auto;
left:-9999px;
overflow:hidden;
}
/*
Page header and footer styles
*/
.header, .footer {
clear:both;
margin:0 20px;
padding:5px 0 0 0;
}
.indexHeader {
margin:10px;
position:relative;
}
.indexHeader span{
margin-right:15px;
}
.indexHeader h1 {
font-size:13px;
}
.title {
color:#2c4557;
margin:10px 0;
}
.subTitle {
margin:5px 0 0 0;
}
.header ul {
margin:0 0 15px 0;
padding:0;
}
.footer ul {
margin:20px 0 5px 0;
}
.header ul li, .footer ul li {
list-style:none;
font-size:13px;
}
/*
Heading styles
*/
div.details ul.blockList ul.blockList ul.blockList li.blockList h4, div.details ul.blockList ul.blockList ul.blockListLast li.blockList h4 {
background-color:#dee3e9;
border:1px solid #d0d9e0;
margin:0 0 6px -8px;
padding:7px 5px;
}
ul.blockList ul.blockList ul.blockList li.blockList h3 {
background-color:#dee3e9;
border:1px solid #d0d9e0;
margin:0 0 6px -8px;
padding:7px 5px;
}
ul.blockList ul.blockList li.blockList h3 {
padding:0;
margin:15px 0;
}
ul.blockList li.blockList h2 {
padding:0px 0 20px 0;
}
/*
Page layout container styles
*/
.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer {
clear:both;
padding:10px 20px;
position:relative;
}
.indexContainer {
margin:10px;
position:relative;
font-size:12px;
}
.indexContainer h2 {
font-size:13px;
padding:0 0 3px 0;
}
.indexContainer ul {
margin:0;
padding:0;
}
.indexContainer ul li {
list-style:none;
padding-top:2px;
}
.contentContainer .description dl dt, .contentContainer .details dl dt, .serializedFormContainer dl dt {
font-size:12px;
font-weight:bold;
margin:10px 0 0 0;
color:#4E4E4E;
}
.contentContainer .description dl dd, .contentContainer .details dl dd, .serializedFormContainer dl dd {
margin:5px 0 10px 0px;
font-size:14px;
font-family:'DejaVu Sans Mono',monospace;
}
.serializedFormContainer dl.nameValue dt {
margin-left:1px;
font-size:1.1em;
display:inline;
font-weight:bold;
}
.serializedFormContainer dl.nameValue dd {
margin:0 0 0 1px;
font-size:1.1em;
display:inline;
}
/*
List styles
*/
ul.horizontal li {
display:inline;
font-size:0.9em;
}
ul.inheritance {
margin:0;
padding:0;
}
ul.inheritance li {
display:inline;
list-style:none;
}
ul.inheritance li ul.inheritance {
margin-left:15px;
padding-left:15px;
padding-top:1px;
}
ul.blockList, ul.blockListLast {
margin:10px 0 10px 0;
padding:0;
}
ul.blockList li.blockList, ul.blockListLast li.blockList {
list-style:none;
margin-bottom:15px;
line-height:1.4;
}
ul.blockList ul.blockList li.blockList, ul.blockList ul.blockListLast li.blockList {
padding:0px 20px 5px 10px;
border:1px solid #ededed;
background-color:#f8f8f8;
}
ul.blockList ul.blockList ul.blockList li.blockList, ul.blockList ul.blockList ul.blockListLast li.blockList {
padding:0 0 5px 8px;
background-color:#ffffff;
border:none;
}
ul.blockList ul.blockList ul.blockList ul.blockList li.blockList {
margin-left:0;
padding-left:0;
padding-bottom:15px;
border:none;
}
ul.blockList ul.blockList ul.blockList ul.blockList li.blockListLast {
list-style:none;
border-bottom:none;
padding-bottom:0;
}
table tr td dl, table tr td dl dt, table tr td dl dd {
margin-top:0;
margin-bottom:1px;
}
/*
Table styles
*/
.overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary {
width:100%;
border-left:1px solid #EEE;
border-right:1px solid #EEE;
border-bottom:1px solid #EEE;
}
.overviewSummary, .memberSummary {
padding:0px;
}
.overviewSummary caption, .memberSummary caption, .typeSummary caption,
.useSummary caption, .constantsSummary caption, .deprecatedSummary caption {
position:relative;
text-align:left;
background-repeat:no-repeat;
color:#253441;
font-weight:bold;
clear:none;
overflow:hidden;
padding:0px;
padding-top:10px;
padding-left:1px;
margin:0px;
white-space:pre;
}
.overviewSummary caption a:link, .memberSummary caption a:link, .typeSummary caption a:link,
.useSummary caption a:link, .constantsSummary caption a:link, .deprecatedSummary caption a:link,
.overviewSummary caption a:hover, .memberSummary caption a:hover, .typeSummary caption a:hover,
.useSummary caption a:hover, .constantsSummary caption a:hover, .deprecatedSummary caption a:hover,
.overviewSummary caption a:active, .memberSummary caption a:active, .typeSummary caption a:active,
.useSummary caption a:active, .constantsSummary caption a:active, .deprecatedSummary caption a:active,
.overviewSummary caption a:visited, .memberSummary caption a:visited, .typeSummary caption a:visited,
.useSummary caption a:visited, .constantsSummary caption a:visited, .deprecatedSummary caption a:visited {
color:#FFFFFF;
}
.overviewSummary caption span, .memberSummary caption span, .typeSummary caption span,
.useSummary caption span, .constantsSummary caption span, .deprecatedSummary caption span {
white-space:nowrap;
padding-top:5px;
padding-left:12px;
padding-right:12px;
padding-bottom:7px;
display:inline-block;
float:left;
background-color:#F8981D;
border: none;
height:16px;
}
.memberSummary caption span.activeTableTab span {
white-space:nowrap;
padding-top:5px;
padding-left:12px;
padding-right:12px;
margin-right:3px;
display:inline-block;
float:left;
background-color:#F8981D;
height:16px;
}
.memberSummary caption span.tableTab span {
white-space:nowrap;
padding-top:5px;
padding-left:12px;
padding-right:12px;
margin-right:3px;
display:inline-block;
float:left;
background-color:#4D974D;
height:16px;
}
.memberSummary caption span.tableTab, .memberSummary caption span.activeTableTab {
padding-top:0px;
padding-left:0px;
padding-right:0px;
background-image:none;
float:none;
display:inline;
}
.overviewSummary .tabEnd, .memberSummary .tabEnd, .typeSummary .tabEnd,
.useSummary .tabEnd, .constantsSummary .tabEnd, .deprecatedSummary .tabEnd {
display:none;
width:5px;
position:relative;
float:left;
background-color:#F8981D;
}
.memberSummary .activeTableTab .tabEnd {
display:none;
width:5px;
margin-right:3px;
position:relative;
float:left;
background-color:#F8981D;
}
.memberSummary .tableTab .tabEnd {
display:none;
width:5px;
margin-right:3px;
position:relative;
background-color:#4D974D;
float:left;
}
.overviewSummary td, .memberSummary td, .typeSummary td,
.useSummary td, .constantsSummary td, .deprecatedSummary td {
text-align:left;
padding:0px 0px 12px 10px;
width:100%;
}
th.colOne, th.colFirst, th.colLast, .useSummary th, .constantsSummary th,
td.colOne, td.colFirst, td.colLast, .useSummary td, .constantsSummary td{
vertical-align:top;
padding-right:0px;
padding-top:8px;
padding-bottom:3px;
}
th.colFirst, th.colLast, th.colOne, .constantsSummary th {
background:#dee3e9;
text-align:left;
padding:8px 3px 3px 7px;
}
td.colFirst, th.colFirst {
white-space:nowrap;
font-size:13px;
}
td.colLast, th.colLast {
font-size:13px;
}
td.colOne, th.colOne {
font-size:13px;
}
.overviewSummary td.colFirst, .overviewSummary th.colFirst,
.overviewSummary td.colOne, .overviewSummary th.colOne,
.memberSummary td.colFirst, .memberSummary th.colFirst,
.memberSummary td.colOne, .memberSummary th.colOne,
.typeSummary td.colFirst{
width:25%;
vertical-align:top;
}
td.colOne a:link, td.colOne a:active, td.colOne a:visited, td.colOne a:hover, td.colFirst a:link, td.colFirst a:active, td.colFirst a:visited, td.colFirst a:hover, td.colLast a:link, td.colLast a:active, td.colLast a:visited, td.colLast a:hover, .constantValuesContainer td a:link, .constantValuesContainer td a:active, .constantValuesContainer td a:visited, .constantValuesContainer td a:hover {
font-weight:bold;
}
.tableSubHeadingColor {
background-color:#EEEEFF;
}
.altColor {
background-color:#FFFFFF;
}
.rowColor {
background-color:#EEEEEF;
}
/*
Content styles
*/
.description pre {
margin-top:0;
}
.deprecatedContent {
margin:0;
padding:10px 0;
}
.docSummary {
padding:0;
}
ul.blockList ul.blockList ul.blockList li.blockList h3 {
font-style:normal;
}
div.block {
font-size:14px;
font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif;
}
td.colLast div {
padding-top:0px;
}
td.colLast a {
padding-bottom:3px;
}
/*
Formatting effect styles
*/
.sourceLineNo {
color:green;
padding:0 30px 0 0;
}
h1.hidden {
visibility:hidden;
overflow:hidden;
font-size:10px;
}
.block {
display:block;
margin:3px 10px 2px 0px;
color:#474747;
}
.deprecatedLabel, .descfrmTypeLabel, .memberNameLabel, .memberNameLink,
.overrideSpecifyLabel, .packageHierarchyLabel, .paramLabel, .returnLabel,
.seeLabel, .simpleTagLabel, .throwsLabel, .typeNameLabel, .typeNameLink {
font-weight:bold;
}
.deprecationComment, .emphasizedPhrase, .interfaceName {
font-style:italic;
}
div.block div.block span.deprecationComment, div.block div.block span.emphasizedPhrase,
div.block div.block span.interfaceName {
font-style:normal;
}
div.contentContainer ul.blockList li.blockList h2{
padding-bottom:0px;
}
================================================
FILE: settings.gradle
================================================
include ':EventBus'
include ':EventBusAnnotationProcessor'
include ':EventBusTestJava'
include ':EventBusTest'
include ':EventBusTestSubscriberInJar'
include ':EventBusPerformance'
include ':eventbus-android'
project(":EventBus").name = "eventbus-java"
project(":EventBusAnnotationProcessor").name = "eventbus-annotation-processor"