blob: ee572833adde669f90ae26e9159eea417f3d6d79 [file] [log] [blame]
/*
* Copyright 2017 HugeGraph Authors
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with this
* work for additional information regarding copyright ownership. The ASF
* licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package com.baidu.hugegraph.unit.event;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import com.baidu.hugegraph.event.Event;
import com.baidu.hugegraph.event.EventHub;
import com.baidu.hugegraph.event.EventListener;
import com.baidu.hugegraph.testutil.Assert;
import com.baidu.hugegraph.unit.BaseUnitTest;
import com.google.common.collect.ImmutableList;
public class EventHubTest extends BaseUnitTest {
private static final int THREADS_NUM = 8;
private EventHub eventHub = null;
@BeforeClass
public static void init() {
EventHub.init(THREADS_NUM);
}
@AfterClass
public static void clear() throws InterruptedException {
EventHub.destroy(30);
}
@Before
public void setup() {
this.eventHub = new EventHub("test");
Assert.assertEquals("test", this.eventHub.name());
}
@After
public void teardown() {
this.eventHub = null;
}
private void wait100ms() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
@Test
public void testEventGetListenerNonResult() {
Assert.assertFalse(this.eventHub.containsListener("not-exist"));
Assert.assertEquals(0, this.eventHub.listeners("not-exist").size());
}
@Test
public void testEventAddListener() {
final String event = "event-test";
EventListener listener = new EventListener() {
@Override
public Object event(Event arg0) {
return null;
}
};
this.eventHub.listen(event, listener);
Assert.assertTrue(this.eventHub.containsListener(event));
Assert.assertEquals(1, this.eventHub.listeners(event).size());
Assert.assertEquals(listener, this.eventHub.listeners(event).get(0));
}
@Test
public void testEventAddListenerTwice() {
final String event = "event-test";
EventListener listener = new EventListener() {
@Override
public Object event(Event arg0) {
return null;
}
};
this.eventHub.listen(event, listener);
this.eventHub.listen(event, listener);
Assert.assertTrue(this.eventHub.containsListener(event));
Assert.assertEquals(2, this.eventHub.listeners(event).size());
Assert.assertEquals(listener, this.eventHub.listeners(event).get(0));
Assert.assertEquals(listener, this.eventHub.listeners(event).get(1));
}
@Test
public void testEventRemoveListener() {
final String event = "event-test";
EventListener listener = new EventListener() {
@Override
public Object event(Event arg0) {
return null;
}
};
this.eventHub.listen(event, listener);
Assert.assertTrue(this.eventHub.containsListener(event));
Assert.assertEquals(1, this.eventHub.listeners(event).size());
Assert.assertEquals(listener, this.eventHub.listeners(event).get(0));
Assert.assertEquals(1, this.eventHub.unlisten(event, listener));
Assert.assertFalse(this.eventHub.containsListener(event));
Assert.assertEquals(0, this.eventHub.listeners(event).size());
}
@Test
public void testEventRemoveListenerButNonResult() {
final String event = "event-test";
EventListener listener = new EventListener() {
@Override
public Object event(Event arg0) {
return null;
}
};
this.eventHub.listen(event, listener);
Assert.assertTrue(this.eventHub.containsListener(event));
Assert.assertEquals(1, this.eventHub.listeners(event).size());
Assert.assertEquals(listener, this.eventHub.listeners(event).get(0));
Assert.assertEquals(0, this.eventHub.unlisten(event, null));
Assert.assertEquals(0, this.eventHub.unlisten("event-fake", listener));
Assert.assertTrue(this.eventHub.containsListener(event));
Assert.assertEquals(1, this.eventHub.listeners(event).size());
Assert.assertEquals(listener, this.eventHub.listeners(event).get(0));
}
@Test
public void testEventRemoveListenerOfOneInTwo() {
final String event1 = "event-test1";
final String event2 = "event-test2";
EventListener listener = new EventListener() {
@Override
public Object event(Event arg0) {
return null;
}
};
this.eventHub.listen(event1, listener);
this.eventHub.listen(event2, listener);
Assert.assertTrue(this.eventHub.containsListener(event1));
Assert.assertEquals(1, this.eventHub.listeners(event1).size());
Assert.assertEquals(listener, this.eventHub.listeners(event1).get(0));
Assert.assertTrue(this.eventHub.containsListener(event2));
Assert.assertEquals(1, this.eventHub.listeners(event2).size());
Assert.assertEquals(listener, this.eventHub.listeners(event2).get(0));
Assert.assertEquals(1, this.eventHub.unlisten(event1, listener));
Assert.assertFalse(this.eventHub.containsListener(event1));
Assert.assertFalse(this.eventHub.containsListener(event1));
Assert.assertEquals(0, this.eventHub.listeners(event1).size());
Assert.assertTrue(this.eventHub.containsListener(event2));
Assert.assertEquals(1, this.eventHub.listeners(event2).size());
Assert.assertEquals(listener, this.eventHub.listeners(event2).get(0));
}
@Test
public void testEventRemoveListenerByEvent() {
final String event = "event-test";
EventListener listener1 = new EventListener() {
@Override
public Object event(Event arg0) {
return null;
}
};
EventListener listener2 = new EventListener() {
@Override
public Object event(Event arg0) {
return null;
}
};
this.eventHub.listen(event, listener1);
this.eventHub.listen(event, listener2);
Assert.assertTrue(this.eventHub.containsListener(event));
Assert.assertEquals(2, this.eventHub.listeners(event).size());
Assert.assertEquals(listener1, this.eventHub.listeners(event).get(0));
Assert.assertEquals(listener2, this.eventHub.listeners(event).get(1));
Assert.assertEquals(2, this.eventHub.unlisten(event).size());
Assert.assertFalse(this.eventHub.containsListener(event));
Assert.assertEquals(0, this.eventHub.listeners(event).size());
}
@Test
public void testEventRemoveListenerByEventButNonResult() {
final String event = "event-test";
EventListener listener1 = new EventListener() {
@Override
public Object event(Event arg0) {
return null;
}
};
EventListener listener2 = new EventListener() {
@Override
public Object event(Event arg0) {
return null;
}
};
this.eventHub.listen(event, listener1);
this.eventHub.listen(event, listener2);
Assert.assertTrue(this.eventHub.containsListener(event));
Assert.assertEquals(2, this.eventHub.listeners(event).size());
Assert.assertEquals(listener1, this.eventHub.listeners(event).get(0));
Assert.assertEquals(listener2, this.eventHub.listeners(event).get(1));
Assert.assertEquals(0, this.eventHub.unlisten("event-fake").size());
Assert.assertEquals(2, this.eventHub.listeners(event).size());
}
@Test
public void testEventRemoveListenerByEventOf2SameListener() {
final String event = "event-test";
EventListener listener = new EventListener() {
@Override
public Object event(Event arg0) {
return null;
}
};
this.eventHub.listen(event, listener);
this.eventHub.listen(event, listener);
Assert.assertTrue(this.eventHub.containsListener(event));
Assert.assertEquals(2, this.eventHub.listeners(event).size());
Assert.assertEquals(listener, this.eventHub.listeners(event).get(0));
Assert.assertEquals(2, this.eventHub.unlisten(event, listener));
Assert.assertFalse(this.eventHub.containsListener(event));
Assert.assertEquals(0, this.eventHub.listeners(event).size());
}
@Test
public void testEventCallWithoutArg() {
final String call = "event-call";
this.eventHub.listen(call, event -> {
Assert.assertEquals(call, event.name());
Assert.assertEquals(0, event.args().length);
return "fake-event-result";
});
Assert.assertEquals("fake-event-result", this.eventHub.call(call));
}
@Test
public void testEventCallWithArg1() {
final String call = "event-call";
this.eventHub.listen(call, event -> {
Assert.assertEquals(call, event.name());
event.checkArgs(Float.class);
Object[] args = event.args();
Assert.assertEquals(1, args.length);
Assert.assertEquals(3.14f, args[0]);
return "fake-event-result";
});
Assert.assertEquals("fake-event-result",
this.eventHub.call(call, 3.14f));
}
@Test
public void testEventCallWithArg2() {
final String call = "event-call";
this.eventHub.listen(call, event -> {
Assert.assertEquals(call, event.name());
event.checkArgs(String.class, Integer.class);
Object[] args = event.args();
Assert.assertEquals(2, args.length);
Assert.assertEquals("fake-arg0", args[0]);
Assert.assertEquals(123, args[1]);
return "fake-event-result";
});
Assert.assertEquals("fake-event-result",
this.eventHub.call(call, "fake-arg0", 123));
}
@Test
public void testEventCallWithArg2ButArgNotMatched() {
final String call = "event-call";
this.eventHub.listen(call, event -> {
Assert.assertEquals(call, event.name());
event.checkArgs(String.class, Integer.class);
Object[] args = event.args();
Assert.assertEquals(2, args.length);
Assert.assertEquals("fake-arg0", args[0]);
Assert.assertEquals(123, args[1]);
return "fake-event-result";
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
this.eventHub.call(call, "fake-arg0");
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
this.eventHub.call(call, "fake-arg0", 123, "456");
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
this.eventHub.call(call, 123, "fake-arg0");
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
this.eventHub.call(call, "fake-arg0", 123f);
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
this.eventHub.call(call, "fake-arg0", "123");
});
}
@Test
public void testEventNotify() {
final String notify = "event-notify";
AtomicInteger count = new AtomicInteger();
this.eventHub.listen(notify, event -> {
Assert.assertEquals(notify, event.name());
Assert.assertEquals(0, event.args().length);
count.incrementAndGet();
return true;
});
this.eventHub.notify(notify);
// Maybe should improve
this.wait100ms();
Assert.assertEquals(1, count.get());
}
@Test
public void testEventNotifyAny() {
AtomicInteger count = new AtomicInteger();
this.eventHub.listen(EventHub.ANY_EVENT, event -> {
Assert.assertTrue(ImmutableList.of("event1", "event2")
.contains(event.name()));
Assert.assertEquals(0, event.args().length);
count.incrementAndGet();
return true;
});
this.eventHub.notify("event1");
this.eventHub.notify("event2");
// Maybe should improve
this.wait100ms();
Assert.assertEquals(2, count.get());
}
@Test
public void testEventNotifyWithArg2() {
final String notify = "event-notify";
AtomicInteger count = new AtomicInteger();
this.eventHub.listen(notify, event -> {
Assert.assertEquals(notify, event.name());
event.checkArgs(String.class, Integer.class);
Object[] args = event.args();
Assert.assertEquals("fake-arg0", args[0]);
Assert.assertEquals(123, args[1]);
count.incrementAndGet();
return true;
});
this.eventHub.notify(notify, "fake-arg0", 123);
// Maybe should improve
this.wait100ms();
Assert.assertEquals(1, count.get());
}
@Test
public void testEventNotifyWithMultiThreads() throws InterruptedException {
final String notify = "event-notify";
EventListener listener1 = new EventListener() {
@Override
public Object event(Event event) {
Assert.assertEquals(notify, event.name());
event.checkArgs(Integer.class);
return null;
}
};
EventListener listener2 = new EventListener() {
@Override
public Object event(Event event) {
Assert.assertEquals(notify, event.name());
event.checkArgs(Integer.class);
int i = (int) event.args()[0];
if (i % 10000 == 0) {
System.out.println("On event '" + notify + "': " + i);
}
return null;
}
};
Thread listenerUpdateThread = new Thread(() -> {
// This will cost about 1s
for (int i = 0; i < 10; i++) {
this.eventHub.listen(notify, listener1);
if (!this.eventHub.listeners(notify).contains(listener2)) {
this.eventHub.listen(notify, listener2);
}
this.wait100ms();
if (i % 2 == 0) {
this.eventHub.unlisten(notify);
} else {
this.eventHub.unlisten(notify, listener1);
}
}
});
listenerUpdateThread.start();
runWithThreads(THREADS_NUM, () -> {
// This will cost about 1s ~ 2s
for (int i = 0; i < 10000 * 10; i++) {
this.eventHub.notify(notify, i);
Thread.yield();
}
});
listenerUpdateThread.join();
}
@Test
public void testEventCallWithMultiThreads() {
final String call = "event-call";
EventListener listener = new EventListener() {
@Override
public Object event(Event event) {
Assert.assertEquals(call, event.name());
event.checkArgs(Integer.class);
int i = (int) event.args()[0];
return i;
}
};
this.eventHub.listen(call, listener);
runWithThreads(THREADS_NUM, () -> {
for (int i = 0; i < 10000 * 1000; i++) {
Assert.assertEquals(i, this.eventHub.call(call, i));
}
});
}
}