or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

bookkeeper-client-mocking.mdbookkeeper-server-testing.mdbookkeeper-testing-utilities.mdindex.mdzookeeper-mocking.md

bookkeeper-testing-utilities.mddocs/

0

# BookKeeper Testing Utilities

1

2

Enhanced testing components providing specialized test clients, in-memory statistics providers, and server testing infrastructure for comprehensive BookKeeper testing scenarios beyond basic mocking.

3

4

## Capabilities

5

6

### BookKeeperTestClient

7

8

Enhanced BookKeeper client with access to internal components and specialized testing methods for integration testing scenarios.

9

10

```java { .api }

11

class BookKeeperTestClient extends BookKeeper {

12

// Constructors

13

BookKeeperTestClient(ClientConfiguration conf) throws InterruptedException, BKException;

14

BookKeeperTestClient(ClientConfiguration conf, TestStatsProvider statsProvider) throws InterruptedException, BKException;

15

BookKeeperTestClient(ClientConfiguration conf, ZooKeeper zkc) throws InterruptedException, BKException;

16

17

// Internal Component Access

18

ZooKeeper getZkHandle();

19

ClientConfiguration getConf();

20

BookieClient getBookieClient();

21

TestStatsProvider getTestStatsProvider();

22

23

// Testing Operations

24

void waitForReadOnlyBookie(BookieId id) throws Exception;

25

void waitForWritableBookie(BookieId id) throws Exception;

26

void readBookiesBlocking() throws BKException;

27

}

28

```

29

30

### TestStatsProvider

31

32

In-memory statistics provider for testing with comprehensive metrics collection and analysis capabilities.

33

34

```java { .api }

35

class TestStatsProvider implements StatsProvider {

36

// StatsProvider Interface

37

void start(Configuration conf);

38

void stop();

39

TestStatsLogger getStatsLogger(String scope);

40

String getStatsName(String... statsComponents);

41

42

// Access Methods

43

TestOpStatsLogger getOpStatsLogger(String path);

44

TestCounter getCounter(String path);

45

Gauge<? extends Number> getGauge(String path);

46

void forEachOpStatLogger(BiConsumer<String, TestOpStatsLogger> f);

47

void clear();

48

}

49

```

50

51

### TestCounter

52

53

In-memory counter for tracking numeric metrics during testing.

54

55

```java { .api }

56

class TestCounter implements Counter {

57

// Counter Operations

58

void clear();

59

void inc();

60

void dec();

61

void addCount(long delta);

62

void addLatency(long eventLatency, TimeUnit unit);

63

64

// Value Access

65

Long get();

66

Long getMax();

67

}

68

```

69

70

### TestOpStatsLogger

71

72

In-memory operation statistics logger for tracking operation latencies and success/failure rates.

73

74

```java { .api }

75

class TestOpStatsLogger implements OpStatsLogger {

76

// Event Registration

77

void registerFailedEvent(long eventLatency, TimeUnit unit);

78

void registerSuccessfulEvent(long eventLatency, TimeUnit unit);

79

synchronized void registerSuccessfulValue(long value);

80

synchronized void registerFailedValue(long value);

81

82

// Statistics Access

83

OpStatsData toOpStatsData();

84

synchronized void clear();

85

synchronized double getSuccessAverage();

86

synchronized long getSuccessCount();

87

}

88

```

89

90

### TestStatsLogger

91

92

In-memory hierarchical statistics logger for organizing metrics by scope.

93

94

```java { .api }

95

class TestStatsLogger implements StatsLogger {

96

// Metric Creation

97

OpStatsLogger getOpStatsLogger(String name);

98

Counter getCounter(String name);

99

Gauge<? extends Number> getGauge(String name);

100

101

// Gauge Management

102

<T extends Number> void registerGauge(String name, Gauge<T> gauge);

103

<T extends Number> void unregisterGauge(String name, Gauge<T> gauge);

104

105

// Scope Management

106

StatsLogger scope(String name);

107

void removeScope(String name, StatsLogger statsLogger);

108

109

// Thread-Scoped Metrics

110

OpStatsLogger getThreadScopedOpStatsLogger(String name);

111

Counter getThreadScopedCounter(String name);

112

}

113

```

114

115

## Types

116

117

### Statistics Interfaces

118

119

