Repository: open-telemetry/opentelemetry-java
File: sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkTest.java (Java)

Code before:
                        (sdk, exc) -> {
                          if (exc != null) {
                            Assertions.fail(exc);
                          } else {
                            try {
                              gotGetResult.put(sdk);
                            } catch (InterruptedException exception) {
                              Thread.currentThread().interrupt();
                              Assertions.fail(exception);
                            }
                          }
                          return null;
                        });
                // Give Thread 2 some time to try obtaining the mutex and getting blocked
                Thread.sleep(500);
                return invocation.callRealMethod();
              });

      AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk =
          builder.setResultAsGlobal().build();

      assertThat(gotGetResult.poll(3, TimeUnit.SECONDS))
          .extracting("delegate")
          .isSameAs(autoConfiguredOpenTelemetrySdk.getOpenTelemetrySdk());
    }
  }
}


Review comment (suggestion):
Here's a version that avoids static mocks:
```suggestion
  @Test
  void globalOpenTelemetryLock() throws InterruptedException, ExecutionException, TimeoutException {
    CountDownLatch autoconfigStarted = new CountDownLatch(1);
    CountDownLatch completeAutoconfig = new CountDownLatch(1);
    ExecutorService executorService = Executors.newFixedThreadPool(2);

    // Submit a future to autoconfigure the SDK and set the result as global. Add a customization
    // hook which blocks until we say so.
    CompletableFuture<OpenTelemetrySdk> autoConfiguredOpenTelemetryFuture =
        CompletableFuture.supplyAsync(
            () ->
                builder
                    .addLoggerProviderCustomizer(
                        (sdkLoggerProviderBuilder, configProperties) -> {
                          autoconfigStarted.countDown();
                          try {
                            completeAutoconfig.await();
                          } catch (InterruptedException e) {
                            Thread.currentThread().interrupt();
                          }
                          return sdkLoggerProviderBuilder;
                        })
                    .setResultAsGlobal()
                    .build()
                    .getOpenTelemetrySdk(),
            executorService);

    // Wait for autoconfiguration to enter our callback, then try to get an instance of
    // GlobalOpenTelemetry. GlobalOpenTelemetry.get() should block until we release the
    // completeAutoconfig latch and allow autoconfiguration to complete.
    autoconfigStarted.await();
    CompletableFuture<OpenTelemetry> globalOpenTelemetryFuture =
        CompletableFuture.supplyAsync(GlobalOpenTelemetry::get, executorService);
    Thread.sleep(10);
    assertThat(globalOpenTelemetryFuture.isDone()).isFalse();
    assertThat(autoConfiguredOpenTelemetryFuture.isDone()).isFalse();

    // Release the latch, allowing autoconfiguration to complete. Confirm that our
    // GlobalOpenTelemetry.get() future resolved to the same instance as autoconfiguration.
    completeAutoconfig.countDown();
    assertThat(unobfuscate(globalOpenTelemetryFuture.get(10, TimeUnit.SECONDS)))
        .isSameAs(autoConfiguredOpenTelemetryFuture.get(10, TimeUnit.SECONDS));

    // Cleanup
    executorService.shutdown();
    autoConfiguredOpenTelemetryFuture.get().shutdown().join(10, TimeUnit.SECONDS);
    GlobalOpenTelemetry.resetForTest();
  }

  private static OpenTelemetry unobfuscate(OpenTelemetry openTelemetry) {
    try {
      Field delegateField =
          Class.forName("io.opentelemetry.api.GlobalOpenTelemetry$ObfuscatedOpenTelemetry")
              .getDeclaredField("delegate");
      delegateField.setAccessible(true);
      Object delegate = delegateField.get(openTelemetry);
      return (OpenTelemetry) delegate;
    } catch (NoSuchFieldException | IllegalAccessException | ClassNotFoundException e) {
      throw new IllegalStateException("Error unobfuscating OpenTelemetry", e);
    }
  }
```

Code after:
                          }
                          return sdkLoggerProviderBuilder;
                        })
                    .setResultAsGlobal()
                    .build()
                    .getOpenTelemetrySdk(),
            executorService);

    // Wait for autoconfiguration to enter our callback, then try to get an instance of
    // GlobalOpenTelemetry. GlobalOpenTelemetry.get() should block until we release the
    // completeAutoconfig latch and allow autoconfiguration to complete.
    autoconfigStarted.await();
    CompletableFuture<OpenTelemetry> globalOpenTelemetryFuture =
        CompletableFuture.supplyAsync(GlobalOpenTelemetry::get, executorService);
    Thread.sleep(10);
    assertThat(globalOpenTelemetryFuture.isDone()).isFalse();
    assertThat(autoConfiguredOpenTelemetryFuture.isDone()).isFalse();

    // Release the latch, allowing autoconfiguration to complete. Confirm that our
    // GlobalOpenTelemetry.get() future resolved to the same instance as autoconfiguration.
    completeAutoconfig.countDown();
    assertThat(unobfuscate(globalOpenTelemetryFuture.get(10, TimeUnit.SECONDS)))
        .isSameAs(autoConfiguredOpenTelemetryFuture.get(10, TimeUnit.SECONDS));

    // Cleanup
    executorService.shutdown();
    autoConfiguredOpenTelemetryFuture.get().shutdown().join(10, TimeUnit.SECONDS);
    GlobalOpenTelemetry.resetForTest();
  }

  private static OpenTelemetry unobfuscate(OpenTelemetry openTelemetry) {
    try {
      Field delegateField =
          Class.forName("io.opentelemetry.api.GlobalOpenTelemetry$ObfuscatedOpenTelemetry")
              .getDeclaredField("delegate");
      delegateField.setAccessible(true);
      Object delegate = delegateField.get(openTelemetry);
      return (OpenTelemetry) delegate;
    } catch (NoSuchFieldException | IllegalAccessException | ClassNotFoundException e) {
      throw new IllegalStateException("Error unobfuscating OpenTelemetry", e);
    }
  }
}