2121import org .apache .drill .PlanTestBase ;
2222import org .apache .drill .test .BaseDirTestWatcher ;
2323import org .junit .AfterClass ;
24+ import org .junit .Assume ;
2425import org .junit .BeforeClass ;
2526import org .junit .runner .Description ;
2627import org .slf4j .Logger ;
3233/**
3334 * Base class for Hive test. Takes care of generating and adding Hive test plugin before tests and deleting the
3435 * plugin after tests. Now uses Docker-based Hive for compatibility with Java 11+.
36+ *
37+ * <p>Tests are automatically skipped if Docker is not available or container fails to start.
3538 */
3639public class HiveTestBase extends PlanTestBase {
3740
3841 private static final Logger logger = LoggerFactory .getLogger (HiveTestBase .class );
3942
40- public static final HiveTestFixture HIVE_TEST_FIXTURE ;
41- public static final HiveContainer HIVE_CONTAINER ;
43+ // Lazy initialization - container is started only when needed
44+ private static HiveTestFixture hiveTestFixture ;
45+ private static HiveContainer hiveContainer ;
46+ private static String initializationError ;
47+ private static boolean initialized = false ;
48+ private static BaseDirTestWatcher generalDirWatcher ;
49+
50+ // Public accessors for backward compatibility
51+ public static HiveTestFixture HIVE_TEST_FIXTURE ;
52+ public static HiveContainer HIVE_CONTAINER ;
4253
43- static {
44- // generate hive data common for all test classes using own dirWatcher
45- BaseDirTestWatcher generalDirWatcher = new BaseDirTestWatcher () {
54+ /**
55+ * Initializes the Hive Docker container and test fixture.
56+ * This is called lazily to avoid blocking class loading if Docker is unavailable.
57+ */
58+ private static synchronized void initializeHiveInfrastructure () {
59+ if (initialized ) {
60+ return ;
61+ }
62+ initialized = true ;
63+
64+ generalDirWatcher = new BaseDirTestWatcher () {
4665 {
47- /*
48- Below protected method invoked to create directory DirWatcher.dir with path like:
49- ./target/org.apache.drill.exec.hive.HiveTestBase123e4567-e89b-12d3-a456-556642440000.
50- Then subdirectory with name 'root' will be used to hold test data shared between
51- all derivatives of the class. Note that UUID suffix is necessary to avoid conflicts between forked JVMs.
52- */
66+ /*
67+ * Below protected method invoked to create directory DirWatcher.dir with path like:
68+ * ./target/org.apache.drill.exec.hive.HiveTestBase123e4567-e89b-12d3-a456-556642440000.
69+ * Then subdirectory with name 'root' will be used to hold test data shared between
70+ * all derivatives of the class. Note that UUID suffix is necessary to avoid conflicts between forked JVMs.
71+ */
5372 starting (Description .createSuiteDescription (HiveTestBase .class .getName ().concat (UUID .randomUUID ().toString ())));
5473 }
5574 };
5675
5776 try {
77+ // Check if Docker is available first
78+ if (!HiveContainer .isDockerAvailable ()) {
79+ initializationError = "Docker is not available. Hive tests will be skipped." ;
80+ logger .warn (initializationError );
81+ return ;
82+ }
83+
84+ // Warn about ARM64 performance
85+ if (HiveContainer .isArm64 ()) {
86+ System .out .println ("WARNING: Running on ARM64 architecture." );
87+ System .out .println ("Hive Docker tests use x86 emulation and may take 15-30 minutes to start." );
88+ System .out .println ("Consider skipping these tests with: mvn test -Dhive.test.excludedGroups=org.apache.drill.categories.HiveStorageTest" );
89+ }
90+
5891 // Get shared Docker container instance (starts on first access)
5992 logger .info ("Getting shared Hive Docker container for tests" );
60- HIVE_CONTAINER = HiveContainer .getInstance ();
93+ hiveContainer = HiveContainer .getInstance ();
94+ HIVE_CONTAINER = hiveContainer ;
6195 logger .info ("Hive container ready" );
6296
6397 System .out .println ("Configuring Hive storage plugin for Drill..." );
6498 long setupStart = System .currentTimeMillis ();
6599
66100 File baseDir = generalDirWatcher .getRootDir ();
67- HIVE_TEST_FIXTURE = HiveTestFixture .builderForDocker (baseDir , HIVE_CONTAINER ).build ();
101+ hiveTestFixture = HiveTestFixture .builderForDocker (baseDir , hiveContainer ).build ();
102+ HIVE_TEST_FIXTURE = hiveTestFixture ;
68103
69104 // Note: Test data generation for Docker-based Hive will be done via JDBC in individual tests
70105 // or test setup methods as needed, since we can't use embedded Hive Driver
@@ -79,20 +114,28 @@ public class HiveTestBase extends PlanTestBase {
79114 // Note: Container is shared singleton, will be cleaned up by Testcontainers
80115 }));
81116 } catch (Exception e ) {
82- logger .error ("Failed to initialize Hive container" , e );
83- throw new RuntimeException ("Failed to initialize Hive test infrastructure" , e );
117+ initializationError = "Failed to initialize Hive container: " + e .getMessage ();
118+ logger .error (initializationError , e );
119+ // Don't throw - let tests be skipped gracefully
84120 }
85121 }
86122
87123 @ BeforeClass
88124 public static void setUp () {
89- HIVE_TEST_FIXTURE .getPluginManager ().addHivePluginTo (bits );
125+ // Initialize lazily
126+ initializeHiveInfrastructure ();
127+
128+ // Skip tests if initialization failed
129+ Assume .assumeTrue ("Hive infrastructure not available: " + initializationError ,
130+ initializationError == null && hiveTestFixture != null );
131+
132+ hiveTestFixture .getPluginManager ().addHivePluginTo (bits );
90133 }
91134
92135 @ AfterClass
93136 public static void tearDown () {
94- if (HIVE_TEST_FIXTURE != null ) {
95- HIVE_TEST_FIXTURE .getPluginManager ().removeHivePluginFrom (bits );
137+ if (hiveTestFixture != null ) {
138+ hiveTestFixture .getPluginManager ().removeHivePluginFrom (bits );
96139 }
97140 }
98141}
0 commit comments