or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

http-testing.mdindex.mdlaunchers.mdtest-annotations.mdtest-context.mdtest-resources.mdutilities.md

launchers.mddocs/

0

# Launcher Infrastructure

1

2

Interfaces and implementations for launching and managing different types of Quarkus artifacts during testing, including JVM, native image, and containerized deployments. The launcher system provides a unified interface for testing applications across various runtime environments.

3

4

## Capabilities

5

6

### ArtifactLauncher Interface

7

8

Main interface for launching different types of Quarkus artifacts with lifecycle management and configuration support.

9

10

```java { .api }

11

public interface ArtifactLauncher<T> extends Closeable {

12

void init(T initContext);

13

void start() throws IOException;

14

LaunchResult runToCompletion(String[] args);

15

void includeAsSysProps(Map<String, String> systemProps);

16

boolean listensOnSsl();

17

void close() throws IOException;

18

19

class LaunchResult {

20

public LaunchResult(int statusCode, byte[] output, byte[] stderror) {}

21

public int getStatusCode() {}

22

public byte[] getOutput() {}

23

public byte[] getStderror() {}

24

}

25

26

interface InitContext {

27

int httpPort();

28

int httpsPort();

29

Duration waitTime();

30

String testProfile();

31

List<String> argLine();

32

Map<String, String> env();

33

DevServicesLaunchResult getDevServicesLaunchResult();

34

}

35

}

36

```

37

38

**Basic Usage Pattern:**

39

```java

40

public class ArtifactLauncherTest {

41

@Test

42

public void testJarLauncher() throws IOException {

43

JarArtifactLauncher launcher = new JarArtifactLauncher();

44

45

// Initialize with context

46

InitContext context = new TestInitContext(8080, 8443, Duration.ofSeconds(30));

47

launcher.init(context);

48

49

// Configure system properties

50

launcher.includeAsSysProps(Map.of(

51

"quarkus.test.profile", "integration",

52

"app.environment", "test"

53

));

54

55

try {

56

// Start the application

57

launcher.start();

58

59

// Verify application is running

60

assertTrue(launcher.listensOnSsl()); // if HTTPS configured

61

62

// Run to completion with arguments

63

LaunchResult result = launcher.runToCompletion(new String[]{"--help"});

64

assertEquals(0, result.getStatusCode());

65

66

} finally {

67

launcher.close();

68

}

69

}

70

}

71

```

72

73

### Concrete Launcher Implementations

74

75

#### JarArtifactLauncher

76

77

Launches Quarkus applications packaged as executable JARs.

78

79

```java { .api }

80

public class JarArtifactLauncher implements ArtifactLauncher<ArtifactLauncher.InitContext> {

81

// Implementation for JAR-based artifacts

82

}

83

```

84

85

**Usage Example:**

86

```java

87

@Test

88

public void testJarDeployment() throws IOException {

89

JarArtifactLauncher launcher = new JarArtifactLauncher();

90

InitContext context = createInitContext();

91

92

launcher.init(context);

93

launcher.includeAsSysProps(Map.of(

94

"quarkus.datasource.jdbc.url", "jdbc:h2:mem:test"

95

));

96

97

launcher.start();

98

99

// Test HTTP endpoints

100

given()

101

.baseUri("http://localhost:" + context.httpPort())

102

.when()

103

.get("/health")

104

.then()

105

.statusCode(200);

106

107

launcher.close();

108

}

109

```

110

111

#### NativeImageLauncher

112

113

Launches Quarkus native images for testing native compilation scenarios.

114

115

```java { .api }

116

public class NativeImageLauncher implements ArtifactLauncher<ArtifactLauncher.InitContext> {

117

// Implementation for native image artifacts

118

}

119

```

120

121

**Usage Example:**

122

```java

123

@Test

124

@EnabledIfSystemProperty(named = "native", matches = "true")

125

public void testNativeImage() throws IOException {

126

NativeImageLauncher launcher = new NativeImageLauncher();

127

InitContext context = createInitContext();

128

129

launcher.init(context);

130

launcher.start();

131

132

// Test native image startup time and memory usage

133

long startTime = System.currentTimeMillis();

134

135

// Verify application is responsive

136

given()

137

.baseUri("http://localhost:" + context.httpPort())

138

.when()

139

.get("/api/startup-time")

140

.then()

141

.statusCode(200)

142

.body("startupTime", lessThan(1000)); // Native should start quickly

143

144

launcher.close();

145

}

146

```

