com.sixt.service.framework.servicetest.eventing.ServiceTestEventHandler.java Source code

Java tutorial

Introduction

Here is the source code for com.sixt.service.framework.servicetest.eventing.ServiceTestEventHandler.java

Source

/**
 * Copyright 2016-2017 Sixt GmbH & Co. Autovermietung KG
 * Licensed under the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may obtain a
 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */

package com.sixt.service.framework.servicetest.eventing;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.google.protobuf.Message;
import com.sixt.service.framework.kafka.EventReceivedCallback;
import com.sixt.service.framework.kafka.KafkaSubscriber;
import com.sixt.service.framework.kafka.KafkaSubscriberFactory;
import com.sixt.service.framework.kafka.KafkaTopicInfo;
import com.sixt.service.framework.protobuf.ProtobufUtil;
import com.sixt.service.framework.util.Sleeper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.concurrent.*;
import java.util.function.Predicate;

@Singleton
public class ServiceTestEventHandler implements EventReceivedCallback<String> {

    private static final Logger logger = LoggerFactory.getLogger(ServiceTestEventHandler.class);

    private static final String GROUP_ID = "service-integration-test";
    private static final int TIMEOUT = 30;
    private final static int POLL_TIME = 200;
    private final static int CORE_POOL_SIZE = 1;
    private final static int MAX_POOL_SIZE = 1;
    private final static int KEEP_ALIVE_TIME = 15;

    private final KafkaSubscriberFactory<String> subscriberFactory;
    @VisibleForTesting
    protected KafkaSubscriber kafkaSubscriber;
    private ConcurrentLinkedQueue<JsonObject> readEvents = new ConcurrentLinkedQueue<>();

    @Inject
    public ServiceTestEventHandler(KafkaSubscriberFactory<String> kafkaFactory) {
        this.subscriberFactory = kafkaFactory;
    }

    public void initialize(String topic) {
        this.kafkaSubscriber = subscriberFactory.newBuilder(topic, this).withPollTime(POLL_TIME)
                .withGroupId(GROUP_ID).withThreadPool(CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME).build();
    }

    @Override
    public void eventReceived(String message, KafkaTopicInfo topicInfo) {
        if (message == null) {
            logger.debug("Received kafka message from topic {} with null body", topicInfo.getTopic());
        } else {
            JsonObject jsonObject = new JsonParser().parse(message).getAsJsonObject();
            readEvents.add(jsonObject);
            kafkaSubscriber.consume(topicInfo);
        }
    }

    public void clearReadEvents() {
        readEvents.clear();
    }

    public List<JsonObject> getAllJsonEvents() {
        List<JsonObject> foundEvents = new ArrayList<>();
        while (!readEvents.isEmpty()) {
            JsonObject poll = readEvents.poll();
            if (poll != null) {
                foundEvents.add(poll);
            }
        }

        logger.info("Found {} events", foundEvents.size());

        return foundEvents;
    }

    public <TYPE extends Message> List<TYPE> getEventsOfType(String eventName, Class<TYPE> eventClass) {
        List<TYPE> foundEvents = new ArrayList<>();

        if (eventName != null && eventClass != null) {
            List<JsonObject> capturedEvents = Arrays.asList(readEvents.toArray(new JsonObject[0]));

            for (JsonObject event : capturedEvents) {
                logger.info("Found event: " + event.toString());
                if (EventUtils.getEventName(event).equals(eventName)) {
                    foundEvents.add(ProtobufUtil.jsonToProtobuf(event.toString(), eventClass));
                    readEvents.remove(event);
                }
            }
        } else {
            logger.error("Event name or event class is null");
        }
        return foundEvents;
    }

    public <TYPE extends Message> List<TYPE> getEventsOfType(Class<TYPE> eventClass) {
        List<TYPE> foundEvents = new ArrayList<>();

        if (eventClass != null) {
            List<JsonObject> capturedEvents = Arrays.asList(readEvents.toArray(new JsonObject[0]));

            for (JsonObject event : capturedEvents) {
                logger.info("Found event: " + event.toString());
                if (EventUtils.getEventName(event).equals(eventClass.getSimpleName())) {
                    foundEvents.add(ProtobufUtil.jsonToProtobuf(event.toString(), eventClass));
                    readEvents.remove(event);
                }
            }
        } else {
            logger.error("Event class is null");
        }
        return foundEvents;
    }

    @SuppressWarnings("unchecked")
    public <T> T getEvent(String eventName, Class eventClass, Predicate<T> predicate, long timeout) {
        long start = System.currentTimeMillis();

        while (System.currentTimeMillis() - start < timeout) {
            //the reversing is for starting with the newest events
            List<T> events = Lists.reverse(getEventsOfType(eventName, eventClass));
            for (T event : events) {
                if (predicate.test(event)) {
                    return event;
                }
            }
            new Sleeper().sleepNoException(10);
        }
        logger.error("The event {} is not found after {} ms", eventName, timeout);
        return null;
    }

    public Map<String, Message> getExpectedEvents(Map<String, Class> expectedEvents) {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future<Map<String, Message>> future = executor.submit(new EventFinder(this, expectedEvents));
        Map<String, Message> foundEvents = new HashMap<>();

        try {
            foundEvents = future.get(TIMEOUT, TimeUnit.SECONDS);
        } catch (Exception ex) {
            logger.error("Could not find expected events: " + expectedEvents.keySet(), ex);
            future.cancel(true);
        }

        executor.shutdownNow();

        // We clear the expected events to be ready for the next testcase
        expectedEvents.clear();

        return foundEvents;
    }
}