or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

aggregation.mdcobertura-reports.mdcoverage-model.mdhtml-reports.mdindex.mdio-utils.mdplugin.mdruntime.mdserialization.mdxml-reports.md

runtime.mddocs/

0

# Runtime Support

1

2

The runtime module provides the infrastructure for collecting coverage measurements during test execution. When the compiler plugin instruments code, it injects calls to the runtime system that record which statements were executed. This module supports JVM, Scala.js, and Scala Native platforms.

3

4

## Capabilities

5

6

### Coverage Data Collection

7

8

The main interface for recording coverage measurements during runtime.

9

10

```scala { .api }

11

/**

12

* Core runtime object for collecting coverage measurements

13

* This object is called by instrumented code to record statement execution

14

*/

15

object Invoker {

16

/**

17

* Record that a statement was invoked during execution

18

* @param id Unique identifier for the statement

19

* @param dataDir Directory where measurement data should be written

20

* @param reportTestName Whether to include test name information

21

*/

22

def invoked(id: Int, dataDir: String, reportTestName: Boolean = false): Unit

23

24

/**

25

* Get the name of the currently executing ScalaTest test

26

* @returns Test name if running under ScalaTest, empty string otherwise

27

*/

28

def getCallingScalaTest: String

29

30

/**

31

* Get the measurement file for a data directory

32

* @param dataDir Coverage data directory as File

33

* @returns File where measurements are written

34

*/

35

def measurementFile(dataDir: File): File

36

37

/**

38

* Get the measurement file for a data directory

39

* @param dataDir Coverage data directory as String path

40

* @returns File where measurements are written

41

*/

42

def measurementFile(dataDir: String): File

43

44

/**

45

* Find all measurement files in a data directory

46

* @param dataDir Coverage data directory as String path

47

* @returns Array of measurement files found

48

*/

49

def findMeasurementFiles(dataDir: String): Array[File]

50

51

/**

52

* Find all measurement files in a data directory

53

* @param dataDir Coverage data directory as File

54

* @returns Array of measurement files found

55

*/

56

def findMeasurementFiles(dataDir: File): Array[File]

57

58

/**

59

* Load statement IDs that were invoked from measurement files

60

* @param files Sequence of measurement files to read

61

* @returns Set of statement IDs that were executed

62

*/

63

def invoked(files: Seq[File]): Set[Int]

64

}

65

```

66

67

**Usage Examples:**

68

69

```scala

70

import scoverage.Invoker

71

import java.io.File

72

73

// This is typically called by instrumented code, not manually

74

Invoker.invoked(12345, "target/scoverage-data", reportTestName = true)

75

76

// Find measurement files

77

val dataDir = new File("target/scoverage-data")

78

val measurementFiles = Invoker.findMeasurementFiles(dataDir)

79

80

// Load executed statement IDs

81

val executedStatements = Invoker.invoked(measurementFiles.toSeq)

82

println(s"Executed ${executedStatements.size} statements")

83

84

// Get measurement file location

85

val measurementFile = Invoker.measurementFile(dataDir)

86

println(s"Measurements written to: ${measurementFile.getAbsolutePath}")

87

```

88

89

### Platform Abstractions

90

91

The runtime provides platform-specific abstractions for different Scala targets.

92

93

#### JVM Platform

94

95

```scala { .api }

96

/**

97

* JVM-specific platform abstractions

98

*/

99

object Platform {

100

/** Thread-safe map implementation for JVM */

101

type ThreadSafeMap[A, B] = scala.collection.concurrent.TrieMap[A, B]

102

lazy val ThreadSafeMap = scala.collection.concurrent.TrieMap

103

104

/** File type for JVM platform */

105

type File = java.io.File

106

107

/** FileWriter type for JVM platform */

108

type FileWriter = java.io.FileWriter

109

110

/** FileFilter type for JVM platform */

111

type FileFilter = java.io.FileFilter

112

113

/** Source companion object for reading files */

114

lazy val Source = scala.io.Source

115

116

/** Generate random UUID (not cryptographically secure) */

117

def insecureRandomUUID(): java.util.UUID

118

}

119

```

