Back to Repositories

Testing Bootstrap Configuration and ClassLoader Enhancement in Arthas

A comprehensive unit test suite for the Arthas Bootstrap functionality, focusing on class loader enhancement, configuration resolution, and environment setup. This test class validates core initialization and configuration handling in the Arthas diagnostic tool.

Test Coverage Overview

The test suite provides extensive coverage of the ArthasBootstrap class functionality.

Key areas tested include:
  • ClassLoader enhancement and SpyAPI integration
  • Configuration location resolution
  • Configuration name handling
  • Environment property management
Edge cases cover null configuration scenarios and property resolution with system variables.

Implementation Analysis

The testing approach employs JUnit with Mockito for robust mocking capabilities. The implementation uses ByteBuddy for instrumentation and reflection utilities for accessing private fields.

Notable patterns include:
  • Mock object manipulation with Mockito
  • Reflection-based field access
  • Java version compatibility checks
  • Instrumentation setup using ByteBuddy

Technical Details

Testing tools and configuration:
  • JUnit 4 test framework
  • Mockito mocking framework
  • ByteBuddy for Java agent installation
  • AssertJ for assertions
  • JBoss Modules for class loading tests
  • Custom TestHelper utilities

Best Practices Demonstrated

The test suite exemplifies high-quality testing practices with thorough setup and verification.

Notable practices include:
  • Proper test isolation using @Before
  • Comprehensive mock object setup
  • Clear test method naming
  • Proper cleanup of system properties
  • Validation of both success and failure scenarios

alibaba/arthas

core/src/test/java/com/taobao/arthas/core/server/ArthasBootstrapTest.java

            
package com.taobao.arthas.core.server;

import static org.assertj.core.api.Assertions.assertThat;

import java.lang.instrument.Instrumentation;
import java.lang.reflect.Field;

import org.jboss.modules.ModuleClassLoader;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;

import com.alibaba.bytekit.utils.ReflectionUtils;
import com.taobao.arthas.common.JavaVersionUtils;
import com.taobao.arthas.core.bytecode.TestHelper;
import com.taobao.arthas.core.config.Configure;
import com.taobao.arthas.core.env.ArthasEnvironment;

import net.bytebuddy.agent.ByteBuddyAgent;

/**
 * 
 * @author hengyunabc 2020-12-02
 *
 */
public class ArthasBootstrapTest {
    @Before
    public void beforeMethod() {
        // jboss modules need jdk8
        org.junit.Assume.assumeTrue(JavaVersionUtils.isGreaterThanJava7());
    }

    @Test
    public void test() throws Exception {
        Instrumentation instrumentation = ByteBuddyAgent.install();
        TestHelper.appendSpyJar(instrumentation);

        ArthasBootstrap arthasBootstrap = Mockito.mock(ArthasBootstrap.class);
        Mockito.doCallRealMethod().when(arthasBootstrap).enhanceClassLoader();

        Configure configure = Mockito.mock(Configure.class);
        Mockito.when(configure.getEnhanceLoaders())
                .thenReturn("java.lang.ClassLoader,org.jboss.modules.ConcurrentClassLoader");
        Field configureField = ArthasBootstrap.class.getDeclaredField("configure");
        configureField.setAccessible(true);
        ReflectionUtils.setField(configureField, arthasBootstrap, configure);

        Field instrumentationField = ArthasBootstrap.class.getDeclaredField("instrumentation");
        instrumentationField.setAccessible(true);
        ReflectionUtils.setField(instrumentationField, arthasBootstrap, instrumentation);

        org.jboss.modules.ModuleClassLoader moduleClassLoader = Mockito.mock(ModuleClassLoader.class);

        boolean flag = false;
        try {
            moduleClassLoader.loadClass("java.arthas.SpyAPI");
        } catch (Exception e) {
            flag = true;
        }
        assertThat(flag).isTrue();

        arthasBootstrap.enhanceClassLoader();

        Class<?> loadClass = moduleClassLoader.loadClass("java.arthas.SpyAPI");

        System.err.println(loadClass);

    }

    @Test
    public void testConfigLocationNull() throws Exception {
        ArthasEnvironment arthasEnvironment = new ArthasEnvironment();
        String location = ArthasBootstrap.reslove(arthasEnvironment, ArthasBootstrap.CONFIG_LOCATION_PROPERTY, null);
        assertThat(location).isEqualTo(null);
    }

    @Test
    public void testConfigLocation() throws Exception {
        ArthasEnvironment arthasEnvironment = new ArthasEnvironment();

        System.setProperty("hhhh", "fff");
        System.setProperty(ArthasBootstrap.CONFIG_LOCATION_PROPERTY, "test${hhhh}");

        String location = ArthasBootstrap.reslove(arthasEnvironment, ArthasBootstrap.CONFIG_LOCATION_PROPERTY, null);
        System.clearProperty("hhhh");
        System.clearProperty(ArthasBootstrap.CONFIG_LOCATION_PROPERTY);

        assertThat(location).isEqualTo("test" + "fff");
    }

    @Test
    public void testConfigNameDefault() throws Exception {
        ArthasEnvironment arthasEnvironment = new ArthasEnvironment();

        String configName = ArthasBootstrap.reslove(arthasEnvironment, ArthasBootstrap.CONFIG_NAME_PROPERTY, "arthas");
        assertThat(configName).isEqualTo("arthas");
    }

    @Test
    public void testConfigName() throws Exception {
        ArthasEnvironment arthasEnvironment = new ArthasEnvironment();

        System.setProperty(ArthasBootstrap.CONFIG_NAME_PROPERTY, "testName");
        String configName = ArthasBootstrap.reslove(arthasEnvironment, ArthasBootstrap.CONFIG_NAME_PROPERTY, "arthas");
        System.clearProperty(ArthasBootstrap.CONFIG_NAME_PROPERTY);
        assertThat(configName).isEqualTo("testName");
    }
}