```java { .api }

120

interface StatsProvider {

121

void start(Configuration conf);

122

void stop();

123

StatsLogger getStatsLogger(String scope);

124

String getStatsName(String... statsComponents);

125

}

126

127

interface StatsLogger {

128

OpStatsLogger getOpStatsLogger(String name);

129

Counter getCounter(String name);

130

<T extends Number> Gauge<T> getGauge(String name);

131

<T extends Number> void registerGauge(String name, Gauge<T> gauge);

132

<T extends Number> void unregisterGauge(String name, Gauge<T> gauge);

133

StatsLogger scope(String name);

134

void removeScope(String name, StatsLogger statsLogger);

135

OpStatsLogger getThreadScopedOpStatsLogger(String name);

136

Counter getThreadScopedCounter(String name);

137

}

138

139

interface OpStatsLogger {

140

void registerFailedEvent(long eventLatency, TimeUnit unit);

141

void registerSuccessfulEvent(long eventLatency, TimeUnit unit);

142

void registerSuccessfulValue(long value);

143

void registerFailedValue(long value);

144

OpStatsData toOpStatsData();

145

void clear();

146

}

147

148

interface Counter {

149

void clear();

150

void inc();

151

void dec();

152

void addCount(long delta);

153

void addLatency(long eventLatency, TimeUnit unit);

154

Long get();

155

}

156

157

interface Gauge<T extends Number> {

158

T getDefaultValue();

159

T getSample();

160

}

161

```

162

163

### BookKeeper Client Types

164

165

```java { .api }

166

class ClientConfiguration extends AbstractConfiguration {

167

// BookKeeper client configuration

168

// (Part of BookKeeper API)

169

}

170

171

class BookieClient {

172

// Internal BookKeeper bookie client

173

// (Part of BookKeeper internal API)

174

}

175

176

class BookieId {

177

// Bookie identifier

178

// (Part of BookKeeper API)

179

}

180

```

181

182

## Usage Examples

183

184

### Enhanced Client Testing

185

186

```java

187

import org.apache.bookkeeper.client.BookKeeperTestClient;

188

import org.apache.bookkeeper.client.TestStatsProvider;

189

import org.apache.bookkeeper.conf.ClientConfiguration;

190

191

// Create client configuration

192

ClientConfiguration conf = new ClientConfiguration();

193

conf.setMetadataServiceUri("zk+null://localhost/ledgers");

194

195

// Create test client with custom statistics provider

196

TestStatsProvider statsProvider = new TestStatsProvider();

197

BookKeeperTestClient testClient = new BookKeeperTestClient(conf, statsProvider);

198

199

// Access internal components for testing

200

ZooKeeper zkHandle = testClient.getZkHandle();

201

BookieClient bookieClient = testClient.getBookieClient();

202

203

// Perform operations and collect statistics

204

LedgerHandle ledger = testClient.createLedger(DigestType.CRC32, "password".getBytes());

205

ledger.addEntry("test data".getBytes());

206

207

// Analyze collected statistics

208

TestStatsProvider.TestOpStatsLogger createStats = statsProvider.getOpStatsLogger("ledger.create");

209

System.out.println("Create operations: " + createStats.getSuccessCount());

210

211

testClient.close();

212

```

213

214

### Statistics Collection and Analysis

215

216

```java

217

TestStatsProvider statsProvider = new TestStatsProvider();

218

219

// Create loggers for different scopes

220

TestStatsProvider.TestStatsLogger rootLogger = statsProvider.getStatsLogger("bookkeeper");

221

TestStatsProvider.TestStatsLogger clientLogger = rootLogger.scope("client");

222

223

// Create metrics

224

TestStatsProvider.TestOpStatsLogger readOps = clientLogger.getOpStatsLogger("read");

225

TestStatsProvider.TestCounter totalRequests = clientLogger.getCounter("requests.total");

226

227

// Simulate operations

228

totalRequests.inc();

229

readOps.registerSuccessfulEvent(50, TimeUnit.MILLISECONDS);

230

totalRequests.inc();

231

readOps.registerSuccessfulEvent(75, TimeUnit.MILLISECONDS);

232

totalRequests.inc();

233

readOps.registerFailedEvent(100, TimeUnit.MILLISECONDS);

234

235

// Analyze results

236

System.out.println("Total requests: " + totalRequests.get());

237

System.out.println("Read success count: " + readOps.getSuccessCount());

238

System.out.println("Average read latency: " + readOps.getSuccessAverage() + "ms");

239

240

// Clear metrics for next test

241

statsProvider.clear();

242

```

243

244

### Bookie State Testing

245

246

