Skip to content

JMockit does not work with newest versions of JaCoCo plugin #748

@pksilen

Description

@pksilen
  • JDK: 17
  • JMockit Version number: 1.49

Some unit tests throw ArrayIndexOutOfBoundsException when using
newest version 0.8.11 of the JaCoCo plugin. An older version of JaCoCo plugin like 0.8.3 works ok.

The expection is thrown in a test case where I mock a singleton class. If I remove the mocking the test case works ok.

Mocking of the below class in a test case field using the @mocked annotation cause all test cases in the module to fail with
the ArrayIndexOutOfBoundsException :

package com.nokia.cni.exportica.batchwriter.common.metrics;

import com.nokia.cni.exportica.batchwriter.application.config.ApplicationConfig;
import com.nokia.cni.exportica.batchwriter.common.configproperties.ConfigProperties;
import com.nokia.cni.exportica.batchwriter.common.metrics.counter.CounterDescriptions;
import com.nokia.cni.exportica.batchwriter.common.metrics.counter.CounterKey;
import com.nokia.cni.exportica.batchwriter.common.metrics.counter.CounterNames;
import com.nokia.cni.exportica.batchwriter.common.metrics.gauge.GaugeDescriptions;
import com.nokia.cni.exportica.batchwriter.common.metrics.gauge.GaugeKey;
import com.nokia.cni.exportica.batchwriter.common.metrics.gauge.GaugeNames;
import com.nokia.cni.exportica.batchwriter.common.metrics.label.LabelKey;
import com.nokia.cni.exportica.batchwriter.common.metrics.label.LabelNames;
import com.nokia.cni.exportica.batchwriter.messagequeue.MessageQueueConfig;
import com.nokia.cni.exportica.batchwriter.output.file.writer.config.FileWriterConfig;
import io.prometheus.client.Counter;
import io.prometheus.client.Gauge;

import java.util.*;

@SuppressWarnings("UseOfConcreteClass")
public final class Metrics {
    private static Metrics instance;
    final Map<CounterKey, Counter> keyToCounter = new EnumMap<>(CounterKey.class);
    final Map<GaugeKey, Gauge> keyToGauge = new EnumMap<>(GaugeKey.class);
    private final double msgQueueMaxLength;
    private final String productName;
    private final String useCaseName;
    private final String podName;
    private final String outputType;

    public static void createInstance(final ConfigProperties configProperties) {
        if (instance == null) {
            instance = new Metrics(configProperties);
        }
    }

    public static Metrics getInstance() {
        return instance;
    }

    @SuppressWarnings("LawOfDemeter")
    private Metrics(final ConfigProperties configProperties) {
        final var namesConfig = new ApplicationConfig(configProperties).namesConfig;
        productName = namesConfig.productName;
        useCaseName = namesConfig.useCaseName;
        podName = namesConfig.podName;
        outputType = new FileWriterConfig(configProperties).destType;
        msgQueueMaxLength = new MessageQueueConfig(configProperties).maxLength;
        createCounters();
        createGauges();
    }

    public void incrementCounter(final CounterKey key, final long value, final String kafkaTopic) {
        final var counter = keyToCounter.get(key);
        counter.labels(getLabelValues(kafkaTopic)).inc(value);
    }

    public void updateMsgQueueGauges(final int msgQueueLength) {
        keyToGauge.get(GaugeKey.MESSAGE_QUEUE_LENGTH).labels(getLabelValues("")).set(msgQueueLength);
        keyToGauge.get(GaugeKey.MESSAGE_QUEUE_UTILIZATION).labels(getLabelValues("")).set(msgQueueLength / msgQueueMaxLength);
    }

    private void createCounters() {
        Arrays.stream(CounterKey.values()).forEach(counterKey -> keyToCounter.put(counterKey, createCounter(counterKey)));
    }

    private Counter createCounter(final CounterKey counterKey) {
        return Counter.build()
                .name(createProductNamespacedMetricName(CounterNames.get(counterKey)))
                .help(CounterDescriptions.get(counterKey))
                .labelNames(getLabelNames())
                .register();
    }

    private void createGauges() {
        Arrays.stream(GaugeKey.values()).forEach(gaugeKey -> keyToGauge.put(gaugeKey, createGauge(gaugeKey)));
    }

    private Gauge createGauge(final GaugeKey gaugeKey) {
        return Gauge.build()
                .name(createProductNamespacedMetricName(GaugeNames.get(gaugeKey)))
                .help(GaugeDescriptions.get(gaugeKey))
                .labelNames(getLabelNames())
                .register();
    }

    private String createProductNamespacedMetricName(final String metricName) {
        final var productNameInMetricName = productName.replace("-", "_");
        return productNameInMetricName + '_' + metricName;
    }

    private static String[] getLabelNames() {
        return Arrays.stream(LabelKey.values()).map(LabelNames::get).toArray(String[]::new);
    }

    private String[] getLabelValues(final String kafkaTopic) {
        return new String[]{useCaseName, podName, outputType, kafkaTopic};
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions