aboutsummaryrefslogtreecommitdiff
path: root/src/test/scala/ParserTest.scala
blob: 579ba959cdf5abed48ebbb7e9a0f1991d09f11f9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package commando

import utest._

object ParserTest extends TestSuite {

  implicit class EliteCommando(line: String) {
    def parse(command: Command): Unit = {
      val args = line.split(" ").tail
      commando.parse(args, command, (c, err) => throw new ParseException(err))
    }
    def fail(command: Command, message: String): Unit = {
      val args = line.split(" ").tail
      try {
        commando.parse(args, command, (c, err) => throw new ParseException(err))
        sys.error("parsing succeeded but was expected to fail")
      } catch {
        case err: ParseException if err.getMessage.contains(message) =>
        case err: ParseException =>
          sys.error(s"parsing failed for the wrong reason: ${err.getMessage}")
      }
    }
  }

  def cbx(asserts: Command.Arguments => Unit) =
    cmd("cbx")(
      opt("server", 's', "name" -> true)
    ).sub(
      cmd("version")(
        opt("verbose", 'v', "k=v" -> false)
      ).run(asserts),
      cmd("login")(
        pos("server_url"),
        pos("username", false),
        pos("password", false)
      ).run(asserts),
      cmd("run")(
        opt("file", 'f', "file_name" -> true),
        opt("force"),
        pos("pipeline", false)
      ).run(asserts),
      cmd("level1")().sub(
        cmd("level2-1")(
          pos("p2")
        ).sub(
          cmd("level3")(pos("p3")).run(asserts)
        ),
        cmd("level2-2")().run(asserts)
      )
    )

  val tests = Tests {
    "print usage" - {
      cbx(_ => ()).usage
    }
    "simple" - {
      "cbx version" parse cbx { args =>
        args ==> Map.empty
      }
    }
    "empty allowed optional" - {
      "cbx version -v" parse cbx { args =>
        args ==> Map("verbose" -> Seq(""))
      }
      "cbx version --verbose" parse cbx { args =>
        args ==> Map("verbose" -> Seq(""))
      }
    }
    "set allowed optional" - {
      "cbx version -v x" parse cbx { args =>
        args ==> Map("verbose" -> Seq("x"))
      }
      "cbx version --verbose x" parse cbx { args =>
        args ==> Map("verbose" -> Seq("x"))
      }
      "cbx version --verbose=x" parse cbx { args =>
        args ==> Map("verbose" -> Seq("x"))
      }
      "cbx version --verbose=x=y" parse cbx { args =>
        args ==> Map("verbose" -> Seq("x=y"))
      }
      "cbx version --verbose=x=y,z=w" parse cbx { args =>
        args ==> Map("verbose" -> Seq("x=y,z=w"))
      }
      "cbx version --verbose x=y" parse cbx { args =>
        args ==> Map("verbose" -> Seq("x=y"))
      }
      "cbx version --verbose x=y z=w".fail(cbx(_ => ()), "too many arguments")
    }
    "required argument optional" - {
      "cbx run" parse cbx { _ ==> Map.empty } // make sure it works first
      "cbx run -f x" parse cbx { _ ==> Map("file" -> Seq("x")) }
      "cbx run --file x" parse cbx { _ ==> Map("file" -> Seq("x")) }
      "cbx run --file=x" parse cbx { _ ==> Map("file" -> Seq("x")) }
      "cbx run --file=x=y,z=w" parse cbx { _ ==> Map("file" -> Seq("x=y,z=w")) }
      "cbx run --file".fail(cbx(_ => ()), "requires")
      "cbx run --file --".fail(cbx(_ => ()), "requires")
    }
    "no argument optional" - {
      "cbx run --force=x".fail(cbx(_ => ()), "no argument allowed")
      "cbx run --force x" parse cbx { _ ==> Map("force" -> Seq(""), "pipeline" -> Seq("x")) }
    }
    "global optional" - {
      "cbx --server run run" parse cbx {_ ==> Map("server" -> Seq("run"))}
      "cbx -s run run" parse cbx {_ ==> Map("server" -> Seq("run"))}
      "cbx --server=run run" parse cbx {_ ==> Map("server" -> Seq("run"))}
      "cbx -x run".fail(cbx(_ => ()), "unknown option")
      "cbx --x run".fail(cbx(_ => ()), "unknown option")
    }
    "positional" - {
      "cbx login x" parse cbx { _ ==> Map("server_url" -> Seq("x"))}
      "cbx login x y" parse cbx { _ ==> Map("server_url" -> Seq("x"), "username" -> Seq("y"))}
      "cbx login x y z" parse cbx { _ ==> Map("server_url" -> Seq("x"), "username" -> Seq("y"), "password" -> Seq("z"))}
      "cbx login - x y z".fail(cbx(_ => ()), "too many")
      "cbx login - y" parse cbx { _ ==> Map("server_url" -> Seq("-"), "username" -> Seq("y"))}
    }
    "out of order options" - {
      "cbx run --force pipelinename -f x" parse cbx {
        _ ==> Map("force" -> Seq(""), "pipeline" -> Seq("pipelinename"), "file" -> Seq("x"))
      }
      "cbx run --force -- -f" parse cbx {
        _ ==> Map("force" -> Seq(""), "pipeline" -> Seq("-f"))
      }
      "cbx run --force -- --file" parse cbx {
        _ ==> Map("force" -> Seq(""), "pipeline" -> Seq("--file"))
      }
      "cbx run --force -- --" parse cbx {
        _ ==> Map("force" -> Seq(""), "pipeline" -> Seq("--"))
      }
      "cbx run --force -- -f x".fail(cbx(_ => ()), "too many")
    }
    "nested1" - {
      "cbx level1 level2-1 x=y level3 z" parse cbx {
        _ ==> Map("p2" -> Seq("x=y"), "p3" -> Seq("z"))
      }
    }
    "nested2" - {
      "cbx level1 level2-2 --" parse cbx {
        _ ==> Map.empty
      }
    }
  }
}