How to use Array.shouldNotContain method of io.kotest.matchers.collections.contain class

Best Kotest code snippet using io.kotest.matchers.collections.contain.Array.shouldNotContain

TestLineTrace.kt

Source:TestLineTrace.kt Github

copy

Full Screen

1package edu.illinois.cs.cs125.jeed.core2import io.kotest.core.spec.style.StringSpec3import io.kotest.matchers.collections.beEmpty4import io.kotest.matchers.collections.shouldContain5import io.kotest.matchers.collections.shouldHaveAtLeastSize6import io.kotest.matchers.collections.shouldHaveAtMostSize7import io.kotest.matchers.collections.shouldHaveSize8import io.kotest.matchers.collections.shouldNotContain9import io.kotest.matchers.ints.beGreaterThan10import io.kotest.matchers.ints.shouldBeGreaterThan11import io.kotest.matchers.ints.shouldBeGreaterThanOrEqual12import io.kotest.matchers.ints.shouldBeLessThanOrEqual13import io.kotest.matchers.longs.shouldBeGreaterThan14import io.kotest.matchers.longs.shouldBeLessThanOrEqual15import io.kotest.matchers.should16import io.kotest.matchers.shouldBe17import io.kotest.matchers.shouldNot18import io.kotest.matchers.shouldNotBe19import io.kotest.matchers.string.endWith20import io.kotest.matchers.string.shouldStartWith21import io.kotest.matchers.types.beInstanceOf22import org.junit.jupiter.api.assertThrows23import java.lang.reflect.InvocationTargetException24class TestLineTrace : StringSpec({25    "should trace a main method" {26        val result = Source.fromJava(27            """28public class Main {29  public static void main() {30    int i = 4;31    i += 1;32    System.out.println(i);33  }34}""".trim()35        ).compile().execute(SourceExecutionArguments().addPlugin(LineTrace))36        result should haveCompleted()37        result should haveOutput("5")38        val trace = result.pluginResult(LineTrace)39        trace.steps shouldHaveAtLeastSize 340        trace.steps[0] shouldBe LineTraceResult.LineStep("Main.java", 3, 0)41    }42    "should trace an if statement" {43        val result = Source.fromJava(44            """45public class Main {46  public static void main() {47    int i = 4;48    if (i > 1) {49      System.out.println("yes");50    }51  }52}""".trim()53        ).compile().execute(SourceExecutionArguments().addPlugin(LineTrace))54        result should haveCompleted()55        result should haveOutput("yes")56        val trace = result.pluginResult(LineTrace)57        trace.steps shouldHaveAtLeastSize 358        trace.steps.map { it.line } shouldContain 559    }60    "should show that an if statement wasn't entered" {61        val result = Source.fromJava(62            """63public class Main {64  public static void main() {65    int i = 4;66    if (i > 9) {67      System.out.println("yes");68      System.out.println("the universe has fractured");69      System.out.println("all is possible");70    }71  }72}""".trim()73        ).compile().execute(SourceExecutionArguments().addPlugin(LineTrace))74        result should haveCompleted()75        result should haveOutput("")76        val trace = result.pluginResult(LineTrace)77        trace.steps shouldHaveAtMostSize 378        trace.steps.map { it.line } shouldNotContain 579    }80    "should trace an if-else statement" {81        val result = Source.fromJava(82            """83public class Main {84  public static void main() {85    int i = 0;86    if (i > 1) {87      System.out.println("yes");88    } else {89      System.out.println("no");90    }91  }92}""".trim()93        ).compile().execute(SourceExecutionArguments().addPlugin(LineTrace))94        result should haveCompleted()95        result should haveOutput("no")96        val trace = result.pluginResult(LineTrace)97        trace.steps.map { it.line } shouldNotContain 598        trace.steps.map { it.line } shouldContain 799    }100    "should trace a for loop" {101        val result = Source.fromJava(102            """103public class Main {104  public static void main() {105    for (int i = 0; i < 3; i++) {106      System.out.println(i);107    }108  }109}""".trim()110        ).compile().execute(SourceExecutionArguments().addPlugin(LineTrace))111        result should haveCompleted()112        result should haveOutput("0\n1\n2")113        val trace = result.pluginResult(LineTrace)114        trace.steps.filter { it.line == 4 }.size shouldBe 3115        trace.steps.filter { it.line == 3 }.size shouldBe 4116    }117    "should trace a while loop" {118        val result = Source.fromJava(119            """120public class Main {121  public static void main() {122    int i = 20;123    while (i > 0) {124      System.out.println(i);125      i /= 2;126      if (i % 2 != 0) {127        i -= 1;128      }129    }130  }131}""".trim()132        ).compile().execute(SourceExecutionArguments().addPlugin(LineTrace))133        result should haveCompleted()134        result should haveOutput("20\n10\n4\n2")135        val trace = result.pluginResult(LineTrace)136        trace.steps.filter { it.line == 5 }.size shouldBe 4137        trace.steps.filter { it.line == 8 }.size shouldBe 2138    }139    "should trace a try-catch-finally block" {140        val result = Source.fromJava(141            """142public class Main {143  public static void main() {144    try {145      System.out.println("Try");146      String s = null;147      s.toString();148      System.out.println("Hmm");149    } catch (Exception e) {150      System.out.println("Catch");151    } finally {152      System.out.println("Finally");153    }154  }155}""".trim()156        ).compile().execute(SourceExecutionArguments().addPlugin(LineTrace))157        result should haveCompleted()158        result should haveOutput("Try\nCatch\nFinally")159        val trace = result.pluginResult(LineTrace)160        trace.steps.filter { it.line == 4 }.size shouldBe 1161        trace.steps.filter { it.line == 7 }.size shouldBe 0162        trace.steps.filter { it.line == 9 }.size shouldBe 1163        trace.steps.filter { it.line == 11 }.size shouldBe 1164    }165    "should trace multiple functions" {166        val result = Source.fromJava(167            """168public class Main {169  public static void main() {170    for (int i = 0; i < 10; i++) {171      showIfOdd(i);172    }173    System.out.println("Done");174  }175  private static void showIfOdd(int i) {176    if (i % 2 != 0) {177      System.out.println(i);178    }179  }180}""".trim()181        ).compile().execute(SourceExecutionArguments().addPlugin(LineTrace))182        result should haveCompleted()183        result should haveOutput("1\n3\n5\n7\n9\nDone")184        val trace = result.pluginResult(LineTrace)185        trace.steps.filter { it.line == 4 }.size shouldBe 10186        trace.steps.filter { it.line == 6 }.size shouldBe 1187        trace.steps.filter { it.line == 9 }.size shouldBe 10188        trace.steps.filter { it.line == 10 }.size shouldBe 5189    }190    "should trace multiple classes" {191        val result = Source.fromJava(192            """193public class Main {194  public static void main() {195    for (int i = 0; i < 10; i++) {196      ShowIfOdd.showIfOdd(i);197    }198    System.out.println("Done");199  }200}201public class ShowIfOdd {202  public static void showIfOdd(int i) {203    if (i % 2 != 0) {204      System.out.println(i);205    }206  }207}""".trim()208        ).compile().execute(SourceExecutionArguments().addPlugin(LineTrace))209        result should haveCompleted()210        result should haveOutput("1\n3\n5\n7\n9\nDone")211        val trace = result.pluginResult(LineTrace)212        trace.steps.filter { it.line == 4 }.size shouldBe 10213        trace.steps.filter { it.line == 6 }.size shouldBe 1214        trace.steps.filter { it.line == 11 }.size shouldBe 10215        trace.steps.filter { it.line == 12 }.size shouldBe 5216        trace.linesRun shouldBe trace.steps.size217    }218    "should trace multiple files" {219        val result = Source(220            mapOf(221                "Main.java" to """222public class Main {223  public static void main() {224    for (int i = 0; i < 10; i++) {225      ShowIfOdd.showIfOdd(i);226    }227    System.out.println("Done");228  }229}""".trim(),230                "ShowIfOdd.java" to """231public class ShowIfOdd {232  public static void showIfOdd(int i) {233    if (i % 2 != 0) {234      System.out.println(i);235    }236  }237}""".trim()238            )239        ).compile().execute(SourceExecutionArguments().addPlugin(LineTrace))240        result should haveCompleted()241        result should haveOutput("1\n3\n5\n7\n9\nDone")242        val trace = result.pluginResult(LineTrace)243        trace.steps.filter { it.source == "Main.java" && it.line == 4 }.size shouldBe 10244        trace.steps.filter { it.source == "Main.java" && it.line == 6 }.size shouldBe 1245        trace.steps.filter { it.source == "ShowIfOdd.java" && it.line == 3 }.size shouldBe 10246        trace.steps.filter { it.source == "ShowIfOdd.java" && it.line == 4 }.size shouldBe 5247    }248    "should trace a simple snippet" {249        val source = Source.fromSnippet(250            """System.out.println("Hello");""".trim()251        )252        val result = source.compile().execute(SourceExecutionArguments().addPlugin(LineTrace))253        result should haveCompleted()254        result should haveOutput("Hello")255        val trace = result.pluginResult(LineTrace).remap(source)256        trace.steps shouldHaveSize 1257        trace.steps[0].line shouldBe 1258    }259    "should trace a snippet" {260        val source = Source.fromSnippet(261            """262            printWithObject();263            264            void printWithObject() {265              new Printer().print();266            }267            268            class Printer {269              void print() {270                System.out.println("Hello");271              }272              void unused() {273                System.out.println("Unused");274              }275            }276            """.trimIndent().trim()277        )278        val result = source.compile().execute(SourceExecutionArguments().addPlugin(LineTrace))279        result should haveCompleted()280        result should haveOutput("Hello")281        val trace = result.pluginResult(LineTrace).remap(source)282        trace.steps shouldHaveAtLeastSize 3283        trace.steps[0].line shouldBe 1284        trace.steps.filter { it.line == 4 }.size shouldBe 1285        trace.steps.filter { it.line == 9 }.size shouldBe 1286        trace.steps.filter { it.line == 12 }.size shouldBe 0287    }288    "should report multiple calls during external iteration" {289        val source = Source.fromSnippet(290            """291            import java.util.ArrayList;292            var list = new ArrayList<String>();293            list.add("a");294            list.add("b");295            list.add("c");296            list.forEach(s -> {297                System.out.println(s); }); // Crazy bracing to ensure only this line is called298            """.trimIndent()299        )300        val result = source.compile().execute(SourceExecutionArguments().addPlugin(LineTrace))301        result should haveCompleted()302        result should haveOutput("a\nb\nc")303        val trace = result.pluginResult(LineTrace).remap(source)304        trace.steps.filter { it.line == 6 }.size shouldBe 1305        trace.steps.filter { it.line == 7 }.size shouldBe 3306    }307    "should stop logging lines after reaching the recording limit" {308        val source = Source.fromSnippet(309            """310            long i = 0;311            while (true) {312                i += 2;313                i -= 1;314            }315            """.trimIndent()316        )317        val lineTraceArguments = LineTraceArguments(recordedLineLimit = 5000L) // Reduced because slow under debugger318        val result = source.compile().execute(SourceExecutionArguments().addPlugin(LineTrace, lineTraceArguments))319        result should haveTimedOut()320        val rawTrace = result.pluginResult(LineTrace)321        val trace = rawTrace.remap(source)322        trace.steps.filter { it.line == 3 }.size shouldBeGreaterThan 100323        rawTrace.steps.size shouldBe lineTraceArguments.recordedLineLimit324    }325    "should keep counting after reaching the recording limit" {326        val source = Source.fromSnippet(327            """328            long i = 0;329            while (true) {330                i += 2;331                i -= 1;332            }333            """.trimIndent()334        )335        val lineTraceArguments = LineTraceArguments(recordedLineLimit = 5000L)336        val result = source.compile().execute(SourceExecutionArguments().addPlugin(LineTrace, lineTraceArguments))337        result should haveTimedOut()338        val trace = result.pluginResult(LineTrace).remap(source)339        trace.linesRun.toInt() should beGreaterThan(trace.arguments.recordedLineLimit.toInt())340    }341    "should trace a Kotlin method" {342        val result = Source.fromKotlin(343            """344            fun main() {345                println("Hello")346            }347            """.trimIndent()348        ).kompile().execute(SourceExecutionArguments().addPlugin(LineTrace))349        result should haveCompleted()350        result should haveOutput("Hello")351        val trace = result.pluginResult(LineTrace)352        trace.steps shouldHaveAtMostSize 2353        trace.steps[0].line shouldBe 2354    }355    "should trace a Kotlin forEach loop" {356        val source = Source.fromKotlin(357            """358            fun main() {359                (1..3).forEach {360                    println(it * it)361                }362            }363            """.trimIndent()364        )365        val result = source.kompile().execute(SourceExecutionArguments().addPlugin(LineTrace))366        result should haveCompleted()367        result should haveOutput("1\n4\n9")368        val trace = result.pluginResult(LineTrace).remap(source)369        trace.steps shouldHaveAtLeastSize 4370        trace.steps[0].line shouldBe 2371        trace.steps.filter { it.line == 3 }.size shouldBe 3372        trace.steps.filter { it.line == 5 }.size shouldBe 1373        trace.steps.filter { it.line > 5 }.size shouldBe 0374    }375    "should trace across Kotlin files" {376        val source = Source(377            mapOf(378                "Main.kt" to """379fun main() {380  println(test())381}382                """.trim(),383                "Test.kt" to """384fun test(): List<String> {385  return listOf("test", "me")386}387                """.trim()388            )389        )390        val result = source.kompile().execute(SourceExecutionArguments().addPlugin(LineTrace))391        result should haveCompleted()392        result should haveOutput("[test, me]")393        val trace = result.pluginResult(LineTrace).remap(source)394        trace.steps shouldHaveAtLeastSize 2395        trace.steps[0] shouldBe LineTraceResult.LineStep("Main.kt", 2, 0)396        trace.steps[1] shouldBe LineTraceResult.LineStep("Test.kt", 2, 0)397    }398    "should trace a simple Kotlin snippet" {399        val source = Source.fromSnippet(400            """println("Hi")""", SnippetArguments(fileType = Source.FileType.KOTLIN)401        )402        val result = source.kompile().execute(SourceExecutionArguments().addPlugin(LineTrace))403        result should haveCompleted()404        result should haveOutput("Hi")405        val trace = result.pluginResult(LineTrace).remap(source)406        trace.steps shouldHaveSize 1407        trace.steps[0].line shouldBe 1408    }409    "should trace a Kotlin snippet with a loop" {410        val source = Source.fromSnippet(411            """412                val fruits = listOf("apple", "banana")413                fruits.forEach {414                    println(it + ".")415                }416            """.trimIndent(),417            SnippetArguments(fileType = Source.FileType.KOTLIN)418        )419        val result = source.kompile().execute(SourceExecutionArguments().addPlugin(LineTrace))420        result should haveCompleted()421        result should haveOutput("apple.\nbanana.")422        val trace = result.pluginResult(LineTrace).remap(source)423        trace.steps shouldHaveAtLeastSize 5424        trace.steps[0].line shouldBe 1425        trace.steps.filter { it.line == 3 }.size shouldBe 2426    }427    "should trace a Kotlin snippet with an if expression" {428        val source = Source.fromSnippet(429            """430                val i = System.currentTimeMillis() // Avoid compile-time evaluation431                val verdict = if (i > 0) {432                    "Positive"433                } else {434                    "Non-positive"435                }436                println(verdict)437            """.trimIndent(),438            SnippetArguments(fileType = Source.FileType.KOTLIN)439        )440        val result = source.kompile().execute(SourceExecutionArguments().addPlugin(LineTrace))441        result should haveCompleted()442        result should haveOutput("Positive")443        val trace = result.pluginResult(LineTrace).remap(source)444        trace.steps shouldHaveAtLeastSize 4 // NOTE: Storing the if expression's result visits line 2 again445        trace.steps[0].line shouldBe 1446        trace.steps[1].line shouldBe 2447        trace.steps[2].line shouldBe 3448        trace.steps.last().line shouldBe 7449        trace.steps.filter { it.line == 5 }.size shouldBe 0450    }451    "should trace a Kotlin snippet with a loop and inlined method" {452        val source = Source.fromSnippet(453            """454                val fruits = listOf("apple", "banana")455                fruits.forEach {456                    println(it.uppercase())457                }458            """.trimIndent(),459            SnippetArguments(fileType = Source.FileType.KOTLIN)460        )461        val result = source.kompile().execute(SourceExecutionArguments().addPlugin(LineTrace))462        result should haveCompleted()463        result should haveOutput("APPLE\nBANANA")464        val trace = result.pluginResult(LineTrace).remap(source)465        trace.steps shouldHaveAtLeastSize 3466        trace.steps[0].line shouldBe 1467        trace.steps.filter { it.line == 3 }.size shouldBe 2468    }469    "should skip Kotlin inline/loop duplicates" {470        val source = Source.fromSnippet(471            """472                val fruits = listOf("apple", "banana")473                fruits.forEach { println(it.uppercase()) }474            """.trimIndent(),475            SnippetArguments(fileType = Source.FileType.KOTLIN)476        )477        val result = source.kompile().execute(SourceExecutionArguments().addPlugin(LineTrace))478        result should haveCompleted()479        result should haveOutput("APPLE\nBANANA")480        val trace = result.pluginResult(LineTrace).remap(source)481        trace.steps.filter { it.line == 2 }.size shouldBeLessThanOrEqual 3482    }483    "should allow recording duplicates" {484        val source = Source.fromSnippet(485            """486                val fruits = listOf("apple", "banana")487                fruits.forEach { println(it.uppercase()) }488            """.trimIndent(),489            SnippetArguments(fileType = Source.FileType.KOTLIN)490        )491        val result = source.kompile().execute(492            SourceExecutionArguments().addPlugin(LineTrace, LineTraceArguments(coalesceDuplicates = false))493        )494        result should haveCompleted()495        result should haveOutput("APPLE\nBANANA")496        val trace = result.pluginResult(LineTrace).remap(source)497        trace.steps.filter { it.line == 2 }.size shouldBeGreaterThan 3498    }499    "should trace a Kotlin snippet with a method" {500        val source = Source.fromSnippet(501            """502                fun printLoud(text: String) {503                    println(text.uppercase())504                }505                506                val fruits = listOf("apple", "banana")507                fruits.forEach(::printLoud)508            """.trimIndent(),509            SnippetArguments(fileType = Source.FileType.KOTLIN)510        )511        val result = source.kompile().execute(SourceExecutionArguments().addPlugin(LineTrace))512        result should haveCompleted()513        result should haveOutput("APPLE\nBANANA")514        val trace = result.pluginResult(LineTrace).remap(source)515        trace.steps shouldHaveAtLeastSize 4516        trace.steps[0].line shouldBe 5517        trace.steps.filter { it.line == 2 }.size shouldBeGreaterThanOrEqual 2518        trace.steps.filter { it.line == 3 }.size shouldBe 2519        trace.steps.filter { it.line == 4 }.size shouldBe 0520    }521    "should trace multiple threads" {522        val source = Source.fromSnippet(523            """524public class Example implements Runnable {525    public void run() {526        System.out.println("Ended");527    }528}529Thread thread = new Thread(new Example());530thread.start();531System.out.println("Started");532try {533    thread.join();534} catch (Exception e) {535    throw new RuntimeException(e);536}537        """.trim()538        )539        val result = source.compile().execute(SourceExecutionArguments(maxExtraThreads = 1).addPlugin(LineTrace))540        result should haveCompleted()541        result should haveOutput("Started\nEnded")542        val rawTrace = result.pluginResult(LineTrace)543        rawTrace.linesRun shouldBe rawTrace.steps.size544        val trace = rawTrace.remap(source)545        val mainLines = trace.steps.filter { it.threadIndex == 0 }.map { it.line }546        mainLines shouldContain 6547        mainLines shouldContain 10548        mainLines shouldNotContain 3549        val extraLines = trace.steps.filter { it.threadIndex == 1 }.map { it.line }550        extraLines shouldContain 3551        extraLines shouldNotContain 6552        trace.steps.filter { it.threadIndex >= 2 }.size shouldBe 0553    }554    "should trace multiple threads using coroutines" {555        val source = Source.fromKotlin(556            """557            import kotlinx.coroutines.*558            fun main() {559                GlobalScope.launch {560                    delay(100)561                    println("Finished")562                }563                println("Started")564            }565            """.trimIndent()566        )567        val executionArgs = SourceExecutionArguments(waitForShutdown = true, timeout = 2000).addPlugin(LineTrace)568        val result = source.kompile().execute(executionArgs)569        result should haveCompleted()570        result should haveOutput("Started\nFinished")571        val rawTrace = result.pluginResult(LineTrace)572        rawTrace.linesRun shouldBe rawTrace.steps.size573        val trace = rawTrace.remap(source)574        val mainLines = trace.steps.filter { it.threadIndex == 0 }.map { it.line }575        mainLines shouldContain 3576        mainLines shouldContain 7577        mainLines shouldNotContain 5578        val extraLines = trace.steps.filter { it.threadIndex == 1 }.map { it.line }579        extraLines shouldContain 5580        extraLines shouldNotContain 7581        trace.steps.filter { it.threadIndex >= 2 }.size shouldBe 0582        trace.steps.filter { it.source != "Main.kt" }.size shouldBe 0583    }584    "should limit executed lines by killing the sandbox" {585        val source = Source.fromSnippet(586            """587            long i = 0;588            while (true) {589                i += 2;590                i -= 1;591            }592            """.trimIndent()593        )594        val result = source.compile().execute(595            SourceExecutionArguments().addPlugin(596                LineTrace, LineTraceArguments(recordedLineLimit = 0, runLineLimit = 100)597            )598        )599        result should haveBeenKilled()600        result.killReason shouldBe LineTrace.KILL_REASON601        result shouldNot haveCompleted()602        result shouldNot haveTimedOut()603        val trace = result.pluginResult(LineTrace)604        trace.linesRun shouldBe 100605        trace.steps should beEmpty()606    }607    "should limit executed lines by throwing an error" {608        val source = Source.fromSnippet(609            """610            try {611              long i = 0;612              while (true) {613                i += 2;614                i -= 1;615              }616            } catch (Throwable t) {}617            """.trimIndent()618        )619        val lineTraceArgs = LineTraceArguments(620            recordedLineLimit = 0,621            runLineLimit = 100,622            runLineLimitExceededAction = LineTraceArguments.RunLineLimitAction.THROW_ERROR623        )624        val result = source.compile().execute(SourceExecutionArguments().addPlugin(LineTrace, lineTraceArgs))625        result shouldNot haveBeenKilled()626        result shouldNot haveCompleted()627        result shouldNot haveTimedOut()628        result.threw should beInstanceOf<LineLimitExceeded>()629        val trace = result.pluginResult(LineTrace)630        trace.linesRun shouldBe 100631    }632    "should limit total lines from multiple threads" {633        val source = Source.fromSnippet(634            """635public class Example implements Runnable {636    public void run() {637        long e = 0;638        while (true) {639            e += 1;640        }641    }642}643Thread thread = new Thread(new Example());644thread.start();645long i = 0;646while (true) {647    i += 1;648}649        """.trim()650        )651        val lineTraceArgs = LineTraceArguments(runLineLimit = 10000)652        val result =653            source.compile().execute(SourceExecutionArguments(maxExtraThreads = 1).addPlugin(LineTrace, lineTraceArgs))654        result should haveBeenKilled()655        val rawTrace = result.pluginResult(LineTrace)656        rawTrace.linesRun.toInt() shouldBeGreaterThan rawTrace.steps.size - 3 // May be killed before incrementing657        rawTrace.linesRun.toInt() shouldBeLessThanOrEqual rawTrace.steps.size658        val trace = rawTrace.remap(source)659        val mainLines = trace.steps.filter { it.threadIndex == 0 }.map { it.line }660        mainLines shouldContain 10661        mainLines shouldNotContain 5662        val extraLines = trace.steps.filter { it.threadIndex == 1 }.map { it.line }663        extraLines shouldContain 5664        extraLines shouldNotContain 10665        trace.linesRun shouldBeLessThanOrEqual lineTraceArgs.runLineLimit!! + lineTraceArgs.maxUnsynchronizedLines666    }667    "should closely limit total lines if required" {668        val source = Source.fromSnippet(669            """670public class Example implements Runnable {671    public void run() {672        long e = 0;673        while (true) {674            e += 1;675        }676    }677}678Thread thread = new Thread(new Example());679thread.start();680long i = 0;681while (true) {682    i += 1;683}684        """.trim()685        )686        val lineTraceArgs = LineTraceArguments(687            runLineLimit = 10000, recordedLineLimit = 0, maxUnsynchronizedLines = 0688        )689        val compiledSource = source.compile()690        repeat(10) {691            val result = compiledSource.execute(692                SourceExecutionArguments(maxExtraThreads = 1).addPlugin(693                    LineTrace, lineTraceArgs694                )695            )696            result should haveBeenKilled()697            val rawTrace = result.pluginResult(LineTrace)698            rawTrace.linesRun shouldBeLessThanOrEqual lineTraceArgs.runLineLimit!! + 1699        }700    }701    "should not allow untrusted code to reset the line counter" {702        val source = Source.fromSnippet(703            """edu.illinois.cs.cs125.jeed.core.LineTrace.resetLineCounts()""",704            SnippetArguments(fileType = Source.FileType.KOTLIN)705        )706        val result = source.kompile().execute(SourceExecutionArguments().addPlugin(LineTrace))707        result shouldNot haveCompleted()708        result.permissionDenied shouldBe true709    }710    "should allow trusted code to reset the line counter" {711        val compiledSource = Source.fromJava(712            """713public class Main {714  public static void print(String text, int times) {715    for (int i = 0; i < times; i++) {716      System.out.print(text);717    } // At least 2, probably 3 lines per iteration718    System.out.println("");719  }720}""".trim()721        ).compile()722        val lineTraceArgs = LineTraceArguments(723            recordedLineLimit = 0, runLineLimit = 25724        )725        val plugins = listOf(ConfiguredSandboxPlugin(LineTrace, lineTraceArgs))726        val subtaskLinesRun = mutableListOf<Long>()727        val result = Sandbox.execute(compiledSource.classLoader, configuredPlugins = plugins) { (loader, _) ->728            val method = loader.loadClass("Main").getMethod("print", String::class.java, Int::class.java)729            method(null, "A", 3)730            subtaskLinesRun.add(LineTrace.getCurrentReport().linesRun)731            LineTrace.resetLineCounts()732            method(null, "B", 4)733            subtaskLinesRun.add(LineTrace.getCurrentReport().linesRun)734            LineTrace.resetLineCounts()735            method(null, "C", 5)736            subtaskLinesRun.add(LineTrace.getCurrentReport().linesRun)737        }738        result should haveCompleted()739        @Suppress("SpellCheckingInspection")740        result should haveOutput("AAA\nBBBB\nCCCCC")741        subtaskLinesRun.size shouldBe 3742        subtaskLinesRun[0] shouldBeGreaterThan 7743        subtaskLinesRun[1] shouldBeGreaterThan 9744        subtaskLinesRun[2] shouldBeGreaterThan 11 // At least 27 lines run in total745    }746    "should allow trusted code to handle the limit exception" {747        val compiledSource = Source.fromJava(748            """749public class Main {750  public static void print(String text, int times) {751    try {752      for (int i = 0; i < times; i++) {753        System.out.print(text);754      }755      System.out.println("");756    } catch (Throwable t) {}757  }758}""".trim()759        ).compile()760        val lineTraceArgs = LineTraceArguments(761            recordedLineLimit = 0,762            runLineLimit = 15,763            runLineLimitExceededAction = LineTraceArguments.RunLineLimitAction.THROW_ERROR764        )765        val plugins = listOf(ConfiguredSandboxPlugin(LineTrace, lineTraceArgs))766        var hitLimit = false767        val result = Sandbox.execute(compiledSource.classLoader, configuredPlugins = plugins) { (loader, _) ->768            val method = loader.loadClass("Main").getMethod("print", String::class.java, Int::class.java)769            try {770                method(null, "A", 15)771            } catch (e: InvocationTargetException) {772                hitLimit = e.cause is LineLimitExceeded773            }774            LineTrace.resetLineCounts()775            method(null, "B", 2)776        }777        result should haveCompleted()778        result.output should endWith("BB")779        hitLimit shouldBe true780    }781    "should be compatible with Jacoco" {782        val result = Source.fromJava(783            """784public class Test {785  private int value;786  public Test() {787    value = 10;788  }789  public Test(int setValue) {790    value = setValue;791  }792}793public class Main {794  public static void main() {795    Test test = new Test(10);796    System.out.println("Done");797  }798}""".trim()799        ).compile().execute(SourceExecutionArguments().addPlugin(Jacoco).addPlugin(LineTrace))800        result.completed shouldBe true801        result.permissionDenied shouldNotBe true802        result should haveOutput("Done")803        val coverage = result.pluginResult(Jacoco)804        val testCoverage = coverage.classes.find { it.name == "Test" }!!805        testCoverage.lineCounter.missedCount shouldBeGreaterThanOrEqual 1806        testCoverage.lineCounter.coveredCount shouldBe 3807        val trace = result.pluginResult(LineTrace)808        trace.steps[0].line shouldBe 12809        trace.steps.map { it.line } shouldContain 7810        trace.steps.map { it.line } shouldNotContain 4811    }812    "should not be installable as a duplicate" {813        val source = Source.fromJava(814            """815public class Main {816  public static void main() {817    System.out.println("Done");818  }819}""".trim()820        )821        assertThrows<IllegalStateException> {822            source.compile().execute(SourceExecutionArguments().addPlugin(LineTrace).addPlugin(LineTrace))823        }.message shouldStartWith "Duplicate plugin: edu.illinois.cs.cs125.jeed.core.LineTrace"824    }825})...

Full Screen

Full Screen

ClassContainerJarTest.kt

Source:ClassContainerJarTest.kt Github

copy

Full Screen

1package com.anatawa12.relocator.internal2import com.anatawa12.relocator.file.SingleFile3import com.anatawa12.relocator.internal.ClassContainer.Jar.Companion.META_INF_VERSIONS4import io.kotest.core.spec.style.DescribeSpec5import io.kotest.matchers.*6import io.kotest.matchers.collections.shouldBeEmpty7import io.kotest.matchers.collections.shouldContain8import io.kotest.matchers.collections.shouldNotContain9import kotlinx.coroutines.Dispatchers10import kotlinx.coroutines.withContext11import java.io.OutputStream12import java.nio.file.Files13import java.util.jar.JarFile14import java.util.zip.ZipEntry15import java.util.zip.ZipOutputStream16class ClassContainerJarTest : DescribeSpec() {17    private fun makeJar(out: OutputStream, withManifest: Boolean) {18        ZipOutputStream(out).use { zipOut ->19            val writer = zipOut.writer()20            // root entries21            zipOut.putNextEntry(ZipEntry("root-only.txt"))22            writer.apply { write("root") }.flush()23            zipOut.putNextEntry(ZipEntry("9-root.txt"))24            writer.apply { write("root") }.flush()25            zipOut.putNextEntry(ZipEntry("9-10-root.txt"))26            writer.apply { write("root") }.flush()27            zipOut.putNextEntry(ZipEntry("8-root.txt"))28            writer.apply { write("root") }.flush()29            // release 9 entries for basic30            zipOut.putNextEntry(ZipEntry("$META_INF_VERSIONS/9/9-only.txt"))31            writer.apply { write("9") }.flush()32            zipOut.putNextEntry(ZipEntry("$META_INF_VERSIONS/9/9-root.txt"))33            writer.apply { write("9") }.flush()34            zipOut.putNextEntry(ZipEntry("$META_INF_VERSIONS/9/9-10-root.txt"))35            writer.apply { write("9") }.flush()36            zipOut.putNextEntry(ZipEntry("$META_INF_VERSIONS/9/9-10-only.txt"))37            writer.apply { write("9") }.flush()38            // release 10 entries for multiple release39            zipOut.putNextEntry(ZipEntry("$META_INF_VERSIONS/10/10-only.txt"))40            writer.apply { write("10") }.flush()41            zipOut.putNextEntry(ZipEntry("$META_INF_VERSIONS/10/9-10-root.txt"))42            writer.apply { write("10") }.flush()43            zipOut.putNextEntry(ZipEntry("$META_INF_VERSIONS/10/9-10-only.txt"))44            writer.apply { write("10") }.flush()45            // invalid version/release: 846            zipOut.putNextEntry(ZipEntry("$META_INF_VERSIONS/8/8-only.txt"))47            writer.apply { write("8") }.flush()48            zipOut.putNextEntry(ZipEntry("$META_INF_VERSIONS/8/8-root.txt"))49            writer.apply { write("8") }.flush()50            // files on META-INF/versions51            zipOut.putNextEntry(ZipEntry("$META_INF_VERSIONS/9"))52            writer.apply { write("$META_INF_VERSIONS/9") }.flush()53            zipOut.putNextEntry(ZipEntry("$META_INF_VERSIONS/test.txt"))54            writer.apply { write("$META_INF_VERSIONS/test.txt") }.flush()55            // enable multi release if withManifest is true56            if (withManifest) {57                zipOut.putNextEntry(ZipEntry(JarFile.MANIFEST_NAME))58                writer.apply {59                    write("""60                    Manifest-Version: 1.061                    Multi-Release: true62                """.trimIndent())63                }.flush()64            }65        }66    }67    init {68        describe("multi release support") {69            val temp = withContext(Dispatchers.IO) {70                val temp = Files.createTempFile("multi-release", ".jar")71                makeJar(Files.newOutputStream(temp), true)72                temp73            }74            val jar = ClassContainer.Jar(temp.toFile())75            it("version list") {76                jar.releases.toSet() shouldBe setOf(9, 10)77            }78            it("check path list") {79                // check multi-release resources80                jar.files shouldContain "root-only.txt"81                jar.files shouldContain "9-only.txt"82                jar.files shouldContain "10-only.txt"83                jar.files shouldContain "9-10-only.txt"84                jar.files shouldContain "9-root.txt"85                jar.files shouldContain "9-10-root.txt"86                jar.files shouldContain "8-root.txt"87                // check files in versions/8 are exists88                jar.files shouldContain "$META_INF_VERSIONS/8/8-only.txt"89                jar.files shouldContain "$META_INF_VERSIONS/8/8-root.txt"90                // check files on META-INF/versions91                jar.files shouldContain "$META_INF_VERSIONS/9"92                jar.files shouldContain "$META_INF_VERSIONS/test.txt"93                // check files in versions/(9|10) are not exists94                jar.files shouldNotContain "$META_INF_VERSIONS/9/9-only.txt"95                jar.files shouldNotContain "$META_INF_VERSIONS/9/9-root.txt"96                jar.files shouldNotContain "$META_INF_VERSIONS/9/9-10-root.txt"97                jar.files shouldNotContain "$META_INF_VERSIONS/9/9-10-only.txt"98                jar.files shouldNotContain "$META_INF_VERSIONS/10/10-only.txt"99                jar.files shouldNotContain "$META_INF_VERSIONS/10/9-10-root.txt"100                jar.files shouldNotContain "$META_INF_VERSIONS/10/9-10-only.txt"101            }102            it("check resolve") {103                // root entries104                jar.loadFiles("root-only.txt") should haveFile("root", 0)105                jar.loadFiles("9-root.txt") should haveFile("root", 0)106                jar.loadFiles("9-10-root.txt") should haveFile("root", 0)107                jar.loadFiles("8-root.txt") should haveFile("root", 0)108                // release 9 entries for basic109                jar.loadFiles("$META_INF_VERSIONS/9/9-only.txt") should haveFile("9", 0)110                jar.loadFiles("$META_INF_VERSIONS/9/9-root.txt") should haveFile("9", 0)111                jar.loadFiles("$META_INF_VERSIONS/9/9-10-root.txt") should haveFile("9", 0)112                jar.loadFiles("$META_INF_VERSIONS/9/9-10-only.txt") should haveFile("9", 0)113                jar.loadFiles("$META_INF_VERSIONS/9/9-only.txt").size shouldBe 1114                jar.loadFiles("$META_INF_VERSIONS/9/9-root.txt").size shouldBe 1115                jar.loadFiles("$META_INF_VERSIONS/9/9-10-root.txt").size shouldBe 1116                jar.loadFiles("$META_INF_VERSIONS/9/9-10-only.txt").size shouldBe 1117                jar.loadFiles("9-only.txt") should haveFile("9", 9)118                jar.loadFiles("9-root.txt") should haveFile("9", 9)119                jar.loadFiles("9-10-root.txt") should haveFile("9", 9)120                jar.loadFiles("9-10-only.txt") should haveFile("9", 9)121                // release 10 entries for multiple release122                jar.loadFiles("$META_INF_VERSIONS/10/10-only.txt") should haveFile("10", 0)123                jar.loadFiles("$META_INF_VERSIONS/10/9-10-root.txt") should haveFile("10", 0)124                jar.loadFiles("$META_INF_VERSIONS/10/9-10-only.txt") should haveFile("10", 0)125                jar.loadFiles("$META_INF_VERSIONS/10/10-only.txt").size shouldBe 1126                jar.loadFiles("$META_INF_VERSIONS/10/9-10-root.txt").size shouldBe 1127                jar.loadFiles("$META_INF_VERSIONS/10/9-10-only.txt").size shouldBe 1128                jar.loadFiles("10-only.txt") should haveFile("10", 10)129                jar.loadFiles("9-10-root.txt") should haveFile("10", 10)130                jar.loadFiles("9-10-only.txt") should haveFile("10", 10)131                // invalid version/release: 8132                jar.loadFiles("$META_INF_VERSIONS/8/8-only.txt") should haveFile("8", 0)133                jar.loadFiles("$META_INF_VERSIONS/8/8-root.txt") should haveFile("8", 0)134                jar.loadFiles("8-only.txt").shouldBeEmpty()135                jar.loadFiles("8-root.txt") shouldNot haveRelease(8)136                // files on META-INF/versions137                jar.loadFiles("$META_INF_VERSIONS/9") should haveFile("$META_INF_VERSIONS/9", 0)138                jar.loadFiles("$META_INF_VERSIONS/test.txt") should haveFile("$META_INF_VERSIONS/test.txt", 0)139            }140            finalizeSpec { withContext(Dispatchers.IO) { Files.delete(temp) } }141        }142        describe("non multi release support") {143            val temp = withContext(Dispatchers.IO) {144                val temp = Files.createTempFile("multi-release", ".jar")145                makeJar(Files.newOutputStream(temp), false)146                temp147            }148            val jar = ClassContainer.Jar(temp.toFile())149            it("version list") {150                jar.releases.toSet().shouldBeEmpty()151            }152            it("check path list") {153                // check multi-release resources154                jar.files shouldContain "root-only.txt"155                jar.files shouldNotContain "9-only.txt"156                jar.files shouldNotContain "10-only.txt"157                jar.files shouldNotContain "9-10-only.txt"158                jar.files shouldContain "9-root.txt"159                jar.files shouldContain "9-10-root.txt"160                jar.files shouldContain "8-root.txt"161                // check files in versions/8 are exists162                jar.files shouldContain "$META_INF_VERSIONS/8/8-only.txt"163                jar.files shouldContain "$META_INF_VERSIONS/8/8-root.txt"164                // check files on META-INF/versions165                jar.files shouldContain "$META_INF_VERSIONS/9"166                jar.files shouldContain "$META_INF_VERSIONS/test.txt"167                // check files in versions/(9|10) are not exists168                jar.files shouldContain "$META_INF_VERSIONS/9/9-only.txt"169                jar.files shouldContain "$META_INF_VERSIONS/9/9-root.txt"170                jar.files shouldContain "$META_INF_VERSIONS/9/9-10-root.txt"171                jar.files shouldContain "$META_INF_VERSIONS/9/9-10-only.txt"172                jar.files shouldContain "$META_INF_VERSIONS/10/10-only.txt"173                jar.files shouldContain "$META_INF_VERSIONS/10/9-10-root.txt"174                jar.files shouldContain "$META_INF_VERSIONS/10/9-10-only.txt"175            }176            it("check resolve") {177                // root entries178                jar.loadFiles("root-only.txt") should haveFile("root", 0)179                jar.loadFiles("9-root.txt") should haveFile("root", 0)180                jar.loadFiles("9-10-root.txt") should haveFile("root", 0)181                jar.loadFiles("8-root.txt") should haveFile("root", 0)182                // release 9 entries for basic183                jar.loadFiles("$META_INF_VERSIONS/9/9-only.txt") should haveFile("9", 0)184                jar.loadFiles("$META_INF_VERSIONS/9/9-root.txt") should haveFile("9", 0)185                jar.loadFiles("$META_INF_VERSIONS/9/9-10-root.txt") should haveFile("9", 0)186                jar.loadFiles("$META_INF_VERSIONS/9/9-10-only.txt") should haveFile("9", 0)187                jar.loadFiles("$META_INF_VERSIONS/9/9-only.txt").size shouldBe 1188                jar.loadFiles("$META_INF_VERSIONS/9/9-root.txt").size shouldBe 1189                jar.loadFiles("$META_INF_VERSIONS/9/9-10-root.txt").size shouldBe 1190                jar.loadFiles("$META_INF_VERSIONS/9/9-10-only.txt").size shouldBe 1191                jar.loadFiles("9-only.txt").shouldBeEmpty()192                jar.loadFiles("9-root.txt").size shouldBe 1193                jar.loadFiles("9-10-root.txt").size shouldBe 1194                jar.loadFiles("9-10-only.txt").shouldBeEmpty()195                // release 10 entries for multiple release196                jar.loadFiles("$META_INF_VERSIONS/10/10-only.txt") should haveFile("10", 0)197                jar.loadFiles("$META_INF_VERSIONS/10/9-10-root.txt") should haveFile("10", 0)198                jar.loadFiles("$META_INF_VERSIONS/10/9-10-only.txt") should haveFile("10", 0)199                jar.loadFiles("$META_INF_VERSIONS/10/10-only.txt").size shouldBe 1200                jar.loadFiles("$META_INF_VERSIONS/10/9-10-root.txt").size shouldBe 1201                jar.loadFiles("$META_INF_VERSIONS/10/9-10-only.txt").size shouldBe 1202                jar.loadFiles("10-only.txt").shouldBeEmpty()203                jar.loadFiles("9-10-root.txt").size shouldBe 1204                jar.loadFiles("9-10-only.txt").shouldBeEmpty()205                // invalid version/release: 8206                jar.loadFiles("$META_INF_VERSIONS/8/8-only.txt") should haveFile("8", 0)207                jar.loadFiles("$META_INF_VERSIONS/8/8-root.txt") should haveFile("8", 0)208                jar.loadFiles("8-only.txt").shouldBeEmpty()209                jar.loadFiles("8-root.txt") shouldNot haveRelease(8)210                // files on META-INF/versions211                jar.loadFiles("$META_INF_VERSIONS/9") should haveFile("$META_INF_VERSIONS/9", 0)212                jar.loadFiles("$META_INF_VERSIONS/test.txt") should haveFile("$META_INF_VERSIONS/test.txt", 0)213            }214            finalizeSpec { withContext(Dispatchers.IO) { Files.delete(temp) } }215        }216    }217    private fun haveFile(body: String, release: Int) = object : Matcher<Collection<SingleFile>> {218        override fun test(value: Collection<SingleFile>): MatcherResult =219            if (value.any { it.data.contentEquals(body.toByteArray()) && it.release == release }) {220                MatcherResult(true, { error("") },221                    { "Collection that have SingleFile for release $release with body '$body'is not expected." }222                )223            } else {224                val contentEq = value.firstOrNull { it.data.contentEquals(body.toByteArray()) }225                if (contentEq != null) {226                    MatcherResult(227                        false,228                        {229                            "Expected collection that have SingleFile for release $release with body '$body'" +230                                    " but not found for $release"231                        },232                        { error("") }233                    )234                } else {235                    MatcherResult(236                        false,237                        { "Expected collection that have SingleFile for release $release with body '$body'." },238                        { error("") }239                    )240                }241            }242    }243    private fun haveRelease(@Suppress("SameParameterValue") release: Int) = object : Matcher<Collection<SingleFile>> {244        override fun test(value: Collection<SingleFile>) = MatcherResult(245            value.any { it.release == release },246            { "Expected collection that have SingleFile for release $release." },247            { "Collection that have SingleFile for release $release is not expected." }248        )249    }250}...

Full Screen

Full Screen

DogControllerIntegrationTest.kt

Source:DogControllerIntegrationTest.kt Github

copy

Full Screen

1package pl.poznan.put.dogloverservice.modules.dog2import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule3import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper4import com.fasterxml.jackson.module.kotlin.readValue5import io.kotest.core.spec.style.AnnotationSpec6import io.kotest.matchers.collections.shouldContain7import io.kotest.matchers.collections.shouldNotContain8import io.kotest.matchers.equality.shouldBeEqualToIgnoringFields9import io.kotest.matchers.should10import io.kotest.matchers.shouldBe11import io.kotest.matchers.shouldNotBe12import io.kotest.spring.SpringListener13import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc14import org.springframework.boot.test.context.SpringBootTest15import org.springframework.http.MediaType16import org.springframework.security.test.context.support.WithMockUser17import org.springframework.test.context.ActiveProfiles18import org.springframework.test.web.servlet.MockMvc19import org.springframework.test.web.servlet.get20import org.springframework.test.web.servlet.multipart21import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*22import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status23import pl.poznan.put.dogloverservice.infrastructure.exceptions.InvalidAvatarImageException24import pl.poznan.put.dogloverservice.modules.dog.dto.DogDTO25import pl.poznan.put.dogloverservice.modules.dog.dto.UpdateDogDTO26import javax.transaction.Transactional27@Transactional28@ActiveProfiles("integration")29@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)30@WithMockUser(authorities = ["SCOPE_dog-lover"], value = "9c04f2d5-0f58-4f1b-9f1a-0a2a3a25fad5")31@AutoConfigureMockMvc32class DogControllerIntegrationTest(33        val mockMvc: MockMvc34) : AnnotationSpec() {35    override fun listeners() = listOf(SpringListener)36    @Test37    fun `Should add dog`() {38        //given39        val updateDogDTO = UpdateDogDTO(DogData.burek)40        val expectedDogDTO = DogDTO(DogData.burek)41        //when42        val response = mockMvc.perform(post("/dogs")43                .content(jacksonObjectMapper().registerModule(JavaTimeModule()).writeValueAsString(updateDogDTO))44                .contentType(MediaType.APPLICATION_JSON))45                .andExpect(status().isCreated)46                .andReturn()47                .response48                .contentAsString49        val returnedDogDTO = jacksonObjectMapper().registerModule(JavaTimeModule()).readValue<DogDTO>(response)50        //then51        returnedDogDTO.should {52            it.name shouldBe expectedDogDTO.name53            it.breed shouldBe expectedDogDTO.breed54            it.color shouldBe expectedDogDTO.color55            it.description shouldBe expectedDogDTO.description56            it.lastVaccinationDate shouldBe expectedDogDTO.lastVaccinationDate57            it.avatarChecksum shouldBe null58        }59    }60    @Test61    fun `Should throw while adding existing dog`() {62        //given63        val dogLoverId = "9c04f2d5-0f58-4f1b-9f1a-0a2a3a25fad5"64        val updateDogDTO = UpdateDogDTO(DogData.yogi)65        //when66        mockMvc.perform(post("/dogs")67                .content(jacksonObjectMapper().registerModule(JavaTimeModule()).writeValueAsString(updateDogDTO))68                .contentType(MediaType.APPLICATION_JSON))69                //then70                .andExpect(status().isConflict)71                .andExpect(status().reason("Dog with name: ${updateDogDTO.name} already exists for user with id: $dogLoverId."))72    }73    @Test74    fun `Should update dog with avatar`() {75        //given76        val updateDogDTO = UpdateDogDTO(DogData.yogi)77        val expectedDogDTO = DogDTO(DogData.yogi)78        val dogId = expectedDogDTO.id79        val avatarMultipartFile = DogAvatarImageData.avatarMultipartFile80        mockMvc.multipart("/dogs/$dogId/avatar") {81            file(avatarMultipartFile)82            with {83                it.apply { method = "PUT" }84            }85        }86                //then87                .andExpect {88                    status { isOk }89                }90        //when91        val response = mockMvc.perform(put("/dogs")92                .content(jacksonObjectMapper().registerModule(JavaTimeModule()).writeValueAsString(updateDogDTO))93                .contentType(MediaType.APPLICATION_JSON))94                .andExpect(status().isOk)95                .andReturn()96                .response97                .contentAsString98        val returnedDogDTO = jacksonObjectMapper().registerModule(JavaTimeModule()).readValue<DogDTO>(response)99        //then100        returnedDogDTO.shouldBeEqualToIgnoringFields(expectedDogDTO, DogDTO::avatarChecksum)101        returnedDogDTO.avatarChecksum shouldNotBe null102    }103    @Test104    fun `Should get dog lover dogs`() {105        //given106        val dogName = "yogi"107        //when108        val response = mockMvc.perform(get("/dogs")109                .contentType(MediaType.APPLICATION_JSON))110                .andExpect(status().isOk)111                .andReturn()112                .response113                .contentAsString114        val returnedDogs = jacksonObjectMapper().registerModule(JavaTimeModule()).readValue<List<DogDTO>>(response)115        //then116        returnedDogs.size shouldBe 2117        returnedDogs.map { it.name } shouldContain dogName118    }119    @Test120    fun `Should remove dog`() {121        //given122        val dogId = DogData.yogi.id123        //when124        mockMvc.perform(delete("/dogs/$dogId")125                .contentType(MediaType.APPLICATION_JSON))126                //then127                .andExpect(status().isNoContent)128        //when129        val response = mockMvc.perform(get("/dogs")130                .contentType(MediaType.APPLICATION_JSON))131                //then132                .andExpect(status().isOk)133                .andReturn()134                .response135                .contentAsString136        val returnedDogs = jacksonObjectMapper().registerModule(JavaTimeModule()).readValue<List<DogDTO>>(response)137        returnedDogs.size shouldBe 1138        returnedDogs.map { it.id } shouldNotContain dogId139    }140    @Test141    fun `Should save and get dog avatar image`() {142        //given143        val dog = DogData.yogi144        val dogId = dog.id145        val avatarMultipartFile = DogAvatarImageData.avatarMultipartFile146        //when147        mockMvc.multipart("/dogs/$dogId/avatar") {148            file(avatarMultipartFile)149            with {150                it.apply { method = "PUT" }151            }152        }153                //then154                .andExpect {155                    status { isOk }156                }157        //when158        val response = mockMvc.get("/dogs/$dogId/avatar")159                //then160                .andExpect {161                    status { isOk }162                }163                .andReturn()164                .response165                .contentAsByteArray166        response contentEquals DogAvatarImageData.avatarBytes shouldBe true167    }168    @Test169    fun `Should throw when adding invalid dog avatar image`() {170        //given171        val dog = DogData.yogi172        val dogId = dog.id173        val invalidAvatarMultipartFile = DogAvatarImageData.invalidAvatarMultipartFile174        //when175        mockMvc.multipart("/dogs/$dogId/avatar") {176            file(invalidAvatarMultipartFile)177            with {178                it.apply { method = "PUT" }179            }180        }181                //then182                .andExpect {183                    status {184                        isBadRequest185                        reason(InvalidAvatarImageException().message)186                    }187                }188    }189}...

Full Screen

Full Screen

RiotServiceTests.kt

Source:RiotServiceTests.kt Github

copy

Full Screen

1package me.l3n.bot.discord.lod.service.http2import io.kotest.assertions.fail3import io.kotest.core.spec.style.ShouldSpec4import io.kotest.matchers.collections.*5import io.kotest.matchers.shouldBe6import io.kotest.matchers.string.shouldNotContain7import io.mockk.coEvery8import io.mockk.mockk9import me.l3n.bot.discord.lod.model.RiotConfig10import me.l3n.bot.discord.lod.model.Role11import me.l3n.bot.discord.lod.models.Champs12import me.l3n.bot.discord.lod.models.Champs.currentRotationIds13import me.l3n.bot.discord.lod.toJson14import kotlin.time.ExperimentalTime15private const val LATEST_VERSION = "1.3.3.7"16private val VERSIONS = listOf(LATEST_VERSION, "1.0", "0.1")17@ExperimentalTime18class RiotServiceTests : ShouldSpec({19    val httpResponseMock = mockk<MockableHttpHandler> {20        coEvery { responseFor("$LEAGUE_DATA_URL/$VERSIONS_ENDPOINT", any()) } returns VERSIONS.toJson()21        coEvery {22            responseFor(23                "$LEAGUE_DATA_URL/$CDN_ENDPOINT/$LATEST_VERSION/$GET_ALL_CHAMPIONS_ENDPOINT",24                any(),25            )26        } returns ChampionListResponse(Champs.noIconsList).toJson()27        coEvery {28            responseFor(29                "$LEAGUE_URL/$GET_CURRENT_ROTATION_ENDPOINT",30                any(),31            )32        } returns ChampionRotationResponse(currentRotationIds, currentRotationIds).toJson()33        Champs.withIconsList.values.forEach { champ ->34            val icon = champ.icon ?: fail("Icon of `${champ.id}` should not be null")35            coEvery {36                responseFor(37                    "$LEAGUE_DATA_URL/cdn/$LATEST_VERSION/$GET_CHAMPION_ICON/${champ.id}.png",38                    any()39                )40            } returns icon.toByteArray()41        }42    }43    val httpClient = MockableHttpHandler.createClient(httpResponseMock)44    context("internal API") {45        val target = RiotServiceImpl(RiotConfig("dummy"), httpClient)46        should("remove spaces from champion names") {47            target.trimChampionsName(Champs.noIconsList).values.forEach { champ ->48                champ.name shouldNotContain " "49            }50        }51        should("filter champions from the rotation list") {52            val filtered =53                target.filterChampionsOnRotation(Champs.noIconsList, Champs.currentRotationIds)54            filtered shouldBe Champs.currentRotation55        }56        should("give all roles with champions") {57            val actual = target.getRoleChampions(Champs.allRolesFilled, Champs.noIconsList)58            actual.keys shouldContain Role.Unknown59            actual.keys shouldContainInOrder listOf(60                Role.Top,61                Role.Jungle,62                Role.Mid,63                Role.Bot,64                Role.Support,65                Role.Unknown66            )67            actual shouldBe mapOf(68                Role.Top to listOf(Champs.NoIcon.lulu),69                Role.Jungle to listOf(Champs.NoIcon.nunu),70                Role.Mid to listOf(Champs.NoIcon.syndra),71                Role.Bot to listOf(Champs.NoIcon.draven),72                Role.Support to listOf(Champs.NoIcon.nami),73                Role.Unknown to listOf(Champs.NoIcon.knox),74            )75        }76        should("give roles with champions, without `Unknown` because there's none") {77            val actual = target.getRoleChampions(Champs.rolesFilledWithoutUnknown, Champs.noIconsList)78            actual.keys shouldNotContain Role.Unknown79            actual.keys shouldContainInOrder listOf(Role.Top, Role.Jungle, Role.Mid, Role.Bot, Role.Support)80            actual shouldBe mapOf(81                Role.Top to listOf(Champs.NoIcon.lulu),82                Role.Jungle to listOf(Champs.NoIcon.nunu),83                Role.Mid to listOf(Champs.NoIcon.syndra),84                Role.Bot to listOf(Champs.NoIcon.draven),85                Role.Support to listOf(Champs.NoIcon.nami, Champs.NoIcon.knox),86            )87        }88        should("give some roles with champions, including `Unknown`") {89            val actual = target.getRoleChampions(Champs.someRolesFilled, Champs.noIconsList)90            actual.keys shouldContain Role.Unknown91            actual.keys shouldContainInOrder listOf(Role.Mid, Role.Bot, Role.Support, Role.Unknown)92            actual shouldBe mapOf(93                Role.Top to listOf(),94                Role.Jungle to listOf(),95                Role.Mid to listOf(Champs.NoIcon.syndra),96                Role.Bot to listOf(Champs.NoIcon.draven, Champs.NoIcon.lulu),97                Role.Support to listOf(Champs.NoIcon.nami, Champs.NoIcon.nunu),98                Role.Unknown to listOf(Champs.NoIcon.knox),99            )100        }101        should("give some roles with champions, without `Unknown` because there's none") {102            val actual =103                target.getRoleChampions(Champs.someRolesFilledWithoutUnknown, Champs.noIconsList)104            actual.keys shouldNotContain Role.Unknown105            actual.keys shouldContainInOrder listOf(Role.Mid, Role.Bot, Role.Support)106            actual shouldBe mapOf(107                Role.Top to listOf(),108                Role.Jungle to listOf(),109                Role.Mid to listOf(Champs.NoIcon.syndra, Champs.NoIcon.knox),110                Role.Bot to listOf(Champs.NoIcon.draven, Champs.NoIcon.lulu),111                Role.Support to listOf(Champs.NoIcon.nami, Champs.NoIcon.nunu),112            )113        }114        context("using HTTP services") {115            should("fetch the latest version in initialization") {116                target.getLatestVersion() shouldBe LATEST_VERSION117            }118            should("get all champions") {119                target.getAllChampions() shouldBe Champs.noIconsList120            }121            should("get champion icon") {122                val case = Champs.WithIcon.draven123                val icon = case.icon ?: fail("`case.icon` must not be null")124                val actual = target.getChampionIcon(case.id)125                actual.shouldContainAll(*icon.toTypedArray())126            }127            should("get champions with icons") {128                val actual = target.addIconsToChampions(Champs.noIconsList)129                actual.keys shouldBe Champs.withIconsList.keys130                actual.values shouldBe Champs.withIconsList.values131            }132        }133    }134    context("public API") {135        should("return rotation champions with their icons") {136            val target = RiotServiceImpl(RiotConfig("dummy"), httpClient)137            val currentRotation = target.getCurrentRotation(Champs.allRolesFilled)138            val champs = currentRotation.roledChampions139            champs.keys.size shouldBe 5140            champs.filterValues { it.isEmpty() }.keys shouldContainExactly listOf(Role.Jungle, Role.Mid, Role.Support)141            champs[Role.Bot]?.shouldHaveSingleElement(Champs.WithIcon.draven)142            champs[Role.Top]?.shouldHaveSingleElement(Champs.WithIcon.lulu)143        }144    }145})...

Full Screen

Full Screen

TestOutputCapture.kt

Source:TestOutputCapture.kt Github

copy

Full Screen

1package edu.illinois.cs.cs125.jeed.core.sandbox2import edu.illinois.cs.cs125.jeed.core.Sandbox3import edu.illinois.cs.cs125.jeed.core.Source4import edu.illinois.cs.cs125.jeed.core.SourceExecutionArguments5import edu.illinois.cs.cs125.jeed.core.compile6import edu.illinois.cs.cs125.jeed.core.execute7import edu.illinois.cs.cs125.jeed.core.findClassMethod8import edu.illinois.cs.cs125.jeed.core.fromSnippet9import edu.illinois.cs.cs125.jeed.core.haveCompleted10import edu.illinois.cs.cs125.jeed.core.haveOutput11import edu.illinois.cs.cs125.jeed.core.haveStderr12import edu.illinois.cs.cs125.jeed.core.haveStdout13import edu.illinois.cs.cs125.jeed.core.haveTimedOut14import io.kotest.core.spec.style.StringSpec15import io.kotest.matchers.collections.shouldNotContain16import io.kotest.matchers.should17import io.kotest.matchers.shouldBe18import io.kotest.matchers.shouldNot19import kotlinx.coroutines.async20import kotlinx.coroutines.delay21import java.io.ByteArrayOutputStream22import java.io.PrintStream23class TestOutputCapture : StringSpec({24    "should capture stdout" {25        val executionResult = Source.fromSnippet(26            """27System.out.println("Here");28            """.trim()29        ).compile().execute()30        executionResult should haveCompleted()31        executionResult shouldNot haveTimedOut()32        executionResult should haveStdout("Here")33        executionResult should haveStderr("")34    }35    "should capture stderr" {36        val executionResult = Source.fromSnippet(37            """38System.err.println("Here");39            """.trim()40        ).compile().execute()41        executionResult should haveCompleted()42        executionResult shouldNot haveTimedOut()43        executionResult should haveStdout("")44        executionResult should haveStderr("Here")45    }46    "should capture stderr and stdout" {47        val executionResult = Source.fromSnippet(48            """49System.out.println("Here");50System.err.println("There");51            """.trim()52        ).compile().execute()53        executionResult should haveCompleted()54        executionResult shouldNot haveTimedOut()55        executionResult should haveStdout("Here")56        executionResult should haveStderr("There")57        executionResult should haveOutput("Here\nThere")58    }59    "should capture incomplete stderr and stdout lines" {60        val executionResult = Source.fromSnippet(61            """62System.out.print("Here");63System.err.print("There");64            """.trim()65        ).compile().execute()66        executionResult should haveCompleted()67        executionResult shouldNot haveTimedOut()68        executionResult should haveStdout("Here")69        executionResult should haveStderr("There")70        executionResult should haveOutput("Here\nThere")71    }72    "should not intermingle unrelated thread output" {73        val combinedOutputStream = ByteArrayOutputStream()74        val combinedPrintStream = PrintStream(combinedOutputStream)75        val originalStdout = System.out76        val originalStderr = System.err77        System.setOut(combinedPrintStream)78        System.setErr(combinedPrintStream)79        (0..8).toList().map {80            if (it % 2 == 0) {81                async {82                    Source.fromSnippet(83                        """84for (int i = 0; i < 32; i++) {85    for (long j = 0; j < 1024 * 1024 * 1024; j++);86}87                        """.trim()88                    ).compile().execute(SourceExecutionArguments(timeout = 1000L))89                }90            } else {91                async {92                    repeat(512) {93                        println("Bad")94                        System.err.println("Bad")95                        delay(1L)96                    }97                }98            }99        }.map { it.await() }.filterIsInstance<Sandbox.TaskResults<out Any?>>().forEach { executionResult ->100            executionResult should haveTimedOut()101            executionResult.outputLines.map { it.line } shouldNotContain "Bad"102            executionResult.stderrLines.map { it.line } shouldNotContain "Bad"103        }104        System.setOut(originalStdout)105        System.setErr(originalStderr)106        val unrelatedOutput = combinedOutputStream.toString()107        unrelatedOutput.lines().filter { it == "Bad" }.size shouldBe (4 * 2 * 512)108    }109    "should redirect output to trusted task properly" {110        val compiledSource = Source.fromSnippet(111            """112System.out.println("Here");113System.out.println("There");114System.err.println("There");115            """.trim()116        ).compile()117        val executionResult = Sandbox.execute(compiledSource.classLoader) { (classLoader, redirectOutput) ->118            redirectOutput {119                classLoader.findClassMethod().invoke(null)120            }.also {121                assert(it.stdout == "Here\nThere\n")122                assert(it.stderr == "There\n")123            }124        }125        executionResult should haveCompleted()126        executionResult shouldNot haveTimedOut()127        executionResult should haveStdout("Here\nThere")128        executionResult should haveStderr("There")129    }130    "should redirect output to trusted task properly with print" {131        val compiledSource = Source.fromSnippet(132            """133System.out.println("Here");134System.out.print("There");135System.err.print("There");136            """.trim()137        ).compile()138        val executionResult = Sandbox.execute(compiledSource.classLoader) { (classLoader, redirectOutput) ->139            redirectOutput {140                classLoader.findClassMethod().invoke(null)141            }.also {142                assert(it.stdout == "Here\nThere")143                assert(it.stderr == "There")144            }145            redirectOutput {146                classLoader.findClassMethod().invoke(null)147            }.also {148                assert(it.stdout == "Here\nThere")149                assert(it.stderr == "There")150            }151        }152        executionResult should haveCompleted()153        executionResult shouldNot haveTimedOut()154        executionResult should haveStdout("Here\nThereHere\nThere")155        executionResult should haveStderr("ThereThere")156    }157    "should handle null print arguments" {158        val executionResult = Source.fromSnippet(159            """160int[] output = null;161System.out.println(output);162            """.trim()163        ).compile().execute()164        executionResult should haveCompleted()165        executionResult shouldNot haveTimedOut()166        executionResult should haveStdout("null")167        executionResult should haveStderr("")168    }169    "should handle print without newline" {170        val executionResult = Source.fromSnippet(171            """172System.out.print("Hello");173            """.trim()174        ).compile().execute()175        executionResult should haveCompleted()176        executionResult shouldNot haveTimedOut()177        executionResult should haveStdout("Hello")178    }179})...

Full Screen

Full Screen

FileSystemServiceImplTest.kt

Source:FileSystemServiceImplTest.kt Github

copy

Full Screen

1package org.factcast.schema.registry.cli.fs2import com.fasterxml.jackson.databind.JsonNode3import io.kotest.core.spec.style.StringSpec4import io.kotest.core.test.TestCase5import io.kotest.core.test.TestResult6import io.kotest.matchers.collections.shouldContain7import io.kotest.matchers.collections.shouldHaveSize8import io.kotest.matchers.shouldBe9import io.kotest.matchers.string.shouldContain10import io.kotest.matchers.string.shouldNotContain11import io.kotest.matchers.types.shouldBeInstanceOf12import org.factcast.schema.registry.cli.fixture13import java.nio.file.Files14import java.nio.file.Paths15class FileSystemServiceImplTest : StringSpec() {16    var tmp = Files.createTempDirectory("fc-test")17    val uut = FileSystemServiceImpl()18    override fun afterTest(testCase: TestCase, result: TestResult) {19        try {20            Files.delete(tmp)21        } catch (e: Exception) {22        } finally {23            tmp = Files.createTempDirectory("fx-test")24        }25    }26    init {27        "exists" {28            uut.exists(fixture("schema.json")) shouldBe true29            uut.exists(fixture("nope.json")) shouldBe false30        }31        "listDirectories" {32            uut.listDirectories(fixture("")) shouldContain fixture("sample-folder")33            uut.listDirectories(fixture("sample-folder")) shouldHaveSize 034        }35        "listFiles" {36            val files = uut.listFiles(fixture(""))37            files shouldHaveSize 138            files shouldContain fixture("schema.json")39        }40        "ensureDirectories" {41            val outputPath = Paths.get(tmp.toString(), "foo")42            uut.ensureDirectories(outputPath)43            uut.exists(outputPath) shouldBe true44        }45        "writeToFile" {46            val outputPath = Paths.get(tmp.toString(), "test.txt")47            uut.writeToFile(outputPath.toFile(), "bar")48            uut.exists(outputPath) shouldBe true49        }50        "readToString" {51            uut.readToString(fixture("schema.json").toFile()) shouldContain "firstName"52        }53        "readToStrings" {54            val output = uut.readToStrings(fixture("schema.json").toFile())55            output[1] shouldContain "additionalProperties"56            output[8] shouldContain "required"57        }58        "copyFile" {59            val outputPath = Paths.get(tmp.toString(), "schema.json")60            uut.copyFile(fixture("schema.json").toFile(), outputPath.toFile())61            uut.exists(outputPath)62        }63        "readToJsonNode" {64            uut.readToJsonNode(fixture("schema.json")).shouldBeInstanceOf<JsonNode>()65            uut.readToJsonNode(fixture("nope.json")) shouldBe null66        }67        "deleteDirectory" {68            uut.exists(tmp) shouldBe true69            uut.deleteDirectory(tmp)70            uut.exists(tmp) shouldBe false71        }72        "readToBytes" {73            val exampleFile = fixture("schema.json")74            uut.readToBytes(exampleFile) shouldBe uut.readToString(exampleFile.toFile()).toByteArray()75        }76        "copyDirectory" {77            val outputPath = Paths.get(tmp.toString(), "foo")78            uut.exists(outputPath) shouldBe false79            uut.copyDirectory(fixture(""), outputPath)80            uut.exists(outputPath) shouldBe true81        }82        "copyFilteredJson" {83            val outputPath = Paths.get(tmp.toString(), "test.txt")84            uut.copyFilteredJson(85                fixture("schema.json").toFile(),86                outputPath.toFile(),87                setOf("title")88            )89            uut.exists(outputPath) shouldBe true90            uut.readToString(outputPath.toFile()) shouldNotContain "title"91        }92    }93}...

Full Screen

Full Screen

contain.kt

Source:contain.kt Github

copy

Full Screen

1package io.kotest.matchers.collections2import io.kotest.assertions.print.print3import io.kotest.equals.Equality4import io.kotest.matchers.Matcher5import io.kotest.matchers.MatcherResult6import io.kotest.matchers.should7import io.kotest.matchers.shouldNot8// Infix9infix fun <T> Iterable<T>.shouldNotContain(t: T): Iterable<T> = shouldNotContain(t, Equality.default())10infix fun <T> Array<T>.shouldNotContain(t: T): Array<T> = shouldNotContain(t, Equality.default())11infix fun <T> Iterable<T>.shouldContain(t: T): Iterable<T> = shouldContain(t, Equality.default())12infix fun <T> Array<T>.shouldContain(t: T): Array<T> = shouldContain(t, Equality.default())13// Should not14fun <T> Iterable<T>.shouldNotContain(t: T, comparator: Equality<T>): Iterable<T> = apply {15   toList() shouldNot contain(t, comparator)16}17fun <T> Array<T>.shouldNotContain(t: T, comparator: Equality<T>): Array<T> = apply {18   asList().shouldNotContain(t, comparator)19}20// Should21fun <T> Iterable<T>.shouldContain(t: T, comparator: Equality<T>): Iterable<T> = apply {22   toList() should contain(t, comparator)23}24fun <T> Array<T>.shouldContain(t: T, comparator: Equality<T>): Array<T> = apply {25   asList().shouldContain(t, comparator)26}27// Matcher28fun <T, C : Collection<T>> contain(t: T, verifier: Equality<T> = Equality.default()) = object : Matcher<C> {29   override fun test(value: C) = MatcherResult(30      value.any { verifier.verify(it, t).areEqual() },31      {32         "Collection should contain element ${t.print().value} based on ${verifier.name()}; " +33            "but the collection is ${value.print().value}"34      },35      { "Collection should not contain element ${t.print().value} based on ${verifier.name()}" }36   )37}...

Full Screen

Full Screen

_001_FindMultInArrayTest.kt

Source:_001_FindMultInArrayTest.kt Github

copy

Full Screen

...18            it shouldBeLessThan array.size19            it shouldBeGreaterThanOrEqual 020        }21        val resultArray = _001_FindMultInArray.findMult(array)22        resultArray shouldNotContain 123        resultArray shouldContain 224        resultArray shouldHaveSize 325        val testList: List<Int> = listOf(2, 3, 5)26        resultArray shouldContainAll testList27    }28    @Test29    fun findMultTestContainNull() {30        val array = listOf(0, 1, 2, 3, 4, 5, 6, 7, 8).toIntArray()31        array.forEach {32            it shouldBeLessThan array.size33            it shouldBeGreaterThanOrEqual 034        }35        _001_FindMultInArray.findMult(array) shouldHaveSize 036    }...

Full Screen

Full Screen

Array.shouldNotContain

Using AI Code Generation

copy

Full Screen

1val list = listOf ( "A" , "B" , "C" , "D" ) list . shouldNotContain ( "E" )2val list = listOf ( "A" , "B" , "C" , "D" ) list . shouldNotContain ( "A" , "B" )3val list = listOf ( "A" , "B" , "C" , "D" ) list . shouldNotContain ( "A" , "B" , "C" , "D" )4val list = listOf ( "A" , "B" , "C" , "D" ) list . shouldNotContain ( "A" , "B" , "C" , "D" , "E" )5val list = listOf ( "A" , "B" , "C" , "D" ) list . shouldNotContain ( "E" , "F" , "G" , "H" )6val list = listOf ( "A" , "B" , "C" , "D" ) list . shouldNotContain ( "E" , "F" , "G" , "H" , "I" )7val list = listOf ( "A" , "B" , "C" , "D" ) list . shouldNotContain ( "E" , "F" , "G" , "H" , "I" , "J" )8val list = listOf ( "A" , "B" , "C" , "D" ) list . shouldNotContain ( "E" , "F" , "G" , "H" , "I" , "J" , "K"

Full Screen

Full Screen

Array.shouldNotContain

Using AI Code Generation

copy

Full Screen

1val list = listOf("Kotlin", "Java", "C++", "C", "C#")2list.shouldNotContain("C++")3val list = listOf("Kotlin", "Java", "C++", "C", "C#")4list.shouldContainAll("C++", "Java")5val list = listOf("Kotlin", "Java", "C++", "C", "C#")6list.shouldNotContainAll("C++", "Java")7val list = listOf("Kotlin", "Java", "C++", "C", "C#")8list.shouldContainAny("C++", "Java")9val list = listOf("Kotlin", "Java", "C++", "C", "C#")10list.shouldNotContainAny("C++", "Java")11val list = listOf("Kotlin", "Java", "C++", "C", "C#")12list.shouldContainNone("C++", "Java")13val list = listOf("Kotlin", "Java", "C++", "C", "C#")14list.shouldNotContainNone("C++", "Java")15val list = listOf("Kotlin", "Java", "C++", "C", "C#")16list.shouldContainExactly("C++", "Java")17val list = listOf("Kotlin", "Java", "C++", "C", "C#")18list.shouldNotContainExactly("C++", "Java")19val list = listOf("Kotlin", "Java",

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run Kotest automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful