expressionorlist_test.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. package config
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "errors"
  6. "testing"
  7. yaml "sigs.k8s.io/yaml/goyaml.v3"
  8. )
  9. func TestExpressionOrListMarshalJSON(t *testing.T) {
  10. for _, tt := range []struct {
  11. err error
  12. input *ExpressionOrList
  13. name string
  14. output []byte
  15. }{
  16. {
  17. name: "single expression",
  18. input: &ExpressionOrList{
  19. Expression: "true",
  20. },
  21. output: []byte(`"true"`),
  22. err: nil,
  23. },
  24. {
  25. name: "all",
  26. input: &ExpressionOrList{
  27. All: []string{"true", "true"},
  28. },
  29. output: []byte(`{"all":["true","true"]}`),
  30. err: nil,
  31. },
  32. {
  33. name: "all one",
  34. input: &ExpressionOrList{
  35. All: []string{"true"},
  36. },
  37. output: []byte(`"true"`),
  38. err: nil,
  39. },
  40. {
  41. name: "any",
  42. input: &ExpressionOrList{
  43. Any: []string{"true", "false"},
  44. },
  45. output: []byte(`{"any":["true","false"]}`),
  46. err: nil,
  47. },
  48. {
  49. name: "any one",
  50. input: &ExpressionOrList{
  51. Any: []string{"true"},
  52. },
  53. output: []byte(`"true"`),
  54. err: nil,
  55. },
  56. } {
  57. t.Run(tt.name, func(t *testing.T) {
  58. result, err := json.Marshal(tt.input)
  59. if !errors.Is(err, tt.err) {
  60. t.Errorf("wanted marshal error: %v but got: %v", tt.err, err)
  61. }
  62. if !bytes.Equal(result, tt.output) {
  63. t.Logf("wanted: %s", string(tt.output))
  64. t.Logf("got: %s", string(result))
  65. t.Error("mismatched output")
  66. }
  67. })
  68. }
  69. }
  70. func TestExpressionOrListMarshalYAML(t *testing.T) {
  71. for _, tt := range []struct {
  72. err error
  73. input *ExpressionOrList
  74. name string
  75. output []byte
  76. }{
  77. {
  78. name: "single expression",
  79. input: &ExpressionOrList{
  80. Expression: "true",
  81. },
  82. output: []byte(`"true"`),
  83. err: nil,
  84. },
  85. {
  86. name: "all",
  87. input: &ExpressionOrList{
  88. All: []string{"true", "true"},
  89. },
  90. output: []byte(`all:
  91. - "true"
  92. - "true"`),
  93. err: nil,
  94. },
  95. {
  96. name: "all one",
  97. input: &ExpressionOrList{
  98. All: []string{"true"},
  99. },
  100. output: []byte(`"true"`),
  101. err: nil,
  102. },
  103. {
  104. name: "any",
  105. input: &ExpressionOrList{
  106. Any: []string{"true", "false"},
  107. },
  108. output: []byte(`any:
  109. - "true"
  110. - "false"`),
  111. err: nil,
  112. },
  113. {
  114. name: "any one",
  115. input: &ExpressionOrList{
  116. Any: []string{"true"},
  117. },
  118. output: []byte(`"true"`),
  119. err: nil,
  120. },
  121. } {
  122. t.Run(tt.name, func(t *testing.T) {
  123. result, err := yaml.Marshal(tt.input)
  124. if !errors.Is(err, tt.err) {
  125. t.Errorf("wanted marshal error: %v but got: %v", tt.err, err)
  126. }
  127. result = bytes.TrimSpace(result)
  128. if !bytes.Equal(result, tt.output) {
  129. t.Logf("wanted: %q", string(tt.output))
  130. t.Logf("got: %q", string(result))
  131. t.Error("mismatched output")
  132. }
  133. })
  134. }
  135. }
  136. func TestExpressionOrListUnmarshalJSON(t *testing.T) {
  137. for _, tt := range []struct {
  138. err error
  139. validErr error
  140. result *ExpressionOrList
  141. name string
  142. inp string
  143. }{
  144. {
  145. name: "simple",
  146. inp: `"\"User-Agent\" in headers"`,
  147. result: &ExpressionOrList{
  148. Expression: `"User-Agent" in headers`,
  149. },
  150. },
  151. {
  152. name: "object-and",
  153. inp: `{
  154. "all": ["\"User-Agent\" in headers"]
  155. }`,
  156. result: &ExpressionOrList{
  157. All: []string{
  158. `"User-Agent" in headers`,
  159. },
  160. },
  161. },
  162. {
  163. name: "object-or",
  164. inp: `{
  165. "any": ["\"User-Agent\" in headers"]
  166. }`,
  167. result: &ExpressionOrList{
  168. Any: []string{
  169. `"User-Agent" in headers`,
  170. },
  171. },
  172. },
  173. {
  174. name: "both-or-and",
  175. inp: `{
  176. "all": ["\"User-Agent\" in headers"],
  177. "any": ["\"User-Agent\" in headers"]
  178. }`,
  179. validErr: ErrExpressionCantHaveBoth,
  180. },
  181. {
  182. name: "expression-empty",
  183. inp: `{
  184. "any": []
  185. }`,
  186. validErr: ErrExpressionEmpty,
  187. },
  188. } {
  189. t.Run(tt.name, func(t *testing.T) {
  190. var eol ExpressionOrList
  191. if err := json.Unmarshal([]byte(tt.inp), &eol); !errors.Is(err, tt.err) {
  192. t.Errorf("wanted unmarshal error: %v but got: %v", tt.err, err)
  193. }
  194. if tt.result != nil && !eol.Equal(tt.result) {
  195. t.Logf("wanted: %#v", tt.result)
  196. t.Logf("got: %#v", &eol)
  197. t.Fatal("parsed expression is not what was expected")
  198. }
  199. if err := eol.Valid(); !errors.Is(err, tt.validErr) {
  200. t.Errorf("wanted validation error: %v but got: %v", tt.err, err)
  201. }
  202. })
  203. }
  204. }
  205. func TestExpressionOrListString(t *testing.T) {
  206. for _, tt := range []struct {
  207. name string
  208. out string
  209. in ExpressionOrList
  210. }{
  211. {
  212. name: "single expression",
  213. in: ExpressionOrList{
  214. Expression: "true",
  215. },
  216. out: "true",
  217. },
  218. {
  219. name: "all",
  220. in: ExpressionOrList{
  221. All: []string{"true"},
  222. },
  223. out: "( true )",
  224. },
  225. {
  226. name: "all with &&",
  227. in: ExpressionOrList{
  228. All: []string{"true", "true"},
  229. },
  230. out: "( true ) && ( true )",
  231. },
  232. {
  233. name: "any",
  234. in: ExpressionOrList{
  235. All: []string{"true"},
  236. },
  237. out: "( true )",
  238. },
  239. {
  240. name: "any with ||",
  241. in: ExpressionOrList{
  242. Any: []string{"true", "true"},
  243. },
  244. out: "( true ) || ( true )",
  245. },
  246. } {
  247. t.Run(tt.name, func(t *testing.T) {
  248. result := tt.in.String()
  249. if result != tt.out {
  250. t.Errorf("wanted %q, got: %q", tt.out, result)
  251. }
  252. })
  253. }
  254. }