```java

247

BookKeeperTestClient testClient = new BookKeeperTestClient(conf);

248

249

// Test bookie availability

250

BookieId bookieId = new BookieId("127.0.0.1", 3181);

251

252

// Wait for bookie to become read-only

253

Future<?> readOnlyFuture = testClient.waitForReadOnlyBookie(bookieId);

254

readOnlyFuture.get(30, TimeUnit.SECONDS);

255

256

// Wait for bookie to become writable again

257

Future<?> writableFuture = testClient.waitForWritableBookie(bookieId);

258

writableFuture.get(30, TimeUnit.SECONDS);

259

260

// Force reading bookie information

261

testClient.readBookiesBlocking();

262

263

testClient.close();

264

```

265

266

### Custom Gauge Testing

267

268

```java

269

TestStatsProvider statsProvider = new TestStatsProvider();

270

TestStatsProvider.TestStatsLogger logger = statsProvider.getStatsLogger("test");

271

272

// Register custom gauge

273

AtomicLong queueSize = new AtomicLong(0);

274

Gauge<Long> queueGauge = new Gauge<Long>() {

275

public Long getDefaultValue() { return 0L; }

276

public Long getSample() { return queueSize.get(); }

277

};

278

279

logger.registerGauge("queue.size", queueGauge);

280

281

// Simulate queue operations

282

queueSize.set(10);

283

Gauge<? extends Number> retrievedGauge = logger.getGauge("queue.size");

284

System.out.println("Queue size: " + retrievedGauge.getSample());

285

286

// Clean up

287

logger.unregisterGauge("queue.size", queueGauge);

288

```

289

290

### Integration Testing with Multiple Clients

291

292

```java

293

public class MultiClientTest {

294

private List<BookKeeperTestClient> clients = new ArrayList<>();

295

private TestStatsProvider globalStats = new TestStatsProvider();

296

297

@Before

298

public void setUp() throws Exception {

299

ClientConfiguration conf = new ClientConfiguration();

300

conf.setMetadataServiceUri("zk+null://localhost/ledgers");

301

302

// Create multiple test clients

303

for (int i = 0; i < 3; i++) {

304

BookKeeperTestClient client = new BookKeeperTestClient(conf, globalStats);

305

clients.add(client);

306

}

307

}

308

309

@Test

310

public void testConcurrentOperations() throws Exception {

311

// Perform concurrent operations with different clients

312

List<CompletableFuture<Void>> futures = new ArrayList<>();

313

314

for (int i = 0; i < clients.size(); i++) {

315

final int clientIndex = i;

316

CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {

317

try {

318

BookKeeperTestClient client = clients.get(clientIndex);

319

LedgerHandle ledger = client.createLedger(DigestType.CRC32, "password".getBytes());

320

321

for (int j = 0; j < 10; j++) {

322

ledger.addEntry(("data-" + clientIndex + "-" + j).getBytes());

323

}

324

325

ledger.close();

326

} catch (Exception e) {

327

throw new RuntimeException(e);

328

}

329

});

330

futures.add(future);

331

}

332

333

// Wait for all operations to complete

334

CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).get();

335

336

// Analyze global statistics

337

globalStats.forEachOpStatLogger((path, opStats) -> {

338

System.out.println(path + ": " + opStats.getSuccessCount() + " operations");

339

});

340

}

341

342

@After

343

public void tearDown() throws Exception {

344

for (BookKeeperTestClient client : clients) {

345

client.close();

346

}

347

}

348

}

349

```

350

351

### Thread-Scoped Metrics Testing

352

353

```java

354

TestStatsProvider statsProvider = new TestStatsProvider();

355

TestStatsProvider.TestStatsLogger logger = statsProvider.getStatsLogger("thread-test");

356

357

// Create thread-scoped metrics

358

ExecutorService executor = Executors.newFixedThreadPool(3);

359

List<Future<?>> futures = new ArrayList<>();

360

361

for (int i = 0; i < 3; i++) {

362

Future<?> future = executor.submit(() -> {

363

// Each thread gets its own scoped metrics

364

TestStatsProvider.TestOpStatsLogger threadOpStats = logger.getThreadScopedOpStatsLogger("operation");

365

TestStatsProvider.TestCounter threadCounter = (TestStatsProvider.TestCounter) logger.getThreadScopedCounter("requests");

366

367

// Perform operations

368

for (int j = 0; j < 5; j++) {

369

threadCounter.inc();

370

threadOpStats.registerSuccessfulEvent(j * 10, TimeUnit.MILLISECONDS);

371

}

372

});

373

futures.add(future);

374

}

375

376

// Wait for completion

377

for (Future<?> future : futures) {

378

future.get();

379

}

380

381

executor.shutdown();

382

```