modules_test.go 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. // Copyright 2020 Google Inc. All rights reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package soongconfig
  15. import (
  16. "reflect"
  17. "testing"
  18. "github.com/google/blueprint/proptools"
  19. )
  20. func Test_CanonicalizeToProperty(t *testing.T) {
  21. tests := []struct {
  22. name string
  23. arg string
  24. want string
  25. }{
  26. {
  27. name: "lowercase",
  28. arg: "board",
  29. want: "board",
  30. },
  31. {
  32. name: "uppercase",
  33. arg: "BOARD",
  34. want: "BOARD",
  35. },
  36. {
  37. name: "numbers",
  38. arg: "BOARD123",
  39. want: "BOARD123",
  40. },
  41. {
  42. name: "underscore",
  43. arg: "TARGET_BOARD",
  44. want: "TARGET_BOARD",
  45. },
  46. {
  47. name: "dash",
  48. arg: "TARGET-BOARD",
  49. want: "TARGET_BOARD",
  50. },
  51. {
  52. name: "unicode",
  53. arg: "boardλ",
  54. want: "board_",
  55. },
  56. }
  57. for _, tt := range tests {
  58. t.Run(tt.name, func(t *testing.T) {
  59. if got := CanonicalizeToProperty(tt.arg); got != tt.want {
  60. t.Errorf("canonicalizeToProperty() = %v, want %v", got, tt.want)
  61. }
  62. })
  63. }
  64. }
  65. func Test_typeForPropertyFromPropertyStruct(t *testing.T) {
  66. tests := []struct {
  67. name string
  68. ps interface{}
  69. property string
  70. want string
  71. }{
  72. {
  73. name: "string",
  74. ps: struct {
  75. A string
  76. }{},
  77. property: "a",
  78. want: "string",
  79. },
  80. {
  81. name: "list",
  82. ps: struct {
  83. A []string
  84. }{},
  85. property: "a",
  86. want: "[]string",
  87. },
  88. {
  89. name: "missing",
  90. ps: struct {
  91. A []string
  92. }{},
  93. property: "b",
  94. want: "",
  95. },
  96. {
  97. name: "nested",
  98. ps: struct {
  99. A struct {
  100. B string
  101. }
  102. }{},
  103. property: "a.b",
  104. want: "string",
  105. },
  106. {
  107. name: "missing nested",
  108. ps: struct {
  109. A struct {
  110. B string
  111. }
  112. }{},
  113. property: "a.c",
  114. want: "",
  115. },
  116. {
  117. name: "not a struct",
  118. ps: struct {
  119. A string
  120. }{},
  121. property: "a.b",
  122. want: "",
  123. },
  124. {
  125. name: "nested pointer",
  126. ps: struct {
  127. A *struct {
  128. B string
  129. }
  130. }{},
  131. property: "a.b",
  132. want: "string",
  133. },
  134. {
  135. name: "nested interface",
  136. ps: struct {
  137. A interface{}
  138. }{
  139. A: struct {
  140. B string
  141. }{},
  142. },
  143. property: "a.b",
  144. want: "string",
  145. },
  146. {
  147. name: "nested interface pointer",
  148. ps: struct {
  149. A interface{}
  150. }{
  151. A: &struct {
  152. B string
  153. }{},
  154. },
  155. property: "a.b",
  156. want: "string",
  157. },
  158. {
  159. name: "nested interface nil pointer",
  160. ps: struct {
  161. A interface{}
  162. }{
  163. A: (*struct {
  164. B string
  165. })(nil),
  166. },
  167. property: "a.b",
  168. want: "string",
  169. },
  170. }
  171. for _, tt := range tests {
  172. t.Run(tt.name, func(t *testing.T) {
  173. typ := typeForPropertyFromPropertyStruct(tt.ps, tt.property)
  174. got := ""
  175. if typ != nil {
  176. got = typ.String()
  177. }
  178. if got != tt.want {
  179. t.Errorf("typeForPropertyFromPropertyStruct() = %v, want %v", got, tt.want)
  180. }
  181. })
  182. }
  183. }
  184. func Test_createAffectablePropertiesType(t *testing.T) {
  185. tests := []struct {
  186. name string
  187. affectableProperties []string
  188. factoryProps interface{}
  189. want string
  190. }{
  191. {
  192. name: "string",
  193. affectableProperties: []string{"cflags"},
  194. factoryProps: struct {
  195. Cflags string
  196. }{},
  197. want: "*struct { Cflags string }",
  198. },
  199. {
  200. name: "list",
  201. affectableProperties: []string{"cflags"},
  202. factoryProps: struct {
  203. Cflags []string
  204. }{},
  205. want: "*struct { Cflags []string }",
  206. },
  207. {
  208. name: "string pointer",
  209. affectableProperties: []string{"cflags"},
  210. factoryProps: struct {
  211. Cflags *string
  212. }{},
  213. want: "*struct { Cflags *string }",
  214. },
  215. {
  216. name: "subset",
  217. affectableProperties: []string{"cflags"},
  218. factoryProps: struct {
  219. Cflags string
  220. Ldflags string
  221. }{},
  222. want: "*struct { Cflags string }",
  223. },
  224. {
  225. name: "none",
  226. affectableProperties: []string{"cflags"},
  227. factoryProps: struct {
  228. Ldflags string
  229. }{},
  230. want: "",
  231. },
  232. {
  233. name: "nested",
  234. affectableProperties: []string{"multilib.lib32.cflags"},
  235. factoryProps: struct {
  236. Multilib struct {
  237. Lib32 struct {
  238. Cflags string
  239. }
  240. }
  241. }{},
  242. want: "*struct { Multilib struct { Lib32 struct { Cflags string } } }",
  243. },
  244. {
  245. name: "complex",
  246. affectableProperties: []string{
  247. "cflags",
  248. "multilib.lib32.cflags",
  249. "multilib.lib32.ldflags",
  250. "multilib.lib64.cflags",
  251. "multilib.lib64.ldflags",
  252. "zflags",
  253. },
  254. factoryProps: struct {
  255. Cflags string
  256. Multilib struct {
  257. Lib32 struct {
  258. Cflags string
  259. Ldflags string
  260. }
  261. Lib64 struct {
  262. Cflags string
  263. Ldflags string
  264. }
  265. }
  266. Zflags string
  267. }{},
  268. want: "*struct { Cflags string; Multilib struct { Lib32 struct { Cflags string; Ldflags string }; Lib64 struct { Cflags string; Ldflags string } }; Zflags string }",
  269. },
  270. }
  271. for _, tt := range tests {
  272. t.Run(tt.name, func(t *testing.T) {
  273. typ := createAffectablePropertiesType(tt.affectableProperties, []interface{}{tt.factoryProps})
  274. got := ""
  275. if typ != nil {
  276. got = typ.String()
  277. }
  278. if !reflect.DeepEqual(got, tt.want) {
  279. t.Errorf("createAffectablePropertiesType() = %v, want %v", got, tt.want)
  280. }
  281. })
  282. }
  283. }
  284. type properties struct {
  285. A *string
  286. B bool
  287. }
  288. type boolVarProps struct {
  289. A *string
  290. B bool
  291. Conditions_default *properties
  292. }
  293. type soongConfigVars struct {
  294. Bool_var interface{}
  295. }
  296. func Test_PropertiesToApply(t *testing.T) {
  297. mt, _ := newModuleType(&ModuleTypeProperties{
  298. Module_type: "foo",
  299. Config_namespace: "bar",
  300. Bool_variables: []string{"bool_var"},
  301. Properties: []string{"a", "b"},
  302. })
  303. boolVarPositive := &properties{
  304. A: proptools.StringPtr("A"),
  305. B: true,
  306. }
  307. conditionsDefault := &properties{
  308. A: proptools.StringPtr("default"),
  309. B: false,
  310. }
  311. actualProps := &struct {
  312. Soong_config_variables soongConfigVars
  313. }{
  314. Soong_config_variables: soongConfigVars{
  315. Bool_var: &boolVarProps{
  316. A: boolVarPositive.A,
  317. B: boolVarPositive.B,
  318. Conditions_default: conditionsDefault,
  319. },
  320. },
  321. }
  322. props := reflect.ValueOf(actualProps)
  323. testCases := []struct {
  324. name string
  325. config SoongConfig
  326. wantProps []interface{}
  327. }{
  328. {
  329. name: "no_vendor_config",
  330. config: Config(map[string]string{}),
  331. wantProps: []interface{}{conditionsDefault},
  332. },
  333. {
  334. name: "vendor_config_false",
  335. config: Config(map[string]string{"bool_var": "n"}),
  336. wantProps: []interface{}{conditionsDefault},
  337. },
  338. {
  339. name: "bool_var_true",
  340. config: Config(map[string]string{"bool_var": "y"}),
  341. wantProps: []interface{}{boolVarPositive},
  342. },
  343. }
  344. for _, tc := range testCases {
  345. gotProps, err := PropertiesToApply(mt, props, tc.config)
  346. if err != nil {
  347. t.Errorf("%s: Unexpected error in PropertiesToApply: %s", tc.name, err)
  348. }
  349. if !reflect.DeepEqual(gotProps, tc.wantProps) {
  350. t.Errorf("%s: Expected %s, got %s", tc.name, tc.wantProps, gotProps)
  351. }
  352. }
  353. }
  354. func Test_Bp2BuildSoongConfigDefinitions(t *testing.T) {
  355. testCases := []struct {
  356. desc string
  357. defs Bp2BuildSoongConfigDefinitions
  358. expected string
  359. }{
  360. {
  361. desc: "all empty",
  362. defs: Bp2BuildSoongConfigDefinitions{},
  363. expected: `soong_config_bool_variables = {}
  364. soong_config_value_variables = {}
  365. soong_config_string_variables = {}`}, {
  366. desc: "only bool",
  367. defs: Bp2BuildSoongConfigDefinitions{
  368. BoolVars: map[string]bool{
  369. "bool_var": true,
  370. },
  371. },
  372. expected: `soong_config_bool_variables = {
  373. "bool_var": True,
  374. }
  375. soong_config_value_variables = {}
  376. soong_config_string_variables = {}`}, {
  377. desc: "only value vars",
  378. defs: Bp2BuildSoongConfigDefinitions{
  379. ValueVars: map[string]bool{
  380. "value_var": true,
  381. },
  382. },
  383. expected: `soong_config_bool_variables = {}
  384. soong_config_value_variables = {
  385. "value_var": True,
  386. }
  387. soong_config_string_variables = {}`}, {
  388. desc: "only string vars",
  389. defs: Bp2BuildSoongConfigDefinitions{
  390. StringVars: map[string][]string{
  391. "string_var": []string{
  392. "choice1",
  393. "choice2",
  394. "choice3",
  395. },
  396. },
  397. },
  398. expected: `soong_config_bool_variables = {}
  399. soong_config_value_variables = {}
  400. soong_config_string_variables = {
  401. "string_var": [
  402. "choice1",
  403. "choice2",
  404. "choice3",
  405. ],
  406. }`}, {
  407. desc: "all vars",
  408. defs: Bp2BuildSoongConfigDefinitions{
  409. BoolVars: map[string]bool{
  410. "bool_var_one": true,
  411. },
  412. ValueVars: map[string]bool{
  413. "value_var_one": true,
  414. "value_var_two": true,
  415. },
  416. StringVars: map[string][]string{
  417. "string_var_one": []string{
  418. "choice1",
  419. "choice2",
  420. "choice3",
  421. },
  422. "string_var_two": []string{
  423. "foo",
  424. "bar",
  425. },
  426. },
  427. },
  428. expected: `soong_config_bool_variables = {
  429. "bool_var_one": True,
  430. }
  431. soong_config_value_variables = {
  432. "value_var_one": True,
  433. "value_var_two": True,
  434. }
  435. soong_config_string_variables = {
  436. "string_var_one": [
  437. "choice1",
  438. "choice2",
  439. "choice3",
  440. ],
  441. "string_var_two": [
  442. "foo",
  443. "bar",
  444. ],
  445. }`},
  446. }
  447. for _, test := range testCases {
  448. t.Run(test.desc, func(t *testing.T) {
  449. actual := test.defs.String()
  450. if actual != test.expected {
  451. t.Errorf("Expected:\n%s\nbut got:\n%s", test.expected, actual)
  452. }
  453. })
  454. }
  455. }