147

148

#### DefaultDockerContainerLauncher

149

150

Launches Quarkus applications in Docker containers.

151

152

```java { .api }

153

public class DefaultDockerContainerLauncher implements ArtifactLauncher<ArtifactLauncher.InitContext> {

154

// Implementation for containerized artifacts

155

}

156

```

157

158

**Usage Example:**

159

```java

160

@Test

161

@Testcontainers

162

public void testContainerDeployment() throws IOException {

163

DefaultDockerContainerLauncher launcher = new DefaultDockerContainerLauncher();

164

InitContext context = createInitContext();

165

166

launcher.init(context);

167

launcher.includeAsSysProps(Map.of(

168

"quarkus.container-image.build", "true",

169

"quarkus.container-image.tag", "test"

170

));

171

172

launcher.start();

173

174

// Test containerized application

175

given()

176

.baseUri("http://localhost:" + context.httpPort())

177

.when()

178

.get("/health")

179

.then()

180

.statusCode(200)

181

.body("status", equalTo("UP"));

182

183

launcher.close();

184

}

185

```

186

187

#### RunCommandLauncher

188

189

Launches applications using custom run commands.

190

191

```java { .api }

192

public class RunCommandLauncher implements ArtifactLauncher<ArtifactLauncher.InitContext> {

193

// Implementation for custom command execution

194

}

195

```

196

197

### Supporting Classes

198

199

#### LauncherUtil

200

201

Utility class for common launcher operations and configuration.

202

203

```java { .api }

204

public class LauncherUtil {

205

public static void updateConfigForPort(Path configFile, int port) {}

206

public static boolean isApplicationStarted(String baseUrl, Duration timeout) {}

207

public static void waitForApplicationStart(String baseUrl, Duration timeout) {}

208

// Additional utility methods

209

}

210

```

211

212

**Usage Example:**

213

```java

214

public class LauncherUtilTest {

215

@Test

216

public void testApplicationStartup() {

217

String baseUrl = "http://localhost:8080";

218

Duration timeout = Duration.ofSeconds(30);

219

220

// Wait for application to start

221

LauncherUtil.waitForApplicationStart(baseUrl, timeout);

222

223

// Verify application is ready

224

assertTrue(LauncherUtil.isApplicationStarted(baseUrl, Duration.ofSeconds(5)));

225

}

226

}

227

```

228

229

#### ProcessReader

230

231

Utility for reading process output streams.

232

233

```java { .api }

234

public class ProcessReader {

235

public static void readProcessOutput(Process process, Consumer<String> outputHandler) {}

236

public static String captureOutput(Process process) throws IOException {}

237

// Additional process handling methods

238

}

239

```

240

241

#### NativeImageStartedNotifier

242

243

Specialized utility for detecting native image startup completion.

244

245

```java { .api }

246

public class NativeImageStartedNotifier {

247

public static boolean waitForStartup(Process process, Duration timeout) {}

248

public static void notifyStartupComplete(String signal) {}

249

// Native image specific utilities

250

}

251

```

252

253

## Advanced Usage Patterns

254

255

### Custom Launcher Implementation

256

257

Creating a custom launcher for specific deployment scenarios:

258

259

```java

260

public class CustomKubernetesLauncher implements ArtifactLauncher<InitContext> {

261

private KubernetesClient kubernetesClient;

262

private String deploymentName;

263

264

@Override

265

public void init(InitContext initContext) {

266

this.kubernetesClient = new DefaultKubernetesClient();

267

this.deploymentName = "test-app-" + System.currentTimeMillis();

268

}

269

270

@Override

271

public void start() throws IOException {

272

// Deploy to Kubernetes

273

Deployment deployment = new DeploymentBuilder()

274

.withNewMetadata().withName(deploymentName).endMetadata()

275

.withNewSpec()

276

.withReplicas(1)

277

.withNewTemplate()

278

.withNewSpec()

279

.addNewContainer()

280

.withName("app")

281

.withImage("quarkus-app:test")

282

.addNewPort().withContainerPort(8080).endPort()

283

.endContainer()

284

.endSpec()

285

.endTemplate()

286

.endSpec()

287

.build();

288

289

kubernetesClient.apps().deployments().create(deployment);

290

291

// Wait for deployment to be ready

292

kubernetesClient.apps().deployments()

293

.withName(deploymentName)

294

.waitUntilReady(60, TimeUnit.SECONDS);

295

}

296

297

@Override

298

public void close() throws IOException {

299

if (kubernetesClient != null && deploymentName != null) {

300

kubernetesClient.apps().deployments().withName(deploymentName).delete();

301

}

302

}

303

304

// Implement other required methods...

305

}

306

```

