parser_test.go 8.4 KB

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