120

121

#### Scala.js Platform

122

123

```scala { .api }

124

/**

125

* Scala.js-specific platform abstractions

126

*/

127

object Platform {

128

/** Thread-safe map implementation for Scala.js */

129

type ThreadSafeMap[A, B] = scala.collection.mutable.HashMap[A, B]

130

lazy val ThreadSafeMap = scala.collection.mutable.HashMap

131

132

/** File type for Scala.js platform */

133

type File = scalajssupport.File

134

135

/** FileWriter type for Scala.js platform */

136

type FileWriter = scalajssupport.FileWriter

137

138

/** FileFilter type for Scala.js platform */

139

type FileFilter = scalajssupport.FileFilter

140

141

/** Source companion object for reading files */

142

lazy val Source = scalajssupport.Source

143

144

/** Generate random UUID (not cryptographically secure) */

145

def insecureRandomUUID(): java.util.UUID

146

}

147

```

148

149

#### Scala Native Platform

150

151

```scala { .api }

152

/**

153

* Scala Native-specific platform abstractions

154

*/

155

object Platform {

156

/** Thread-safe map implementation for Scala Native */

157

type ThreadSafeMap[A, B] = scala.collection.mutable.HashMap[A, B]

158

lazy val ThreadSafeMap = scala.collection.mutable.HashMap

159

160

/** File type for Scala Native platform */

161

type File = scalanativesupport.File

162

163

/** FileWriter type for Scala Native platform */

164

type FileWriter = scalanativesupport.FileWriter

165

166

/** FileFilter type for Scala Native platform */

167

type FileFilter = scalanativesupport.FileFilter

168

169

/** Source companion object for reading files */

170

lazy val Source = scalanativesupport.Source

171

172

/** Generate random UUID (not cryptographically secure) */

173

def insecureRandomUUID(): java.util.UUID

174

}

175

```

176

177

### Scala.js File Support

178

179

File system abstractions for Scala.js environments.

180

181

```scala { .api }

182

/**

183

* File abstraction for Scala.js environments

184

* @param path File path

185

*/

186

class File(path: String) {

187

/**

188

* Create file with parent path and child name

189

* @param path Parent directory path

190

* @param child Child file/directory name

191

*/

192

def this(path: String, child: String)

193

194

/** Delete this file or directory */

195

def delete(): Unit

196

197

/** Get absolute path of this file */

198

def getAbsolutePath(): String

199

200

/** Get name of this file (last component of path) */

201

def getName(): String

202

203

/** Get path of this file */

204

def getPath(): String

205

206

/** Check if this file represents a directory */

207

def isDirectory(): Boolean

208

209

/** Create directory and any necessary parent directories */

210

def mkdirs(): Unit

211

212

/** List all files in this directory */

213

def listFiles(): Array[File]

214

215

/**

216

* List files in this directory matching the filter

217

* @param filter FileFilter to apply

218

* @returns Array of matching files

219

*/

220

def listFiles(filter: FileFilter): Array[File]

221

222

/** Read entire contents of this file as string */

223

def readFile(): String

224

225

override def toString: String

226

}

227

228

object File {

229

/** Global JavaScript object reference */

230

val globalObject: js.Dynamic

231

232

/** JavaScript file operations object */

233

val jsFile: JsFileObject

234

235

/**

236

* Join path components

237

* @param path Base path

238

* @param child Child component to append

239

* @returns Joined path

240

*/

241

def pathJoin(path: String, child: String): String

242

243

/**

244

* Write data to file

245

* @param path File path to write to

246

* @param data String data to write

247

* @param mode Write mode ("a" for append, "w" for overwrite)

248

*/

249

def write(path: String, data: String, mode: String = "a"): Unit

250

}

251

```

252

253

### File I/O Support

254

255

Additional file system support classes for different JavaScript environments.

256

257