307

308

### Multi-Environment Testing

309

310

Testing across different deployment environments:

311

312

```java

313

@ParameterizedTest

314

@ValueSource(strings = {"jar", "native", "container"})

315

public void testAcrossEnvironments(String launcherType) throws IOException {

316

ArtifactLauncher<?> launcher = createLauncher(launcherType);

317

InitContext context = createInitContext();

318

319

launcher.init(context);

320

launcher.start();

321

322

try {

323

// Common test logic for all environments

324

verifyHealthEndpoint(context.httpPort());

325

verifyAPIEndpoints(context.httpPort());

326

verifyMetrics(context.httpPort());

327

328

} finally {

329

launcher.close();

330

}

331

}

332

333

private ArtifactLauncher<?> createLauncher(String type) {

334

return switch (type) {

335

case "jar" -> new JarArtifactLauncher();

336

case "native" -> new NativeImageLauncher();

337

case "container" -> new DefaultDockerContainerLauncher();

338

default -> throw new IllegalArgumentException("Unknown launcher type: " + type);

339

};

340

}

341

```

342

343

### Performance Testing with Launchers

344

345

Measuring application performance across different deployment modes:

346

347

```java

348

public class PerformanceTest {

349

@Test

350

public void compareStartupTimes() throws IOException {

351

Map<String, Duration> startupTimes = new HashMap<>();

352

353

// Test JAR startup

354

startupTimes.put("JAR", measureStartupTime(new JarArtifactLauncher()));

355

356

// Test native image startup

357

startupTimes.put("Native", measureStartupTime(new NativeImageLauncher()));

358

359

// Verify native is faster

360

assertTrue(startupTimes.get("Native").compareTo(startupTimes.get("JAR")) < 0,

361

"Native image should start faster than JAR");

362

363

System.out.println("Startup times: " + startupTimes);

364

}

365

366

private Duration measureStartupTime(ArtifactLauncher<?> launcher) throws IOException {

367

InitContext context = createInitContext();

368

launcher.init(context);

369

370

long start = System.currentTimeMillis();

371

launcher.start();

372

373

// Wait for application to be responsive

374

LauncherUtil.waitForApplicationStart(

375

"http://localhost:" + context.httpPort(),

376

Duration.ofSeconds(60)

377

);

378

379

long end = System.currentTimeMillis();

380

launcher.close();

381

382

return Duration.ofMillis(end - start);

383

}

384

}

385

```

386

387

### Resource Monitoring

388

389

Monitoring resource usage during testing:

390

391

```java

392

public class ResourceMonitoringTest {

393

@Test

394

public void monitorResourceUsage() throws IOException {

395

JarArtifactLauncher launcher = new JarArtifactLauncher();

396

InitContext context = createInitContext();

397

398

launcher.init(context);

399

launcher.start();

400

401

try {

402

// Monitor memory usage

403

MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();

404

long initialMemory = memoryBean.getHeapMemoryUsage().getUsed();

405

406

// Simulate load

407

IntStream.range(0, 1000).parallel().forEach(i -> {

408

given()

409

.baseUri("http://localhost:" + context.httpPort())

410

.when()

411

.get("/api/data/" + i)

412

.then()

413

.statusCode(200);

414

});

415

416

long finalMemory = memoryBean.getHeapMemoryUsage().getUsed();

417

long memoryIncrease = finalMemory - initialMemory;

418

419

System.out.println("Memory increase: " + memoryIncrease + " bytes");

420

assertTrue(memoryIncrease < 100_000_000, "Memory usage should be reasonable");

421

422

} finally {

423

launcher.close();

424

}

425

}

426

}

427

```