org.epiphanic.instrumentation.performance.AOPMetricGathererIntegrationTest.java Source code

Java tutorial

Introduction

Here is the source code for org.epiphanic.instrumentation.performance.AOPMetricGathererIntegrationTest.java

Source

/**
 * Thoreau: a demonstration library for performance instrumentation.
 *
 * This source is licensed under the MIT license. Please see the distributed license.txt for details.
 */
package org.epiphanic.instrumentation.performance;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * A full-blown, wired up, Springtastic integration test of our {@link org.epiphanic.instrumentation.performance.AOPMetricGatherer},
 * including method interception and a Hibernate configuration. You can more or less take this test and it's
 * configuration and transfer it to your project to use the artifacts from this project.<p/>
 *
 * @author Greg Feigenson
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public final class AOPMetricGathererIntegrationTest {
    /**
     * Holds an autowired-by-name instance of our class under test. We've set up all our object graph and some AOP advice
     * on this class, telling our interceptor {@link org.epiphanic.instrumentation.performance.AOPMetricGatherer} to be
     * intercept our method.
     */
    @Resource
    private IBoringClassWithInstrumentableMethods instrumentedClass;

    /**
     * Holds an injected instance of our {@link javax.sql.DataSource} so that we can query our backing store.
     */
    @Autowired
    private DataSource _dataSource;

    /**
     * Holds an instance of {@link org.springframework.jdbc.core.JdbcTemplate} that we create upon test setup, based on our
     * injected {@link javax.sql.DataSource}. Useful for querying things.
     */
    private JdbcTemplate _jdbcTemplate;

    /**
     * Runs any set up for our unit tests. In this case we create a {@link org.springframework.jdbc.core.JdbcTemplate} for
     * testing our database state later.
     */
    @Before
    public void setUp() throws Exception {
        _jdbcTemplate = new JdbcTemplate(_dataSource);
    }

    /**
     * Given our instrumented class {@link org.epiphanic.instrumentation.performance.BoringClassWithInstrumentableMethods},
     * runs through a set of methods and gathers a set of performance metrics. When done, verifies that we've got what we
     * think we've got.
     */
    @SuppressWarnings("unchecked")
    @Test
    public void testInstrumentation() throws Exception {
        // Run through the methods we've instrumented. 
        instrumentedClass.fibonacciSequenceRecursive(4);
        instrumentedClass.fibonacciSequenceIterative(4);
        instrumentedClass.voidReturningMethodThatDoesNothing();
        instrumentedClass.longRunningObjectCreatingMethod();

        try {
            // We should get some metadata off this method - the stack trace information.
            instrumentedClass.exceptionThrowingMethod();
            Assert.fail();
        } catch (final Exception ex) {
            // We need this to fail.
        }

        // Make sure our writers have a chance to finish.
        Thread.sleep(5000);

        // Pull back our entities from the database then sort it by ID.
        final List<MethodCallStatistic> stats = _jdbcTemplate.query("select * from method_performance",
                (rs, rowNum) -> {
                    final MethodCallStatistic methodCallStatistic = new MethodCallStatistic();

                    methodCallStatistic.setId(rs.getLong("metric_id"));
                    methodCallStatistic.setUserId(rs.getLong("user_id"));
                    methodCallStatistic.setOperationName(rs.getString("operation_name"));
                    methodCallStatistic.setOperationStart(rs.getDate("start_time"));
                    methodCallStatistic.setOperationCompletion(rs.getDate("end_time"));
                    methodCallStatistic.setMetaData(rs.getString("metadata"));
                    methodCallStatistic.setOperationSuccessful(rs.getBoolean("success"));

                    return methodCallStatistic;
                });

        Collections.sort(stats, new Comparator<MethodCallStatistic>() {
            @Override
            public int compare(final MethodCallStatistic lhs, final MethodCallStatistic rhs) {
                return lhs.getId().compareTo(rhs.getId());
            }
        });

        // Verify we've got what we think.
        Assert.assertEquals(5, stats.size());

        verifyEntity(stats.get(0), 1L, "fibonacciSequenceRecursive", null, true);
        verifyEntity(stats.get(1), 2L, "fibonacciSequenceIterative", null, true);
        verifyEntity(stats.get(2), 3L, "voidReturningMethodThatDoesNothing", null, true);
        verifyEntity(stats.get(3), 4L, "longRunningObjectCreatingMethod", null, true);
        verifyEntity(stats.get(4), 5L, "exceptionThrowingMethod",
                "java.lang.Exception: I am the very modern model of a modern Major-General.", false);
    }

    /**
     * A utility method to verify an extracted object vs. what we think should be set on it. In this case we can skip all
     * the dates set on our metric, as well as our user ID.
     *
     * @param statisticToVerify The {@link org.epiphanic.instrumentation.performance.MethodCallStatistic} to verify.
     * @param expectedId What we expect {@link MethodCallStatistic#getId()} to be.
     * @param expectedOperation What we expect {@link MethodCallStatistic#getOperationName()} to be.
     * @param expectedMetadata What we expect {@link MethodCallStatistic#getMetaData()} to be.
     * @param expectedSuccessIndicator What we expect {@link MethodCallStatistic#isOperationSuccessful()} to be.
     */
    private void verifyEntity(final MethodCallStatistic statisticToVerify, final long expectedId,
            final String expectedOperation, final String expectedMetadata, final boolean expectedSuccessIndicator) {
        // This hits both assertEquals(object, object) and assertEquals(long, long) - cast so we can resolve which method
        // to call.
        Assert.assertEquals(expectedId, (long) statisticToVerify.getId());
        Assert.assertEquals(expectedOperation, statisticToVerify.getOperationName());
        Assert.assertEquals(expectedMetadata, statisticToVerify.getMetaData());
        Assert.assertEquals(expectedSuccessIndicator, statisticToVerify.isOperationSuccessful());
    }
}