```scala { .api }

258

/**

259

* File writer abstraction for Scala.js

260

*/

261

class FileWriter(file: File) {

262

def write(data: String): Unit

263

def close(): Unit

264

}

265

266

/**

267

* File filter for selecting files

268

*/

269

trait FileFilter {

270

def accept(file: File): Boolean

271

}

272

273

/**

274

* Source file reading support

275

*/

276

object Source {

277

/**

278

* Create source from file

279

* @param file File to read from

280

* @returns Source for reading file contents

281

*/

282

def fromFile(file: File): Source

283

284

/**

285

* Create source from file path

286

* @param path Path to file

287

* @returns Source for reading file contents

288

*/

289

def fromFile(path: String): Source

290

}

291

292

class Source {

293

/** Get all lines from source as iterator */

294

def getLines(): Iterator[String]

295

296

/** Close the source */

297

def close(): Unit

298

}

299

```

300

301

**Usage Examples:**

302

303

```scala

304

import scoverage.Platform

305

import Platform.{File, FileWriter, Source}

306

307

// Create and write to file (works across all platforms)

308

val file = new File("coverage-data", "measurements.txt")

309

file.mkdirs() // Ensure parent directory exists

310

311

val writer = new FileWriter(file)

312

writer.write("statement_id:12345\n")

313

writer.close()

314

315

// Read file contents

316

val source = Source.fromFile(file)

317

val lines = source.getLines().toList

318

source.close()

319

320

// Use platform-specific thread-safe map

321

val measurements = Platform.ThreadSafeMap[Int, String]()

322

measurements.put(12345, "com.example.Service.method")

323

```

324

325

## Runtime Integration

326

327

### Instrumented Code Example

328

329

When the compiler plugin instruments code, it injects calls like:

330

331

```scala

332

// Original code:

333

def processUser(user: User): String = {

334

val name = user.name

335

if (name.nonEmpty) {

336

s"Hello, $name"

337

} else {

338

"Hello, Anonymous"

339

}

340

}

341

342

// Instrumented code (simplified):

343

def processUser(user: User): String = {

344

scoverage.Invoker.invoked(1001, "target/scoverage-data")

345

val name = {

346

scoverage.Invoker.invoked(1002, "target/scoverage-data")

347

user.name

348

}

349

if ({

350

scoverage.Invoker.invoked(1003, "target/scoverage-data")

351

name.nonEmpty

352

}) {

353

scoverage.Invoker.invoked(1004, "target/scoverage-data")

354

s"Hello, $name"

355

} else {

356

scoverage.Invoker.invoked(1005, "target/scoverage-data")

357

"Hello, Anonymous"

358

}

359

}

360

```

361

362

### Test Integration

363

364

The runtime automatically detects ScalaTest execution:

365

366

```scala

367

import org.scalatest.flatspec.AnyFlatSpec

368

369

class UserServiceSpec extends AnyFlatSpec {

370

"UserService" should "process valid users" in {

371

// When this test runs, Invoker.getCallingScalaTest returns:

372

// "UserServiceSpec.UserService should process valid users"

373

val result = userService.processUser(validUser)

374

assert(result.startsWith("Hello,"))

375

}

376

}

377

```

378

379

### Multi-Module Support

380

381

For multi-module projects, each module writes to its own measurement files:

382

383

```scala

384

// Module A measurements: target/scoverage-data/scoverage.measurements.module-a.12345

385

// Module B measurements: target/scoverage-data/scoverage.measurements.module-b.67890

386

387

val allFiles = Invoker.findMeasurementFiles("target/scoverage-data")

388

val allInvoked = Invoker.invoked(allFiles.toSeq)

389

// Contains statement IDs from all modules

390

```

391

392

## Error Handling

393

394

- **IOException**: File I/O operations may fail if coverage data directory is not writable

395

- **SecurityException**: May be thrown if running in restricted security environment

396

- **OutOfMemoryError**: Can occur with very large codebases generating excessive measurement data

397

- **ConcurrentModificationException**: Rare threading issues when multiple test processes write simultaneously