diff --git a/README.md b/README.md index c908d6d..c669743 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ [![License](https://img.shields.io/github/license/JohnLCaron/egk-ec)](https://github.com/JohnLCaron/egk-ec/blob/main/LICENSE.txt) ![GitHub branch checks state](https://img.shields.io/github/actions/workflow/status/JohnLCaron/egk-ec/unit-tests.yml) -![Coverage](https://img.shields.io/badge/coverage-90.7%25%20LOC%20(6967/7680)-blue) +![Coverage](https://img.shields.io/badge/coverage-90.4%25%20LOC%20(6997/7741)-blue) # ElectionGuard-Kotlin Elliptic Curve -_last update 04/25/2024_ +_last update 04/30/2024_ EGK Elliptic Curve (egk-ec) is an experimental implementation of [ElectionGuard](https://github.com/microsoft/electionguard), [version 2.0](https://github.com/microsoft/electionguard/releases/download/v2.0/EG_Spec_2_0.pdf), diff --git a/src/main/kotlin/org/cryptobiotic/eg/cli/RunAddEncryptedBallots.kt b/src/main/kotlin/org/cryptobiotic/eg/cli/RunAddEncryptedBallots.kt index e8b7ad8..952934f 100644 --- a/src/main/kotlin/org/cryptobiotic/eg/cli/RunAddEncryptedBallots.kt +++ b/src/main/kotlin/org/cryptobiotic/eg/cli/RunAddEncryptedBallots.kt @@ -11,10 +11,9 @@ import org.cryptobiotic.eg.input.ManifestInputValidation import org.cryptobiotic.eg.publish.readElectionRecord import org.cryptobiotic.util.ErrorMessages import kotlin.random.Random +import kotlin.system.exitProcess -/** - * This reads plaintext ballots from ballotDir and writes their encryptions into the specified election record. - */ +/** This reads plaintext ballots from ballotDir and writes their encryptions into the specified election record. */ class RunAddEncryptedBallots { companion object { @@ -48,6 +47,11 @@ class RunAddEncryptedBallots { shortName = "challenge", description = "Challenge percent of ballots" ).default(0) + val noexit by parser.option( + ArgType.Boolean, + shortName = "noexit", + description = "Dont call System.exit" + ).default(false) parser.parse(args) @@ -56,56 +60,62 @@ class RunAddEncryptedBallots { " outputDir = $outputDir\n challengePct = $challengePct" } - val electionRecord = readElectionRecord(inputDir) - val electionInit = electionRecord.electionInit()!! - val consumerIn = electionRecord.consumer() + try { + val electionRecord = readElectionRecord(inputDir) + val electionInit = electionRecord.electionInit()!! + val consumerIn = electionRecord.consumer() - val manifest = consumerIn.makeManifest(electionInit.config.manifestBytes) - val errors = ManifestInputValidation(manifest).validate() - if (ManifestInputValidation(manifest).validate().hasErrors()) { - logger.error { "ManifestInputValidation error ${errors}" } - throw RuntimeException("ManifestInputValidation error $errors") - } - val chaining = electionInit.config.chainConfirmationCodes + val manifest = consumerIn.makeManifest(electionInit.config.manifestBytes) + val errors = ManifestInputValidation(manifest).validate() + if (ManifestInputValidation(manifest).validate().hasErrors()) { + logger.error { "ManifestInputValidation error ${errors}" } + if (!noexit) exitProcess(1) + else throw RuntimeException("ManifestInputValidation error $errors") + } + val chaining = electionInit.config.chainConfirmationCodes - var allOk = true + var allOk = true - val encryptor = AddEncryptedBallot( - electionRecord.manifest(), - BallotInputValidation(electionRecord.manifest()), - electionInit.config.chainConfirmationCodes, - electionInit.config.configBaux0, - electionInit.jointPublicKey, - electionInit.extendedBaseHash, - device, - outputDir, - "${outputDir}/invalidDir", - noDeviceNameInDir = !chaining - ) + val encryptor = AddEncryptedBallot( + electionRecord.manifest(), + BallotInputValidation(electionRecord.manifest()), + electionInit.config.chainConfirmationCodes, + electionInit.config.configBaux0, + electionInit.jointPublicKey, + electionInit.extendedBaseHash, + device, + outputDir, + "${outputDir}/invalidDir", + noDeviceNameInDir = !chaining + ) - var countChallenge = 0 - consumerIn.iteratePlaintextBallots(ballotDir, null).forEach { pballot -> - val errs = ErrorMessages("AddEncryptedBallot ${pballot.ballotId}") - val encrypted = encryptor.encrypt(pballot, errs) - if (encrypted == null) { - logger.error{ "failed errors = $errs"} - allOk = false - } else { - val challengeThisOne = (challengePct != 0) && (Random.nextInt(100) > (100 - challengePct)) - if (challengeThisOne) { - encryptor.challenge(encrypted.confirmationCode) - countChallenge++ + var countChallenge = 0 + consumerIn.iteratePlaintextBallots(ballotDir, null).forEach { pballot -> + val errs = ErrorMessages("AddEncryptedBallot ${pballot.ballotId}") + val encrypted = encryptor.encrypt(pballot, errs) + if (encrypted == null) { + logger.error { "failed errors = $errs" } + allOk = false } else { - encryptor.cast(encrypted.confirmationCode) + val challengeThisOne = (challengePct != 0) && (Random.nextInt(100) > (100 - challengePct)) + if (challengeThisOne) { + encryptor.challenge(encrypted.confirmationCode) + countChallenge++ + } else { + encryptor.cast(encrypted.confirmationCode) + } } } - } - encryptor.close() + encryptor.close() - if (allOk) { - logger.info { "success" } - } else { - logger.error { "failure" } + if (allOk) { + logger.info { "success" } + } else { + if (!noexit) exitProcess(2) + } + } catch (t: Throwable) { + logger.error { "Exception= ${t.message} ${t.stackTraceToString()}" } + if (!noexit) exitProcess(-1) } } } diff --git a/src/main/kotlin/org/cryptobiotic/eg/cli/RunBatchEncryption.kt b/src/main/kotlin/org/cryptobiotic/eg/cli/RunBatchEncryption.kt index c1ab36a..bd938a5 100644 --- a/src/main/kotlin/org/cryptobiotic/eg/cli/RunBatchEncryption.kt +++ b/src/main/kotlin/org/cryptobiotic/eg/cli/RunBatchEncryption.kt @@ -36,6 +36,7 @@ import org.cryptobiotic.eg.verifier.VerifyEncryptedBallots import org.cryptobiotic.util.ErrorMessages import org.cryptobiotic.util.Stats import org.cryptobiotic.util.Stopwatch +import kotlin.system.exitProcess /** * Run ballot encryption in multithreaded batch mode CLI. @@ -107,6 +108,11 @@ class RunBatchEncryption { shortName = "anon", description = "anonymize ballot" ).default(false) + val noexit by parser.option( + ArgType.Boolean, + shortName = "noexit", + description = "Dont call System.exit" + ).default(false) parser.parse(args) val startupInfo = @@ -120,23 +126,35 @@ class RunBatchEncryption { println(startupInfo) if (outputDir == null && encryptDir == null) { - throw RuntimeException("Must specify outputDir or encryptDir") + logger.error { "Must specify outputDir or encryptDir" } + if (!noexit) exitProcess(1) + else throw RuntimeException("Must specify outputDir or encryptDir") } - batchEncryption( - inputDir, - ballotDir, - device = device, - outputDir, - encryptDir, - invalidDir, - nthreads, - createdBy, - check, - cleanOutput, - anonymize, - ) - logger.info { "success" } + try { + val retval = batchEncryption( + inputDir, + ballotDir, + device = device, + outputDir, + encryptDir, + invalidDir, + nthreads, + createdBy, + check, + cleanOutput, + anonymize, + ) + if (retval == 0) { + logger.info { "success" } + } else { + if (!noexit) exitProcess(retval) + } + + } catch (t: Throwable) { + logger.error { "Exception= ${t.message} ${t.stackTraceToString()}" } + if (!noexit) exitProcess(-1) + } } enum class CheckType { None, Verify, EncryptTwice, DecryptNonce } @@ -154,7 +172,7 @@ class RunBatchEncryption { check: CheckType = CheckType.None, cleanOutput: Boolean = false, anonymize: Boolean = false, - ) { + ): Int { // ballots can be in either format val consumer = makeConsumer(inputDir) @@ -180,13 +198,13 @@ class RunBatchEncryption { check: CheckType = CheckType.None, cleanOutput: Boolean = false, anonymize: Boolean = false, - ) { + ): Int { count = 0 // start over each batch val consumerIn = makeConsumer(inputDir) val initResult = consumerIn.readElectionInitialized() if (initResult is Err) { - logger.error{ "readElectionInitialized error ${initResult.error}" } - return + logger.error { "readElectionInitialized error ${initResult.error}" } + return 2 } val electionInit = initResult.unwrap() val manifest = consumerIn.makeManifest(electionInit.config.manifestBytes) @@ -195,8 +213,8 @@ class RunBatchEncryption { val manifestValidator = ManifestInputValidation(manifest) val errors = manifestValidator.validate() if (errors.hasErrors()) { - logger.error{ "ManifestInputValidation error on election record in $inputDir errs=$errors}" } - return + logger.error { "ManifestInputValidation error on election record in $inputDir errs=$errors}" } + return 3 } // debugging // Map @@ -271,15 +289,24 @@ class RunBatchEncryption { } // Must save invalid ballots if (invalidBallots.isNotEmpty()) { - val useInvalidDir = if (invalidDir != null) invalidDir else if (outputDir != null) "$outputDir/invalid" else "$encryptDir/invalid" + val useInvalidDir = + if (invalidDir != null) invalidDir else if (outputDir != null) "$outputDir/invalid" else "$encryptDir/invalid" createDirectories(useInvalidDir) publisher.writePlaintextBallot(useInvalidDir, invalidBallots) - logger.info{ " wrote ${invalidBallots.size} invalid ballots to $useInvalidDir" } + logger.info { " wrote ${invalidBallots.size} invalid ballots to $useInvalidDir" } } - logger.debug{ "Encryption with nthreads = $nthreads ${stopwatch.tookPer(count, "ballot")}" } + logger.debug { "Encryption with nthreads = $nthreads ${stopwatch.tookPer(count, "ballot")}" } val encryptionPerBallot = if (count == 0) 0 else (countEncryptions / count) - logger.debug{ " $countEncryptions total encryptions = $encryptionPerBallot per ballot ${stopwatch.tookPer(countEncryptions, "encryptions")}"} + logger.debug { + " $countEncryptions total encryptions = $encryptionPerBallot per ballot ${ + stopwatch.tookPer( + countEncryptions, + "encryptions" + ) + }" + } + return 0 } private var codeBaux = ByteArray(0) @@ -312,7 +339,8 @@ class RunBatchEncryption { // experiments in testing the encryption val errs2 = ErrorMessages("Ballot ${ballot.ballotId}") if (check == CheckType.EncryptTwice) { - val encrypted2 = encryptor.encrypt(ballot, config.configBaux0, errs2, ciphertextBallot.ballotNonce)!! + val encrypted2 = + encryptor.encrypt(ballot, config.configBaux0, errs2, ciphertextBallot.ballotNonce)!! if (encrypted2.confirmationCode != ciphertextBallot.confirmationCode) { logger.warn { "CheckType.EncryptTwice: encrypted.confirmationCode doesnt match" } } @@ -332,7 +360,7 @@ class RunBatchEncryption { val encryptedBallot = ciphertextBallot.submit(EncryptedBallot.BallotState.CAST) val decryptionWithPrimaryNonce = DecryptBallotWithNonce(group, publicKey, extendedBaseHash) - val decryptResult = with( decryptionWithPrimaryNonce) { encryptedBallot.decrypt(primaryNonce) } + val decryptResult = with(decryptionWithPrimaryNonce) { encryptedBallot.decrypt(primaryNonce) } if (decryptResult is Err) { logger.warn { "CheckType.DecryptNonce: encrypted ballot fails decryption = $decryptResult" } } @@ -379,7 +407,7 @@ class RunBatchEncryption { input: Channel, sink: EncryptedBallotSinkIF, anonymize: Boolean, ) = launch { for (ballot in input) { - val useBallot = if (!anonymize) ballot else ballot.copy(ballotId = (count+1).toString()) + val useBallot = if (!anonymize) ballot else ballot.copy(ballotId = (count + 1).toString()) sink.writeEncryptedBallot(useBallot) logger.debug { " Sink wrote $count submitted ballot ${useBallot.ballotId}" } count++ diff --git a/src/main/kotlin/org/cryptobiotic/eg/cli/RunCreateInputBallots.kt b/src/main/kotlin/org/cryptobiotic/eg/cli/RunCreateInputBallots.kt index 95728a2..47a6030 100644 --- a/src/main/kotlin/org/cryptobiotic/eg/cli/RunCreateInputBallots.kt +++ b/src/main/kotlin/org/cryptobiotic/eg/cli/RunCreateInputBallots.kt @@ -1,5 +1,6 @@ package org.cryptobiotic.eg.cli +import io.github.oshai.kotlinlogging.KotlinLogging import kotlinx.cli.ArgParser import kotlinx.cli.ArgType import kotlinx.cli.default @@ -8,11 +9,14 @@ import org.cryptobiotic.eg.election.PlaintextBallot import org.cryptobiotic.eg.input.RandomBallotProvider import org.cryptobiotic.eg.publish.makePublisher import org.cryptobiotic.eg.publish.readAndCheckManifest +import kotlin.system.exitProcess /** Run Create Input Ballots CLI. */ class RunCreateInputBallots { companion object { + private val logger = KotlinLogging.logger("RunCreateInputBallots") + @JvmStatic fun main(args: Array) { val parser = ArgParser("RunCreateInputBallots") @@ -31,32 +35,36 @@ class RunCreateInputBallots { shortName = "n", description = "Number of ballots to generate" ).default(11) - val isJson by parser.option( + val noexit by parser.option( ArgType.Boolean, - shortName = "json", - description = "Generate Json ballots (default to manifest type)" - ) + shortName = "noexit", + description = "Dont call System.exit" + ).default(false) + parser.parse(args) println( "RunCreateInputBallots\n" + " electionManifest = '$manifestDirOrFile'\n" + " outputDir = '$outputDir'\n" + - " nballots = '$nballots'\n" + - " isJson = '$isJson'\n" + " nballots = '$nballots'\n" ) - val (manifestIsJson, manifest, _) = readAndCheckManifest(manifestDirOrFile) - val useJson = isJson ?: manifestIsJson - val publisher = makePublisher(outputDir, true) + try { + val (_, manifest, _) = readAndCheckManifest(manifestDirOrFile) + val publisher = makePublisher(outputDir, true) - val ballots = mutableListOf() - val ballotProvider = RandomBallotProvider(manifest) - repeat(nballots) { - ballots.add(ballotProvider.makeBallot()) - } + val ballots = mutableListOf() + val ballotProvider = RandomBallotProvider(manifest) + repeat(nballots) { + ballots.add(ballotProvider.makeBallot()) + } + publisher.writePlaintextBallot(outputDir, ballots) - publisher.writePlaintextBallot(outputDir, ballots) + } catch (t: Throwable) { + logger.error { "Exception= ${t.message} ${t.stackTraceToString()}" } + if (!noexit) exitProcess(-1) + } } } } \ No newline at end of file diff --git a/src/main/kotlin/org/cryptobiotic/eg/cli/RunCreateTestManifest.kt b/src/main/kotlin/org/cryptobiotic/eg/cli/RunCreateTestManifest.kt index 841d4e3..368f5a3 100644 --- a/src/main/kotlin/org/cryptobiotic/eg/cli/RunCreateTestManifest.kt +++ b/src/main/kotlin/org/cryptobiotic/eg/cli/RunCreateTestManifest.kt @@ -1,16 +1,20 @@ package org.cryptobiotic.eg.cli +import io.github.oshai.kotlinlogging.KotlinLogging import kotlinx.cli.ArgParser import kotlinx.cli.ArgType import kotlinx.cli.default import kotlinx.cli.required import org.cryptobiotic.eg.input.ManifestInputValidation import org.cryptobiotic.eg.publish.makePublisher +import kotlin.system.exitProcess /** Create Test Manifest CLI. */ class RunCreateTestManifest { companion object { + private val logger = KotlinLogging.logger("RunCreateTestManifest") + @JvmStatic fun main(args: Array) { val parser = ArgParser("RunCreateTestManifest") @@ -39,6 +43,12 @@ class RunCreateTestManifest { shortName = "out", description = "Directory to write test manifest file" ).required() + val noexit by parser.option( + ArgType.Boolean, + shortName = "noexit", + description = "Dont call System.exit" + ).default(false) + parser.parse(args) println( @@ -50,18 +60,23 @@ class RunCreateTestManifest { " output = $outputDir\n" ) - val manifest = if (nstyles == 1) buildTestManifest(ncontests, nselections) - else buildTestManifest(nstyles, ncontests, nselections) - + try { + val manifest = if (nstyles == 1) buildTestManifest(ncontests, nselections) + else buildTestManifest(nstyles, ncontests, nselections) - val validator = ManifestInputValidation(manifest) - val errs = validator.validate() - if (errs.hasErrors()) { - println("failed $errs") - } else { - val publisher = makePublisher(outputDir, true) - publisher.writeManifest(manifest) - println("ManifestInputValidation succeeded") + val validator = ManifestInputValidation(manifest) + val errs = validator.validate() + if (errs.hasErrors()) { + logger.error{"failed $errs"} + if (!noexit) exitProcess(1) + } else { + val publisher = makePublisher(outputDir, true) + publisher.writeManifest(manifest) + logger.info("ManifestInputValidation succeeded") + } + } catch (t: Throwable) { + logger.error { "Exception= ${t.message} ${t.stackTraceToString()}" } + if (!noexit) exitProcess(-1) } } } diff --git a/src/main/kotlin/org/cryptobiotic/eg/cli/RunExampleEncryption.kt b/src/main/kotlin/org/cryptobiotic/eg/cli/RunExampleEncryption.kt index 5e62d63..afdb09a 100644 --- a/src/main/kotlin/org/cryptobiotic/eg/cli/RunExampleEncryption.kt +++ b/src/main/kotlin/org/cryptobiotic/eg/cli/RunExampleEncryption.kt @@ -12,6 +12,7 @@ import org.cryptobiotic.eg.input.RandomBallotProvider import org.cryptobiotic.eg.publish.makeConsumer import org.cryptobiotic.eg.publish.makePublisher import kotlin.random.Random +import kotlin.system.exitProcess /** * Simulates using RunEncryptBallot one ballot at a time. @@ -57,6 +58,12 @@ class RunExampleEncryption { shortName = "deviceDir", description = "Dont add device name to encrypted ballots directory" ).default(false) + val noexit by parser.option( + ArgType.Boolean, + shortName = "noexit", + description = "Dont call System.exit" + ).default(false) + parser.parse(args) val devices = deviceNames.split(",") @@ -65,58 +72,63 @@ class RunExampleEncryption { " outputDir = $outputDir\n devices = $devices\n noDeviceNameInDir= $noDeviceNameInDir" } - val consumerIn = makeConsumer(inputDir) - val initResult = consumerIn.readElectionInitialized() - if (initResult is Err) { - logger.error { "readElectionInitialized error ${initResult.error}" } - return - } - val electionInit = initResult.unwrap() - val manifest = consumerIn.makeManifest(electionInit.config.manifestBytes) - val errors = ManifestInputValidation(manifest).validate() - if (ManifestInputValidation(manifest).validate().hasErrors()) { - logger.error { "ManifestInputValidation error ${errors}" } - throw RuntimeException("ManifestInputValidation error $errors") - } - val chaining = electionInit.config.chainConfirmationCodes - val publisher = makePublisher(plaintextBallotDir) - var allOk = true + try { + val consumerIn = makeConsumer(inputDir) + val initResult = consumerIn.readElectionInitialized() + if (initResult is Err) { + logger.error { "readElectionInitialized error ${initResult.error}" } + if (!noexit) exitProcess(1) else return + } + val electionInit = initResult.unwrap() + val manifest = consumerIn.makeManifest(electionInit.config.manifestBytes) + val errors = ManifestInputValidation(manifest).validate() + if (ManifestInputValidation(manifest).validate().hasErrors()) { + logger.error { "ManifestInputValidation error ${errors}" } + if (!noexit) exitProcess(2) else return + } + val chaining = electionInit.config.chainConfirmationCodes + val publisher = makePublisher(plaintextBallotDir) + var allOk = true - val ballotProvider = RandomBallotProvider(manifest) - repeat(nballots) { - val pballot = ballotProvider.getFakeBallot(manifest, null, "ballot$it") - publisher.writePlaintextBallot(plaintextBallotDir, listOf(pballot)) - val pballotFilename = "$plaintextBallotDir/pballot-${pballot.ballotId}.json" - val deviceIdx = if(devices.size == 1) 0 else Random.nextInt(devices.size) - val device = devices[deviceIdx] - // val eballotDir = if (chaining || !noDeviceNameInDir) "$encryptBallotDir/$device" else encryptBallotDir - // createDirectories(eballotDir) + val ballotProvider = RandomBallotProvider(manifest) + repeat(nballots) { + val pballot = ballotProvider.getFakeBallot(manifest, null, "ballot$it") + publisher.writePlaintextBallot(plaintextBallotDir, listOf(pballot)) + val pballotFilename = "$plaintextBallotDir/pballot-${pballot.ballotId}.json" + val deviceIdx = if (devices.size == 1) 0 else Random.nextInt(devices.size) + val device = devices[deviceIdx] + // val eballotDir = if (chaining || !noDeviceNameInDir) "$encryptBallotDir/$device" else encryptBallotDir + // createDirectories(eballotDir) - val retval = RunEncryptBallot.encryptBallot( - consumerIn, - pballotFilename, - outputDir, - device, - noDeviceNameInDir, - ) - if (retval != 0) allOk = false - } - if (chaining) { - devices.forEach { device -> - RunEncryptBallot.encryptBallot( + val retval = RunEncryptBallot.encryptBallot( consumerIn, - "CLOSE", + pballotFilename, outputDir, device, noDeviceNameInDir, ) + if (retval != 0) allOk = false + } + if (chaining) { + devices.forEach { device -> + RunEncryptBallot.encryptBallot( + consumerIn, + "CLOSE", + outputDir, + device, + noDeviceNameInDir, + ) + } } - } - if (allOk) { - logger.info { "success" } - } else { - logger.error { "failure" } + if (allOk) { + logger.info { "success" } + } else { + if (!noexit) exitProcess(3) + } + } catch (t: Throwable) { + logger.error { "Exception= ${t.message} ${t.stackTraceToString()}" } + if (!noexit) exitProcess(-1) } } } diff --git a/src/test/kotlin/org/cryptobiotic/eg/cli/RunAddEncryptedBallotsTest.kt b/src/test/kotlin/org/cryptobiotic/eg/cli/RunAddEncryptedBallotsTest.kt index 15d3caa..065b7f6 100644 --- a/src/test/kotlin/org/cryptobiotic/eg/cli/RunAddEncryptedBallotsTest.kt +++ b/src/test/kotlin/org/cryptobiotic/eg/cli/RunAddEncryptedBallotsTest.kt @@ -18,6 +18,7 @@ class RunAddEncryptedBallotsTest { "--device", "device11", "--outputDir", outputDir, "--challengePct", "10", + "--noexit" ) ) @@ -38,6 +39,7 @@ class RunAddEncryptedBallotsTest { "--device", "device11", "--outputDir", outputDir, "--challengePct", "10", + "--noexit" ) ) diff --git a/src/test/kotlin/org/cryptobiotic/eg/cli/RunCreateInputBallotsTest.kt b/src/test/kotlin/org/cryptobiotic/eg/cli/RunCreateInputBallotsTest.kt index 268fe7a..0868da7 100644 --- a/src/test/kotlin/org/cryptobiotic/eg/cli/RunCreateInputBallotsTest.kt +++ b/src/test/kotlin/org/cryptobiotic/eg/cli/RunCreateInputBallotsTest.kt @@ -10,7 +10,8 @@ class RunCreateInputBallotsTest { arrayOf( "-manifest", "src/test/data/startConfigEc", "-out", "${Testing.testOut}/generateInputBallots", - "-n", "42" + "-n", "42", + "--noexit" ) ) } diff --git a/src/test/kotlin/org/cryptobiotic/eg/cli/RunCreateTestManifestTest.kt b/src/test/kotlin/org/cryptobiotic/eg/cli/RunCreateTestManifestTest.kt index 0131ba9..22a0a97 100644 --- a/src/test/kotlin/org/cryptobiotic/eg/cli/RunCreateTestManifestTest.kt +++ b/src/test/kotlin/org/cryptobiotic/eg/cli/RunCreateTestManifestTest.kt @@ -13,6 +13,7 @@ class RunCreateTestManifestTest { "-ncontests", "20", "-nselections", "4", "-out", "${Testing.testOut}/manifest/runCreateTestManifest", + "--noexit" ) ) } diff --git a/src/test/kotlin/org/cryptobiotic/eg/cli/RunExampleEncryptionTest.kt b/src/test/kotlin/org/cryptobiotic/eg/cli/RunExampleEncryptionTest.kt index 3c13cc5..3a75ae5 100644 --- a/src/test/kotlin/org/cryptobiotic/eg/cli/RunExampleEncryptionTest.kt +++ b/src/test/kotlin/org/cryptobiotic/eg/cli/RunExampleEncryptionTest.kt @@ -22,6 +22,7 @@ class RunExampleEncryptionTest { "--plaintextBallotDir", "$outputDir/plaintext", "--outputDir", outputDir, "-device", "device42,device11", + "--noexit" ) ) @@ -45,6 +46,7 @@ class RunExampleEncryptionTest { "-device", "device42,device11", "--outputDir", "$outputDir", "--noDeviceNameInDir", + "--noexit" ) ) diff --git a/src/test/kotlin/org/cryptobiotic/eg/encrypt/RunBatchEncryptionTest.kt b/src/test/kotlin/org/cryptobiotic/eg/encrypt/RunBatchEncryptionTest.kt index 831c859..0e5f694 100644 --- a/src/test/kotlin/org/cryptobiotic/eg/encrypt/RunBatchEncryptionTest.kt +++ b/src/test/kotlin/org/cryptobiotic/eg/encrypt/RunBatchEncryptionTest.kt @@ -9,6 +9,7 @@ import org.cryptobiotic.eg.publish.readElectionRecord import org.cryptobiotic.util.Testing import kotlin.test.Test import kotlin.test.assertContains +import kotlin.test.assertEquals class RunBatchEncryptionTest { @@ -25,6 +26,7 @@ RunBatchEncryptionTest { "-nthreads", "$nthreads", "-device", "device2", "--cleanOutput", + "--noexit" ) ) RunVerifier.runVerifier("${Testing.testOut}/encrypt/testRunBatchEncryptionWithEc", 11) @@ -41,6 +43,7 @@ RunBatchEncryptionTest { "-nthreads", "$nthreads", "-device", "device2", "--cleanOutput", + "--noexit" ) ) RunVerifier.runVerifier("${Testing.testOut}/encrypt/testRunBatchEncryptionWithInteger", 11) @@ -58,6 +61,7 @@ RunBatchEncryptionTest { "-device", "device4", "-check", "EncryptTwice", "--cleanOutput", + "--noexit" ) ) } @@ -74,6 +78,7 @@ RunBatchEncryptionTest { "-device", "device35", "-check", "Verify", "--cleanOutput", + "--noexit" ) ) } @@ -90,6 +95,7 @@ RunBatchEncryptionTest { "-device", "device42", "-check", "DecryptNonce", "--cleanOutput", + "--noexit" ) ) } @@ -105,7 +111,7 @@ RunBatchEncryptionTest { val ballot = RandomBallotProvider(electionRecord.manifest(), 1).makeBallot() val ballots = listOf( ballot.copy(ballotStyle = "badStyleId")) - batchEncryption( + val retval = batchEncryption( inputDir, ballots, device = "testDevice", @@ -115,6 +121,7 @@ RunBatchEncryptionTest { 1, "testInvalidBallot", ) + assertEquals(0, retval) val consumerOut = ConsumerJson(invalidDir, electionRecord.group) consumerOut.iteratePlaintextBallots(invalidDir, null).forEach { diff --git a/src/test/kotlin/org/cryptobiotic/eg/workflow/CreateTestManifest.kt b/src/test/kotlin/org/cryptobiotic/eg/workflow/CreateTestManifest.kt index 94f6c52..e9153f9 100644 --- a/src/test/kotlin/org/cryptobiotic/eg/workflow/CreateTestManifest.kt +++ b/src/test/kotlin/org/cryptobiotic/eg/workflow/CreateTestManifest.kt @@ -13,6 +13,7 @@ class CreateTestManifest { "-ncontests", "20", "-nselections", "4", "-out", "${Testing.testOut}/manifest/runCreateTestManifest", + "--noexit" ) ) }