expand_test.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. package expansion
  2. import (
  3. "testing"
  4. api "k8s.io/kubernetes/pkg/apis/core"
  5. )
  6. func TestMapReference(t *testing.T) {
  7. envs := []api.EnvVar{
  8. {
  9. Name: "FOO",
  10. Value: "bar",
  11. },
  12. {
  13. Name: "ZOO",
  14. Value: "$(FOO)-1",
  15. },
  16. {
  17. Name: "BLU",
  18. Value: "$(ZOO)-2",
  19. },
  20. }
  21. declaredEnv := map[string]string{
  22. "FOO": "bar",
  23. "ZOO": "$(FOO)-1",
  24. "BLU": "$(ZOO)-2",
  25. }
  26. serviceEnv := map[string]string{}
  27. mapping := MappingFuncFor(declaredEnv, serviceEnv)
  28. for _, env := range envs {
  29. declaredEnv[env.Name] = Expand(env.Value, mapping)
  30. }
  31. expectedEnv := map[string]string{
  32. "FOO": "bar",
  33. "ZOO": "bar-1",
  34. "BLU": "bar-1-2",
  35. }
  36. for k, v := range expectedEnv {
  37. if e, a := v, declaredEnv[k]; e != a {
  38. t.Errorf("Expected %v, got %v", e, a)
  39. } else {
  40. delete(declaredEnv, k)
  41. }
  42. }
  43. if len(declaredEnv) != 0 {
  44. t.Errorf("Unexpected keys in declared env: %v", declaredEnv)
  45. }
  46. }
  47. func TestMapping(t *testing.T) {
  48. context := map[string]string{
  49. "VAR_A": "A",
  50. "VAR_B": "B",
  51. "VAR_C": "C",
  52. "VAR_REF": "$(VAR_A)",
  53. "VAR_EMPTY": "",
  54. }
  55. mapping := MappingFuncFor(context)
  56. doExpansionTest(t, mapping)
  57. }
  58. func TestMappingDual(t *testing.T) {
  59. context := map[string]string{
  60. "VAR_A": "A",
  61. "VAR_EMPTY": "",
  62. }
  63. context2 := map[string]string{
  64. "VAR_B": "B",
  65. "VAR_C": "C",
  66. "VAR_REF": "$(VAR_A)",
  67. }
  68. mapping := MappingFuncFor(context, context2)
  69. doExpansionTest(t, mapping)
  70. }
  71. func doExpansionTest(t *testing.T, mapping func(string) string) {
  72. cases := []struct {
  73. name string
  74. input string
  75. expected string
  76. }{
  77. {
  78. name: "whole string",
  79. input: "$(VAR_A)",
  80. expected: "A",
  81. },
  82. {
  83. name: "repeat",
  84. input: "$(VAR_A)-$(VAR_A)",
  85. expected: "A-A",
  86. },
  87. {
  88. name: "beginning",
  89. input: "$(VAR_A)-1",
  90. expected: "A-1",
  91. },
  92. {
  93. name: "middle",
  94. input: "___$(VAR_B)___",
  95. expected: "___B___",
  96. },
  97. {
  98. name: "end",
  99. input: "___$(VAR_C)",
  100. expected: "___C",
  101. },
  102. {
  103. name: "compound",
  104. input: "$(VAR_A)_$(VAR_B)_$(VAR_C)",
  105. expected: "A_B_C",
  106. },
  107. {
  108. name: "escape & expand",
  109. input: "$$(VAR_B)_$(VAR_A)",
  110. expected: "$(VAR_B)_A",
  111. },
  112. {
  113. name: "compound escape",
  114. input: "$$(VAR_A)_$$(VAR_B)",
  115. expected: "$(VAR_A)_$(VAR_B)",
  116. },
  117. {
  118. name: "mixed in escapes",
  119. input: "f000-$$VAR_A",
  120. expected: "f000-$VAR_A",
  121. },
  122. {
  123. name: "backslash escape ignored",
  124. input: "foo\\$(VAR_C)bar",
  125. expected: "foo\\Cbar",
  126. },
  127. {
  128. name: "backslash escape ignored",
  129. input: "foo\\\\$(VAR_C)bar",
  130. expected: "foo\\\\Cbar",
  131. },
  132. {
  133. name: "lots of backslashes",
  134. input: "foo\\\\\\\\$(VAR_A)bar",
  135. expected: "foo\\\\\\\\Abar",
  136. },
  137. {
  138. name: "nested var references",
  139. input: "$(VAR_A$(VAR_B))",
  140. expected: "$(VAR_A$(VAR_B))",
  141. },
  142. {
  143. name: "nested var references second type",
  144. input: "$(VAR_A$(VAR_B)",
  145. expected: "$(VAR_A$(VAR_B)",
  146. },
  147. {
  148. name: "value is a reference",
  149. input: "$(VAR_REF)",
  150. expected: "$(VAR_A)",
  151. },
  152. {
  153. name: "value is a reference x 2",
  154. input: "%%$(VAR_REF)--$(VAR_REF)%%",
  155. expected: "%%$(VAR_A)--$(VAR_A)%%",
  156. },
  157. {
  158. name: "empty var",
  159. input: "foo$(VAR_EMPTY)bar",
  160. expected: "foobar",
  161. },
  162. {
  163. name: "unterminated expression",
  164. input: "foo$(VAR_Awhoops!",
  165. expected: "foo$(VAR_Awhoops!",
  166. },
  167. {
  168. name: "expression without operator",
  169. input: "f00__(VAR_A)__",
  170. expected: "f00__(VAR_A)__",
  171. },
  172. {
  173. name: "shell special vars pass through",
  174. input: "$?_boo_$!",
  175. expected: "$?_boo_$!",
  176. },
  177. {
  178. name: "bare operators are ignored",
  179. input: "$VAR_A",
  180. expected: "$VAR_A",
  181. },
  182. {
  183. name: "undefined vars are passed through",
  184. input: "$(VAR_DNE)",
  185. expected: "$(VAR_DNE)",
  186. },
  187. {
  188. name: "multiple (even) operators, var undefined",
  189. input: "$$$$$$(BIG_MONEY)",
  190. expected: "$$$(BIG_MONEY)",
  191. },
  192. {
  193. name: "multiple (even) operators, var defined",
  194. input: "$$$$$$(VAR_A)",
  195. expected: "$$$(VAR_A)",
  196. },
  197. {
  198. name: "multiple (odd) operators, var undefined",
  199. input: "$$$$$$$(GOOD_ODDS)",
  200. expected: "$$$$(GOOD_ODDS)",
  201. },
  202. {
  203. name: "multiple (odd) operators, var defined",
  204. input: "$$$$$$$(VAR_A)",
  205. expected: "$$$A",
  206. },
  207. {
  208. name: "missing open expression",
  209. input: "$VAR_A)",
  210. expected: "$VAR_A)",
  211. },
  212. {
  213. name: "shell syntax ignored",
  214. input: "${VAR_A}",
  215. expected: "${VAR_A}",
  216. },
  217. {
  218. name: "trailing incomplete expression not consumed",
  219. input: "$(VAR_B)_______$(A",
  220. expected: "B_______$(A",
  221. },
  222. {
  223. name: "trailing incomplete expression, no content, is not consumed",
  224. input: "$(VAR_C)_______$(",
  225. expected: "C_______$(",
  226. },
  227. {
  228. name: "operator at end of input string is preserved",
  229. input: "$(VAR_A)foobarzab$",
  230. expected: "Afoobarzab$",
  231. },
  232. {
  233. name: "shell escaped incomplete expr",
  234. input: "foo-\\$(VAR_A",
  235. expected: "foo-\\$(VAR_A",
  236. },
  237. {
  238. name: "lots of $( in middle",
  239. input: "--$($($($($--",
  240. expected: "--$($($($($--",
  241. },
  242. {
  243. name: "lots of $( in beginning",
  244. input: "$($($($($--foo$(",
  245. expected: "$($($($($--foo$(",
  246. },
  247. {
  248. name: "lots of $( at end",
  249. input: "foo0--$($($($(",
  250. expected: "foo0--$($($($(",
  251. },
  252. {
  253. name: "escaped operators in variable names are not escaped",
  254. input: "$(foo$$var)",
  255. expected: "$(foo$$var)",
  256. },
  257. {
  258. name: "newline not expanded",
  259. input: "\n",
  260. expected: "\n",
  261. },
  262. }
  263. for _, tc := range cases {
  264. expanded := Expand(tc.input, mapping)
  265. if e, a := tc.expected, expanded; e != a {
  266. t.Errorf("%v: expected %q, got %q", tc.name, e, a)
  267. }
  268. }
  269. }