/*
* 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 org.apache.flume.source;
import static org.fest.reflect.core.Reflection.field;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import java.util.ArrayList;
import java.util.List;
import junit.framework.Assert;
import junit.framework.TestCase;
import org.apache.flume.ChannelException;
import org.apache.flume.Context;
import org.apache.flume.CounterGroup;
import org.apache.flume.Event;
import org.apache.flume.EventDeliveryException;
import org.apache.flume.PollableSource.Status;
import org.apache.flume.channel.ChannelProcessor;
import org.junit.Before;
import org.junit.Test;
public class TestStressSource {
private ChannelProcessor mockProcessor;
@Before
public void setUp() {
mockProcessor = mock(ChannelProcessor.class);
}
private Event getEvent(StressSource source) {
return field("event").ofType(Event.class)
.in(source)
.get();
}
@SuppressWarnings("unchecked")
private List<Event> getLastProcessedEventList(StressSource source) {
return field("eventBatchListToProcess").ofType(List.class).in(source).get();
}
private CounterGroup getCounterGroup(StressSource source) {
return field("counterGroup").ofType(CounterGroup.class).in(source).get();
}
@Test
public void testMaxTotalEvents() throws InterruptedException,
EventDeliveryException {
StressSource source = new StressSource();
source.setChannelProcessor(mockProcessor);
Context context = new Context();
context.put("maxTotalEvents", "35");
source.configure(context);
source.start();
for (int i = 0; i < 50; i++) {
source.process();
}
verify(mockProcessor, times(35)).processEvent(getEvent(source));
}
@Test
public void testBatchEvents() throws InterruptedException,
EventDeliveryException {
StressSource source = new StressSource();
source.setChannelProcessor(mockProcessor);
Context context = new Context();
context.put("maxTotalEvents", "35");
context.put("batchSize", "10");
source.configure(context);
source.start();
for (int i = 0; i < 50; i++) {
if (source.process() == Status.BACKOFF) {
TestCase.assertTrue("Source should have sent all events in 4 batches", i == 4);
break;
}
if (i < 3) {
verify(mockProcessor,
times(i + 1)).processEventBatch(getLastProcessedEventList(source));
} else {
verify(mockProcessor,
times(1)).processEventBatch(getLastProcessedEventList(source));
}
}
long successfulEvents = getCounterGroup(source).get("events.successful");
TestCase.assertTrue("Number of successful events should be 35 but was " +
successfulEvents, successfulEvents == 35);
long failedEvents = getCounterGroup(source).get("events.failed");
TestCase.assertTrue("Number of failure events should be 0 but was " +
failedEvents, failedEvents == 0);
}
@Test
public void testBatchEventsWithoutMatTotalEvents() throws InterruptedException,
EventDeliveryException {
StressSource source = new StressSource();
source.setChannelProcessor(mockProcessor);
Context context = new Context();
context.put("batchSize", "10");
source.configure(context);
source.start();
for (int i = 0; i < 10; i++) {
Assert.assertFalse("StressSource with no maxTotalEvents should not return " +
Status.BACKOFF, source.process() == Status.BACKOFF);
}
verify(mockProcessor,
times(10)).processEventBatch(getLastProcessedEventList(source));
long successfulEvents = getCounterGroup(source).get("events.successful");
TestCase.assertTrue("Number of successful events should be 100 but was " +
successfulEvents, successfulEvents == 100);
long failedEvents = getCounterGroup(source).get("events.failed");
TestCase.assertTrue("Number of failure events should be 0 but was " +
failedEvents, failedEvents == 0);
}
@Test
public void testMaxSuccessfulEvents() throws InterruptedException,
EventDeliveryException {
StressSource source = new StressSource();
source.setChannelProcessor(mockProcessor);
Context context = new Context();
context.put("maxSuccessfulEvents", "35");
source.configure(context);
source.start();
for (int i = 0; i < 10; i++) {
source.process();
}
// 1 failed call, 10 successful
doThrow(new ChannelException("stub")).when(
mockProcessor).processEvent(getEvent(source));
source.process();
doNothing().when(mockProcessor).processEvent(getEvent(source));
for (int i = 0; i < 10; i++) {
source.process();
}
// 1 failed call, 50 successful
doThrow(new ChannelException("stub")).when(
mockProcessor).processEvent(getEvent(source));
source.process();
doNothing().when(mockProcessor).processEvent(getEvent(source));
for (int i = 0; i < 50; i++) {
source.process();
}
// We should have called processEvent(evt) 37 times, twice for failures
// and twice for successful events.
verify(mockProcessor, times(37)).processEvent(getEvent(source));
}
}