parser_test.go 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. package parser
  2. import (
  3. "os"
  4. "testing"
  5. "github.com/stretchr/testify/assert"
  6. "github.com/stretchr/testify/require"
  7. )
  8. func TestOption_Add(t *testing.T) {
  9. t.Parallel()
  10. type fields struct {
  11. Args []string
  12. }
  13. type args struct {
  14. arg string
  15. }
  16. tests := []struct {
  17. name string
  18. fields fields
  19. args args
  20. want []string
  21. }{
  22. {name: "simple add", fields: fields{
  23. Args: []string{"a", "b"},
  24. }, args: args{
  25. arg: "c",
  26. }, want: []string{"a", "b", "c"}},
  27. {name: "null add", fields: fields{
  28. Args: nil,
  29. }, args: args{
  30. arg: "c",
  31. }, want: []string{"c"}},
  32. }
  33. for _, tt := range tests {
  34. tt := tt
  35. t.Run(tt.name, func(t *testing.T) {
  36. t.Parallel()
  37. o := &Option{
  38. Args: tt.fields.Args,
  39. }
  40. o.Add(tt.args.arg)
  41. assert.ElementsMatch(t, tt.want, o.Args)
  42. })
  43. }
  44. }
  45. func TestOption_Set(t *testing.T) {
  46. t.Parallel()
  47. type fields struct {
  48. Args []string
  49. }
  50. type args struct {
  51. arg string
  52. }
  53. tests := []struct {
  54. name string
  55. fields fields
  56. args args
  57. want []string
  58. }{
  59. {name: "simple set", fields: fields{
  60. Args: []string{"a", "b"},
  61. }, args: args{
  62. arg: "c",
  63. }, want: []string{"c"}},
  64. {name: "null set", fields: fields{
  65. Args: nil,
  66. }, args: args{
  67. arg: "c",
  68. }, want: []string{"c"}},
  69. }
  70. for _, tt := range tests {
  71. tt := tt
  72. t.Run(tt.name, func(t *testing.T) {
  73. t.Parallel()
  74. o := &Option{
  75. Args: tt.fields.Args,
  76. }
  77. o.Set(tt.args.arg)
  78. assert.ElementsMatch(t, tt.want, o.Args)
  79. })
  80. }
  81. }
  82. func TestOption_First(t *testing.T) {
  83. t.Parallel()
  84. type fields struct {
  85. Args []string
  86. }
  87. tests := []struct {
  88. name string
  89. fields fields
  90. want string
  91. }{
  92. {name: "simple first", fields: fields{
  93. Args: []string{"a", "b"},
  94. }, want: "a"},
  95. {name: "null first", fields: fields{
  96. Args: nil,
  97. }, want: ""},
  98. }
  99. for _, tt := range tests {
  100. tt := tt
  101. t.Run(tt.name, func(t *testing.T) {
  102. t.Parallel()
  103. o := &Option{
  104. Args: tt.fields.Args,
  105. }
  106. assert.Equal(t, tt.want, o.First())
  107. })
  108. }
  109. }
  110. func TestMakeArguments(t *testing.T) {
  111. t.Parallel()
  112. args := MakeArguments()
  113. assert.NotNil(t, args)
  114. assert.Equal(t, "", args.Op)
  115. assert.Empty(t, args.Options)
  116. assert.Empty(t, args.Targets)
  117. }
  118. func TestArguments_CopyGlobal(t *testing.T) {
  119. t.Parallel()
  120. type fields struct {
  121. Op string
  122. Options map[string]*Option
  123. Targets []string
  124. }
  125. tests := []struct {
  126. name string
  127. fields fields
  128. want *Arguments
  129. }{
  130. {name: "simple", fields: fields{
  131. Op: "Q",
  132. Options: map[string]*Option{
  133. "a": {}, "arch": {
  134. Global: true,
  135. Args: []string{"x86_x64"},
  136. }, "boo": {Global: true, Args: []string{"a", "b"}},
  137. },
  138. Targets: []string{"a", "b"},
  139. }, want: &Arguments{
  140. Op: "",
  141. Options: map[string]*Option{
  142. "arch": {
  143. Global: true,
  144. Args: []string{"x86_x64"},
  145. }, "boo": {Global: true, Args: []string{"a", "b"}},
  146. },
  147. Targets: []string{},
  148. }},
  149. }
  150. for _, tt := range tests {
  151. tt := tt
  152. t.Run(tt.name, func(t *testing.T) {
  153. t.Parallel()
  154. cmdArgs := &Arguments{
  155. Op: tt.fields.Op,
  156. Options: tt.fields.Options,
  157. Targets: tt.fields.Targets,
  158. }
  159. got := cmdArgs.CopyGlobal()
  160. assert.NotEqualValues(t, tt.fields.Options, got.Options)
  161. assert.NotEqualValues(t, tt.fields.Targets, got.Targets)
  162. assert.NotEqual(t, tt.fields.Op, got.Op)
  163. assert.Equal(t, tt.want, got)
  164. })
  165. }
  166. }
  167. func TestArguments_Copy(t *testing.T) {
  168. t.Parallel()
  169. type fields struct {
  170. Op string
  171. Options map[string]*Option
  172. Targets []string
  173. }
  174. tests := []struct {
  175. name string
  176. fields fields
  177. want *Arguments
  178. }{
  179. {name: "simple", fields: fields{
  180. Op: "Q",
  181. Options: map[string]*Option{
  182. "a": {}, "arch": {
  183. Args: []string{"x86_x64"}, Global: true,
  184. }, "boo": {Args: []string{"a", "b"}, Global: true},
  185. },
  186. Targets: []string{"a", "b"},
  187. }, want: &Arguments{
  188. Op: "Q",
  189. Options: map[string]*Option{
  190. "a": {}, "arch": {
  191. Global: true,
  192. Args: []string{"x86_x64"},
  193. }, "boo": {Args: []string{"a", "b"}, Global: true},
  194. },
  195. Targets: []string{"a", "b"},
  196. }},
  197. }
  198. for _, tt := range tests {
  199. tt := tt
  200. t.Run(tt.name, func(t *testing.T) {
  201. t.Parallel()
  202. cmdArgs := &Arguments{
  203. Op: tt.fields.Op,
  204. Options: tt.fields.Options,
  205. Targets: tt.fields.Targets,
  206. }
  207. got := cmdArgs.Copy()
  208. assert.Equal(t, cmdArgs, got)
  209. assert.Equal(t, tt.want, got)
  210. })
  211. }
  212. }
  213. func TestArguments_DelArg(t *testing.T) {
  214. t.Parallel()
  215. args := MakeArguments()
  216. args.addParam("arch", "arg")
  217. args.addParam("ask", "arg")
  218. args.DelArg("arch", "ask")
  219. assert.Empty(t, args.Options)
  220. }
  221. func TestArguments_FormatArgs(t *testing.T) {
  222. t.Parallel()
  223. type fields struct {
  224. Op string
  225. Options map[string]*Option
  226. Targets []string
  227. }
  228. tests := []struct {
  229. name string
  230. fields fields
  231. wantArgs []string
  232. }{
  233. {name: "simple", fields: fields{
  234. Op: "S",
  235. Options: map[string]*Option{},
  236. Targets: []string{"yay", "yay-bin", "yay-git"},
  237. }, wantArgs: []string{"-S"}},
  238. {name: "only global", fields: fields{
  239. Op: "Y",
  240. Options: map[string]*Option{"noconfirm": {Global: true, Args: []string{""}}},
  241. Targets: []string{"yay", "yay-bin", "yay-git"},
  242. }, wantArgs: []string{"-Y"}},
  243. {name: "options single", fields: fields{
  244. Op: "Y",
  245. Options: map[string]*Option{"overwrite": {Args: []string{"/tmp/a"}}, "useask": {Args: []string{""}}},
  246. Targets: []string{},
  247. }, wantArgs: []string{"-Y", "--overwrite", "/tmp/a", "--useask"}},
  248. {name: "options doubles", fields: fields{
  249. Op: "Y",
  250. Options: map[string]*Option{"overwrite": {Args: []string{"/tmp/a", "/tmp/b", "/tmp/c"}}, "needed": {Args: []string{""}}},
  251. Targets: []string{},
  252. }, wantArgs: []string{"-Y", "--overwrite", "/tmp/a", "--overwrite", "/tmp/b", "--overwrite", "/tmp/c", "--needed"}},
  253. }
  254. for _, tt := range tests {
  255. tt := tt
  256. t.Run(tt.name, func(t *testing.T) {
  257. t.Parallel()
  258. cmdArgs := &Arguments{
  259. Op: tt.fields.Op,
  260. Options: tt.fields.Options,
  261. Targets: tt.fields.Targets,
  262. }
  263. gotArgs := cmdArgs.FormatArgs()
  264. assert.ElementsMatch(t, gotArgs, tt.wantArgs)
  265. })
  266. }
  267. }
  268. func TestArguments_FormatGlobalArgs(t *testing.T) {
  269. t.Parallel()
  270. type fields struct {
  271. Op string
  272. Options map[string]*Option
  273. Targets []string
  274. }
  275. tests := []struct {
  276. name string
  277. fields fields
  278. wantArgs []string
  279. }{
  280. {name: "simple", fields: fields{
  281. Op: "S",
  282. Options: map[string]*Option{"dbpath": {Global: true, Args: []string{"/tmp/a", "/tmp/b"}}},
  283. Targets: []string{"yay", "yay-bin", "yay-git"},
  284. }, wantArgs: []string{"--dbpath", "/tmp/a", "--dbpath", "/tmp/b"}},
  285. {name: "only global", fields: fields{
  286. Op: "Y",
  287. Options: map[string]*Option{"noconfirm": {Global: true, Args: []string{""}}},
  288. Targets: []string{"yay", "yay-bin", "yay-git"},
  289. }, wantArgs: []string{"--noconfirm"}},
  290. {name: "options single", fields: fields{
  291. Op: "Y",
  292. Options: map[string]*Option{"overwrite": {Args: []string{"/tmp/a"}}, "useask": {Args: []string{""}}},
  293. Targets: []string{},
  294. }, wantArgs: []string(nil)},
  295. {name: "options doubles", fields: fields{
  296. Op: "Y",
  297. Options: map[string]*Option{"overwrite": {Args: []string{"/tmp/a", "/tmp/b", "/tmp/c"}}, "needed": {Args: []string{""}}},
  298. Targets: []string{},
  299. }, wantArgs: []string(nil)},
  300. }
  301. for _, tt := range tests {
  302. tt := tt
  303. t.Run(tt.name, func(t *testing.T) {
  304. t.Parallel()
  305. cmdArgs := &Arguments{
  306. Op: tt.fields.Op,
  307. Options: tt.fields.Options,
  308. Targets: tt.fields.Targets,
  309. }
  310. gotArgs := cmdArgs.FormatGlobals()
  311. assert.ElementsMatch(t, tt.wantArgs, gotArgs)
  312. })
  313. }
  314. }
  315. func Test_isArg(t *testing.T) {
  316. t.Parallel()
  317. got := isArg("zorg")
  318. assert.False(t, got)
  319. got = isArg("dbpath")
  320. assert.True(t, got)
  321. }
  322. func TestArguments_ParseStdin(t *testing.T) {
  323. input := []byte("yay")
  324. r, w, err := os.Pipe()
  325. require.NoError(t, err)
  326. _, err = w.Write(input)
  327. require.NoError(t, err)
  328. w.Close()
  329. // Restore stdin after the test.
  330. defer func(o *os.File) { os.Stdin = o }(os.Stdin)
  331. os.Stdin = r
  332. args := MakeArguments()
  333. err = args.parseStdin()
  334. assert.NoError(t, err)
  335. expectedTargets := []string{string(input)}
  336. assert.ElementsMatch(t, args.Targets, expectedTargets)
  337. }
  338. func TestArguments_ParseStdin_broken_pipe(t *testing.T) {
  339. r, _, err := os.Pipe()
  340. require.NoError(t, err)
  341. r.Close() // Close early to break pipe
  342. // Restore stdin after the test.
  343. defer func(o *os.File) { os.Stdin = o }(os.Stdin)
  344. os.Stdin = r
  345. args := MakeArguments()
  346. err = args.parseStdin()
  347. assert.Error(t, err)
  348. }