Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

765 linhas
27 KiB

  1. -module(rebar_upgrade_SUITE).
  2. -include_lib("common_test/include/ct.hrl").
  3. -include_lib("eunit/include/eunit.hrl").
  4. -compile(export_all).
  5. all() -> [{group, git}, {group, pkg}, novsn_pkg].
  6. groups() ->
  7. [{all, [], [top_a, top_b, top_c, top_d1, top_d2, top_e,
  8. pair_a, pair_b, pair_ab, pair_c, pair_all,
  9. triplet_a, triplet_b, triplet_c,
  10. tree_a, tree_b, tree_c, tree_c2, tree_cj, tree_ac, tree_all,
  11. delete_d, promote, stable_lock, fwd_lock,
  12. compile_upgrade_parity, umbrella_config,
  13. profiles, profiles_exclusion]},
  14. {git, [], [{group, all}]},
  15. {pkg, [], [{group, all}]}].
  16. init_per_suite(Config) ->
  17. application:start(meck),
  18. Config.
  19. end_per_suite(_Config) ->
  20. application:stop(meck).
  21. init_per_group(git, Config) ->
  22. [{deps_type, git} | Config];
  23. init_per_group(pkg, Config) ->
  24. [{deps_type, pkg} | Config];
  25. init_per_group(_, Config) ->
  26. Config.
  27. end_per_group(_, Config) ->
  28. Config.
  29. init_per_testcase(novsn_pkg, Config0) ->
  30. Config = rebar_test_utils:init_rebar_state(Config0, "novsn_pkg_"),
  31. AppDir = ?config(apps, Config),
  32. RebarConf = rebar_test_utils:create_config(AppDir, [{deps, [fakeapp]}]),
  33. Deps = [{{<<"fakeapp">>, <<"1.0.0">>}, []}],
  34. UpDeps = [{{<<"fakeapp">>, <<"1.1.0">>}, []}],
  35. Upgrades = ["fakeapp"],
  36. [{rebarconfig, RebarConf},
  37. {mock, fun() ->
  38. catch mock_pkg_resource:unmock(),
  39. mock_pkg_resource:mock([{pkgdeps, Deps}, {upgrade, []}])
  40. end},
  41. {mock_update, fun() ->
  42. catch mock_pkg_resource:unmock(),
  43. mock_pkg_resource:mock([{pkgdeps, UpDeps++Deps}, {upgrade, Upgrades}])
  44. end},
  45. {expected, {ok, [{dep, "fakeapp", "1.1.0"}, {lock, "fakeapp", "1.1.0"}]}}
  46. | Config];
  47. init_per_testcase(Case, Config) ->
  48. DepsType = ?config(deps_type, Config),
  49. {Deps, UpDeps, ToUp, Expectations} = upgrades(Case),
  50. Expanded = rebar_test_utils:expand_deps(DepsType, Deps),
  51. UpExpanded = rebar_test_utils:expand_deps(DepsType, UpDeps),
  52. [{expected, normalize_unlocks(Expectations)},
  53. {mock, fun() -> mock_deps(DepsType, Expanded, []) end},
  54. {mock_update, fun() -> mock_deps(DepsType, Expanded, UpExpanded, ToUp) end}
  55. | setup_project(Case, Config, Expanded, UpExpanded)].
  56. end_per_testcase(_, Config) ->
  57. meck:unload(),
  58. Config.
  59. setup_project(Case=umbrella_config, Config0, Deps, UpDeps) ->
  60. DepsType = ?config(deps_type, Config0),
  61. NameRoot = atom_to_list(Case)++"_"++atom_to_list(DepsType),
  62. Config = rebar_test_utils:init_rebar_state(Config0, NameRoot++"_"),
  63. AppDir = filename:join([?config(apps, Config), "apps", NameRoot]),
  64. rebar_test_utils:create_app(AppDir, "Root", "0.0.0", [kernel, stdlib]),
  65. TopDeps = rebar_test_utils:top_level_deps(Deps),
  66. TopConf = rebar_test_utils:create_config(AppDir, [{deps, []}]),
  67. RebarConf = rebar_test_utils:create_config(AppDir, [{deps, TopDeps}]),
  68. [{rebarconfig, TopConf},
  69. {rebarumbrella, RebarConf},
  70. {next_top_deps, rebar_test_utils:top_level_deps(UpDeps)} | Config];
  71. setup_project(Case, Config0, Deps, UpDeps) when Case == profiles;
  72. Case == profiles_exclusion ->
  73. DepsType = ?config(deps_type, Config0),
  74. NameRoot = atom_to_list(Case)++"_"++atom_to_list(DepsType),
  75. Config = rebar_test_utils:init_rebar_state(Config0, NameRoot++"_"),
  76. AppDir = filename:join([?config(apps, Config), "apps", NameRoot]),
  77. rebar_test_utils:create_app(AppDir, "Root", "0.0.0", [kernel, stdlib]),
  78. [Top|ProfileDeps] = rebar_test_utils:top_level_deps(Deps),
  79. RebarConf = rebar_test_utils:create_config(AppDir, [
  80. {deps, [Top]},
  81. {profiles, [{fake, [{deps, ProfileDeps}]}]}
  82. ]),
  83. [NextTop|NextPDeps] = rebar_test_utils:top_level_deps(UpDeps),
  84. NextConfig = [{deps, [NextTop]},
  85. {profiles, [{fake, [{deps, NextPDeps}]}]}],
  86. [{rebarconfig, RebarConf},
  87. {next_config, NextConfig} | Config];
  88. setup_project(Case, Config0, Deps, UpDeps) ->
  89. DepsType = ?config(deps_type, Config0),
  90. Config = rebar_test_utils:init_rebar_state(
  91. Config0,
  92. atom_to_list(Case)++"_"++atom_to_list(DepsType)++"_"
  93. ),
  94. AppDir = ?config(apps, Config),
  95. rebar_test_utils:create_app(AppDir, "Root", "0.0.0", [kernel, stdlib]),
  96. TopDeps = rebar_test_utils:top_level_deps(Deps),
  97. RebarConf = rebar_test_utils:create_config(AppDir, [{deps, TopDeps}]),
  98. [{rebarconfig, RebarConf},
  99. {next_top_deps, rebar_test_utils:top_level_deps(UpDeps)} | Config].
  100. upgrades(top_a) ->
  101. %% Original tree
  102. {[{"A", "1", [{"B", [{"D", "1", []}]},
  103. {"C", [{"D", "2", []}]}]}
  104. ],
  105. %% Updated tree
  106. [{"A", "1", [{"B", [{"D", "3", []}]},
  107. {"C", [{"D", "2", []}]}]}
  108. ],
  109. %% Modified apps, gobally
  110. ["A","B","D"],
  111. %% upgrade vs. new tree
  112. {"A", [{"A","1"}, "B", "C", {"D","3"}]}};
  113. upgrades(top_b) ->
  114. %% Original tree
  115. {[{"A", "1", [{"B", [{"D", "1", []}]},
  116. {"C", [{"D", "2", []}]}]}
  117. ],
  118. %% Updated tree
  119. [{"A", "1", [{"B", [{"D", "3", []}]},
  120. {"C", [{"D", "2", []}]}]}
  121. ],
  122. %% Modified apps, gobally
  123. ["A","B","D"],
  124. %% upgrade vs. new tree
  125. {"B", {error, {rebar_prv_upgrade, {transitive_dependency, <<"B">>}}}}};
  126. upgrades(top_c) ->
  127. %% Original tree
  128. {[{"A", "1", [{"B", [{"D", "1", []}]},
  129. {"C", [{"D", "2", []}]}]}
  130. ],
  131. %% Updated tree
  132. [{"A", "1", [{"B", [{"D", "3", []}]},
  133. {"C", [{"D", "2", []}]}]}
  134. ],
  135. %% Modified apps, gobally
  136. ["A","B","D"],
  137. %% upgrade vs. new tree
  138. {"C", {error, {rebar_prv_upgrade, {transitive_dependency, <<"C">>}}}}};
  139. upgrades(top_d1) ->
  140. %% Original tree
  141. {[{"A", "1", [{"B", [{"D", "1", []}]},
  142. {"C", [{"D", "2", []}]}]}
  143. ],
  144. %% Updated tree
  145. [{"A", "1", [{"B", [{"D", "3", []}]},
  146. {"C", [{"D", "2", []}]}]}
  147. ],
  148. %% Modified apps, gobally
  149. ["A","B","D"],
  150. %% upgrade vs. new tree
  151. {"D", {error, {rebar_prv_upgrade, {transitive_dependency, <<"D">>}}}}};
  152. upgrades(top_d2) ->
  153. %% Original tree
  154. {[{"A", "1", [{"B", [{"D", "1", []}]},
  155. {"C", [{"D", "2", []}]}]}
  156. ],
  157. %% Updated tree
  158. [{"A", "1", [{"B", [{"D", "3", []}]},
  159. {"C", [{"D", "2", []}]}]}
  160. ],
  161. %% Modified apps, gobally
  162. ["A","B","D"],
  163. %% upgrade vs. new tree
  164. {"D", {error, {rebar_prv_upgrade, {transitive_dependency, <<"D">>}}}}};
  165. upgrades(top_e) ->
  166. %% Original tree
  167. {[{"A", "1", [{"B", [{"D", "1", []}]},
  168. {"C", [{"D", "2", []}]}]}
  169. ],
  170. %% Updated tree
  171. [{"A", "1", [{"B", [{"D", "3", []}]},
  172. {"C", [{"D", "2", []}]}]}
  173. ],
  174. %% Modified apps, gobally
  175. ["A","B","D"],
  176. %% upgrade vs. new tree
  177. {"E", {error, {rebar_prv_upgrade, {unknown_dependency, <<"E">>}}}}};
  178. upgrades(pair_a) ->
  179. {[{"A", "1", [{"C", "1", []}]},
  180. {"B", "1", [{"D", "1", []}]}
  181. ],
  182. [{"A", "2", [{"C", "2", []}]},
  183. {"B", "2", [{"D", "2", []}]}
  184. ],
  185. ["A","B","C","D"],
  186. {"A", [{"A","2"},{"C","2"},{"B","1"},{"D","1"}]}};
  187. upgrades(pair_b) ->
  188. {[{"A", "1", [{"C", "1", []}]},
  189. {"B", "1", [{"D", "1", []}]}
  190. ],
  191. [{"A", "2", [{"C", "2", []}]},
  192. {"B", "2", [{"D", "2", []}]}
  193. ],
  194. ["A","B","C","D"],
  195. {"B", [{"A","1"},{"C","1"},{"B","2"},{"D","2"}]}};
  196. upgrades(pair_ab) ->
  197. {[{"A", "1", [{"C", "1", []}]},
  198. {"B", "1", [{"D", "1", []}]}
  199. ],
  200. [{"A", "2", [{"C", "2", []}]},
  201. {"B", "2", [{"D", "2", []}]}
  202. ],
  203. ["A","B","C","D"],
  204. {"A,B", [{"A","2"},{"C","2"},{"B","2"},{"D","2"}]}};
  205. upgrades(pair_c) ->
  206. {[{"A", "1", [{"C", "1", []}]},
  207. {"B", "1", [{"D", "1", []}]}
  208. ],
  209. [{"A", "2", [{"C", "2", []}]},
  210. {"B", "2", [{"D", "2", []}]}
  211. ],
  212. ["A","B","C","D"],
  213. {"C", {error, {rebar_prv_upgrade, {transitive_dependency, <<"C">>}}}}};
  214. upgrades(pair_all) ->
  215. {[{"A", "1", [{"C", "1", []}]},
  216. {"B", "1", [{"D", "1", []}]}
  217. ],
  218. [{"A", "2", [{"C", "2", []}]},
  219. {"B", "2", [{"D", "2", []}]}
  220. ],
  221. ["A","B","C","D"],
  222. {"", [{"A","2"},{"C","2"},{"B","2"},{"D","2"}]}};
  223. upgrades(triplet_a) ->
  224. {[{"A", "1", [{"D",[]},
  225. {"E","3",[]}]},
  226. {"B", "1", [{"F","1",[]},
  227. {"G",[]}]},
  228. {"C", "0", [{"H","3",[]},
  229. {"I",[]}]}],
  230. [{"A", "1", [{"D",[]},
  231. {"E","2",[]}]},
  232. {"B", "1", [{"F","1",[]},
  233. {"G",[]}]},
  234. {"C", "1", [{"H","4",[]},
  235. {"I",[]}]}],
  236. ["A","C","E","H"],
  237. {"A", [{"A","1"}, "D", {"E","2"},
  238. {"B","1"}, {"F","1"}, "G",
  239. {"C","0"}, {"H","3"}, "I"]}};
  240. upgrades(triplet_b) ->
  241. {[{"A", "1", [{"D",[]},
  242. {"E","3",[]}]},
  243. {"B", "1", [{"F","1",[]},
  244. {"G",[]}]},
  245. {"C", "0", [{"H","3",[]},
  246. {"I",[]}]}],
  247. [{"A", "2", [{"D",[]},
  248. {"E","2",[]}]},
  249. {"B", "1", [{"F","1",[]},
  250. {"G",[]}]},
  251. {"C", "1", [{"H","4",[]},
  252. {"I",[]}]}],
  253. ["A","C","E","H"],
  254. {"B", [{"A","1"}, "D", {"E","3"},
  255. {"B","1"}, {"F","1"}, "G",
  256. {"C","0"}, {"H","3"}, "I"]}};
  257. upgrades(triplet_c) ->
  258. {[{"A", "1", [{"D",[]},
  259. {"E","3",[]}]},
  260. {"B", "1", [{"F","1",[]},
  261. {"G",[]}]},
  262. {"C", "0", [{"H","3",[]},
  263. {"I",[]}]}],
  264. [{"A", "2", [{"D",[]},
  265. {"E","2",[]}]},
  266. {"B", "1", [{"F","1",[]},
  267. {"G",[]}]},
  268. {"C", "1", [{"H","4",[]},
  269. {"I",[]}]}],
  270. ["A","C","E","H"],
  271. {"C", [{"A","1"}, "D", {"E","3"},
  272. {"B","1"}, {"F","1"}, "G",
  273. {"C","1"}, {"H","4"}, "I"]}};
  274. upgrades(tree_a) ->
  275. {[{"A", "1", [{"D",[{"J",[]}]},
  276. {"E",[{"I","1",[]}]}]},
  277. {"B", "1", [{"F",[]},
  278. {"G",[]}]},
  279. {"C", "1", [{"H",[]},
  280. {"I","2",[]}]}
  281. ],
  282. [{"A", "1", [{"D",[{"J",[]}]},
  283. {"E",[{"I","1",[]}]}]},
  284. {"B", "1", [{"F",[]},
  285. {"G",[]}]},
  286. {"C", "2", [{"H",[]}]}
  287. ],
  288. ["C"],
  289. {"A", [{"A","1"}, "D", "J", "E",
  290. {"B","1"}, "F", "G",
  291. {"C","1"}, "H", {"I","2"}]}};
  292. upgrades(tree_b) ->
  293. {[{"A", "1", [{"D",[{"J",[]}]},
  294. {"E",[{"I","1",[]}]}]},
  295. {"B", "1", [{"F",[]},
  296. {"G",[]}]},
  297. {"C", "1", [{"H",[]},
  298. {"I","2",[]}]}
  299. ],
  300. [{"A", "1", [{"D",[{"J",[]}]},
  301. {"E",[{"I","1",[]}]}]},
  302. {"B", "1", [{"F",[]},
  303. {"G",[]}]},
  304. {"C", "2", [{"H",[]}]}
  305. ],
  306. ["C"],
  307. {"B", [{"A","1"}, "D", "J", "E",
  308. {"B","1"}, "F", "G",
  309. {"C","1"}, "H", {"I","2"}]}};
  310. upgrades(tree_c) ->
  311. {[{"A", "1", [{"D",[{"J",[]}]},
  312. {"E",[{"I","1",[]}]}]},
  313. {"B", "1", [{"F",[]},
  314. {"G",[]}]},
  315. {"C", "1", [{"H",[]},
  316. {"I","2",[]}]}
  317. ],
  318. [{"A", "1", [{"D",[{"J",[]}]},
  319. {"E",[{"I","1",[]}]}]},
  320. {"B", "1", [{"F",[]},
  321. {"G",[]}]},
  322. {"C", "1", [{"H",[]}]}
  323. ],
  324. ["C","I"],
  325. {"C", [{"A","1"}, "D", "J", "E", {"I","1"},
  326. {"B","1"}, "F", "G",
  327. {"C","1"}, "H"]}};
  328. upgrades(tree_c2) ->
  329. {[{"A", "1", [{"D",[{"J",[]}]},
  330. {"E",[{"I","1",[]}]}]},
  331. {"B", "1", [{"F",[]},
  332. {"G",[]}]},
  333. {"C", "1", [{"H",[]},
  334. {"I","2",[]}]}
  335. ],
  336. [{"A", "1", [{"D",[{"J",[]}]},
  337. {"E",[{"I","1",[]}]}]},
  338. {"B", "1", [{"F",[]},
  339. {"G",[]}]},
  340. {"C", "1", [{"H",[{"K",[]}]},
  341. {"I","2",[]}]}
  342. ],
  343. ["C", "H"],
  344. {"C", [{"A","1"}, "D", "J", "E",
  345. {"B","1"}, "F", "G",
  346. {"C","1"}, "H", {"I", "2"}, "K"]}};
  347. upgrades(tree_cj) ->
  348. {[{"A", "1", [{"D",[{"J", "1",[]}]},
  349. {"E",[{"I","1",[]}]}]},
  350. {"B", "1", [{"F",[]},
  351. {"G",[]}]},
  352. {"C", "1", [{"H",[]},
  353. {"I","1",[]}]}
  354. ],
  355. [{"A", "1", [{"D",[{"J", "2", []}]},
  356. {"E",[{"I","1",[]}]}]},
  357. {"B", "1", [{"F",[]},
  358. {"G",[]}]},
  359. {"C", "1", [{"H",[]},
  360. {"I","1",[]}]}
  361. ],
  362. ["C","J"],
  363. {"C", [{"A","1"}, "D", {"J", "1"}, "E", {"I","1"},
  364. {"B","1"}, "F", "G",
  365. {"C","1"}, "H"]}};
  366. upgrades(tree_ac) ->
  367. {[{"A", "1", [{"D",[{"J",[]}]},
  368. {"E",[{"I","1",[]}]}]},
  369. {"B", "1", [{"F",[]},
  370. {"G",[]}]},
  371. {"C", "1", [{"H",[]},
  372. {"I","2",[]}]}
  373. ],
  374. [{"A", "1", [{"D",[{"J",[]}]},
  375. {"E",[{"I","1",[]}]}]},
  376. {"B", "1", [{"F",[]},
  377. {"G",[]}]},
  378. {"C", "1", [{"H",[]}]}
  379. ],
  380. ["C","I"],
  381. {"C, A", [{"A","1"}, "D", "J", "E", {"I","1"},
  382. {"B","1"}, "F", "G",
  383. {"C","1"}, "H"]}};
  384. upgrades(tree_all) ->
  385. {[{"A", "1", [{"D",[{"J",[]}]},
  386. {"E",[{"I","1",[]}]}]},
  387. {"B", "1", [{"F",[]},
  388. {"G",[]}]},
  389. {"C", "1", [{"H",[]},
  390. {"I","2",[]}]}
  391. ],
  392. [{"A", "1", [{"D",[{"J",[]}]},
  393. {"E",[{"I","1",[]}]}]},
  394. {"B", "1", [{"F",[]},
  395. {"G",[]}]},
  396. {"C", "1", [{"H",[]}]}
  397. ],
  398. ["C","I"],
  399. {"", [{"A","1"}, "D", "J", "E", {"I","1"},
  400. {"B","1"}, "F", "G",
  401. {"C","1"}, "H"]}};
  402. upgrades(delete_d) ->
  403. {[{"A", "1", [{"B", [{"D", "1", []}]},
  404. {"C", [{"D", "2", []}]}]}
  405. ],
  406. [{"A", "2", [{"B", []},
  407. {"C", []}]}
  408. ],
  409. ["A","B", "C"],
  410. %% upgrade vs. new tree
  411. {"", [{"A","2"}, "B", "C"]}};
  412. upgrades(promote) ->
  413. {[{"A", "1", [{"C", "1", []}]},
  414. {"B", "1", [{"D", "1", []}]}
  415. ],
  416. [{"A", "2", [{"C", "2", []}]},
  417. {"B", "2", [{"D", "2", []}]},
  418. {"C", "3", []}
  419. ],
  420. ["A","B","C","D"],
  421. {"C", [{"A","1"},{"C","3"},{"B","1"},{"D","1"}]}};
  422. upgrades(stable_lock) ->
  423. {[{"A", "1", [{"C", "1", []}]},
  424. {"B", "1", [{"D", "1", []}]}
  425. ], % lock after this
  426. [{"A", "2", [{"C", "2", []}]},
  427. {"B", "2", [{"D", "2", []}]}
  428. ],
  429. [],
  430. %% Run a regular lock and no app should be upgraded
  431. {"any", [{"A","1"},{"C","1"},{"B","1"},{"D","1"}]}};
  432. upgrades(fwd_lock) ->
  433. {[{"A", "1", [{"C", "1", []}]},
  434. {"B", "1", [{"D", "1", []}]}
  435. ],
  436. [{"A", "2", [{"C", "2", []}]},
  437. {"B", "2", [{"D", "2", []}]}
  438. ],
  439. ["A","B","C","D"],
  440. %% For this one, we should build, rewrite the lock
  441. %% file to include the result post-upgrade, and then
  442. %% run a regular lock to see that the lock file is respected
  443. %% in deps.
  444. {"any", [{"A","2"},{"C","2"},{"B","2"},{"D","2"}]}};
  445. upgrades(compile_upgrade_parity) ->
  446. {[{"A", "1", [{"D",[{"J",[]}]},
  447. {"E",[{"I","1",[]}]}]},
  448. {"B", "1", [{"F",[]},
  449. {"G",[]}]},
  450. {"C", "1", [{"H",[]},
  451. {"I","2",[]}]}
  452. ],
  453. [],
  454. [],
  455. {"", [{"A","1"}, "D", "J", "E", {"I","1"},
  456. {"B","1"}, "F", "G",
  457. {"C","1"}, "H"]}};
  458. upgrades(umbrella_config) ->
  459. {[{"A", "1", []}],
  460. [{"A", "2", []}],
  461. ["A"],
  462. {"A", [{"A","2"}]}};
  463. upgrades(profiles) ->
  464. %% Ensure that we can unlock deps under a given profile;
  465. %% B and C should both be in a custom profile
  466. %% and must not be locked.
  467. {[{"A", "1", [{"D",[]},
  468. {"E","3",[]}]},
  469. {"B", "1", [{"F","1",[]},
  470. {"G",[]}]},
  471. {"C", "0", [{"H","3",[]},
  472. {"I",[]}]}],
  473. [{"A", "2", [{"D",[]},
  474. {"E","2",[]}]},
  475. {"B", "2", [{"F","2",[]},
  476. {"G",[]}]},
  477. {"C", "1", [{"H","4",[]},
  478. {"I",[]}]}],
  479. ["A","B","C","E","F","H"],
  480. {"C", [{"A","1"}, "D", {"E","3"},
  481. {"B","2"}, {"F","2"}, "G",
  482. {"C","1"}, {"H","4"}, "I"]}};
  483. upgrades(profiles_exclusion) ->
  484. %% Ensure that we can unlock deps under a given profile;
  485. %% B and C should both be in a custom profile
  486. %% and must not be locked.
  487. {[{"A", "1", [{"D",[]},
  488. {"E","3",[]}]},
  489. {"B", "1", [{"F","1",[]},
  490. {"G",[]}]},
  491. {"C", "0", [{"H","3",[]},
  492. {"I",[]}]}],
  493. [{"A", "2", [{"D",[]},
  494. {"E","2",[]}]},
  495. {"B", "2", [{"F","2",[]},
  496. {"G",[]}]},
  497. {"C", "1", [{"H","4",[]},
  498. {"I",[]}]}],
  499. ["A","B","C","E","F","H"],
  500. {"A", [{"A","1"}, "D", {"E","3"},
  501. {"B","2"}, {"F","2"}, "G",
  502. {"C","1"}, {"H","4"}, "I"]}}.
  503. %% TODO: add a test that verifies that unlocking files and then
  504. %% running the upgrade code is enough to properly upgrade things.
  505. mock_deps(git, Deps, Upgrades) ->
  506. catch mock_git_resource:unmock(),
  507. {SrcDeps, _} = rebar_test_utils:flat_deps(Deps),
  508. mock_git_resource:mock([{deps, SrcDeps}, {upgrade, Upgrades}]);
  509. mock_deps(pkg, Deps, Upgrades) ->
  510. catch mock_pkg_resource:unmock(),
  511. {_, PkgDeps} = rebar_test_utils:flat_deps(Deps),
  512. mock_pkg_resource:mock([{pkgdeps, PkgDeps}, {upgrade, Upgrades}]).
  513. mock_deps(git, OldDeps, Deps, Upgrades) ->
  514. catch mock_git_resource:unmock(),
  515. {SrcDeps, _} = rebar_test_utils:flat_deps(Deps++OldDeps),
  516. mock_git_resource:mock([{deps, SrcDeps}, {upgrade, Upgrades}]);
  517. mock_deps(pkg, OldDeps, Deps, Upgrades) ->
  518. catch mock_pkg_resource:unmock(),
  519. {_, PkgDeps} = rebar_test_utils:flat_deps(Deps++OldDeps),
  520. mock_pkg_resource:mock([{pkgdeps, PkgDeps}, {upgrade, Upgrades}]).
  521. normalize_unlocks({App, Locks}) ->
  522. {iolist_to_binary(App),
  523. normalize_unlocks_expect(Locks)};
  524. normalize_unlocks({App, Vsn, Locks}) ->
  525. {iolist_to_binary(App), iolist_to_binary(Vsn),
  526. normalize_unlocks_expect(Locks)}.
  527. normalize_unlocks_expect({error, Reason}) ->
  528. {error, Reason};
  529. normalize_unlocks_expect([]) ->
  530. [];
  531. normalize_unlocks_expect([{App,Vsn} | Rest]) ->
  532. [{dep, App, Vsn},
  533. {lock, App, Vsn}
  534. | normalize_unlocks_expect(Rest)];
  535. normalize_unlocks_expect([App | Rest]) ->
  536. [{dep, App},
  537. {lock, App} | normalize_unlocks_expect(Rest)].
  538. top_a(Config) -> run(Config).
  539. top_b(Config) -> run(Config).
  540. top_c(Config) -> run(Config).
  541. top_d1(Config) -> run(Config).
  542. top_d2(Config) -> run(Config).
  543. top_e(Config) -> run(Config).
  544. pair_a(Config) -> run(Config).
  545. pair_b(Config) -> run(Config).
  546. pair_ab(Config) -> run(Config).
  547. pair_c(Config) -> run(Config).
  548. pair_all(Config) -> run(Config).
  549. triplet_a(Config) -> run(Config).
  550. triplet_b(Config) -> run(Config).
  551. triplet_c(Config) -> run(Config).
  552. tree_a(Config) -> run(Config).
  553. tree_b(Config) -> run(Config).
  554. tree_c(Config) -> run(Config).
  555. tree_c2(Config) -> run(Config).
  556. tree_cj(Config) -> run(Config).
  557. tree_ac(Config) -> run(Config).
  558. tree_all(Config) -> run(Config).
  559. promote(Config) -> run(Config).
  560. delete_d(Config) ->
  561. meck:new(rebar_log, [no_link, passthrough]),
  562. run(Config),
  563. Infos = [{Str, Args}
  564. || {_, {rebar_log, log, [info, Str, Args]}, _} <- meck:history(rebar_log)],
  565. meck:unload(rebar_log),
  566. ?assertNotEqual([],
  567. [1 || {"App ~ts is no longer needed and can be deleted.",
  568. [<<"D">>]} <- Infos]).
  569. stable_lock(Config) ->
  570. apply(?config(mock, Config), []),
  571. {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)),
  572. %% Install dependencies before re-mocking for an upgrade
  573. rebar_test_utils:run_and_check(Config, RebarConfig, ["lock"], {ok, []}),
  574. {App, Unlocks} = ?config(expected, Config),
  575. ct:pal("Upgrades: ~p -> ~p", [App, Unlocks]),
  576. Expectation = case Unlocks of
  577. {error, Term} -> {error, Term};
  578. _ -> {ok, Unlocks}
  579. end,
  580. apply(?config(mock_update, Config), []),
  581. NewRebarConf = rebar_test_utils:create_config(?config(apps, Config),
  582. [{deps, ?config(next_top_deps, Config)}]),
  583. {ok, NewRebarConfig} = file:consult(NewRebarConf),
  584. rebar_test_utils:run_and_check(
  585. Config, NewRebarConfig, ["lock", App], Expectation
  586. ).
  587. fwd_lock(Config) ->
  588. apply(?config(mock, Config), []),
  589. {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)),
  590. %% Install dependencies before re-mocking for an upgrade
  591. rebar_test_utils:run_and_check(Config, RebarConfig, ["lock"], {ok, []}),
  592. {App, Unlocks} = ?config(expected, Config),
  593. ct:pal("Upgrades: ~p -> ~p", [App, Unlocks]),
  594. Expectation = case Unlocks of
  595. {error, Term} -> {error, Term};
  596. _ -> {ok, Unlocks}
  597. end,
  598. rewrite_locks(Expectation, Config),
  599. apply(?config(mock_update, Config), []),
  600. NewRebarConf = rebar_test_utils:create_config(?config(apps, Config),
  601. [{deps, ?config(next_top_deps, Config)}]),
  602. {ok, NewRebarConfig} = file:consult(NewRebarConf),
  603. rebar_test_utils:run_and_check(
  604. Config, NewRebarConfig, ["lock", App], Expectation
  605. ).
  606. compile_upgrade_parity(Config) ->
  607. AppDir = ?config(apps, Config),
  608. apply(?config(mock, Config), []),
  609. {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)),
  610. %% compiling and upgrading should generate the same lockfiles when
  611. %% deps are identical
  612. Lockfile = filename:join([AppDir, "rebar.lock"]),
  613. rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, []}),
  614. {ok, CompileLockData1} = file:read_file(Lockfile),
  615. rebar_test_utils:run_and_check(Config, RebarConfig, ["upgrade"], {ok, []}),
  616. {ok, UpgradeLockData} = file:read_file(Lockfile),
  617. rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, []}),
  618. {ok, CompileLockData2} = file:read_file(Lockfile),
  619. ?assertEqual(CompileLockData1, CompileLockData2),
  620. ?assertEqual(CompileLockData1, UpgradeLockData).
  621. umbrella_config(Config) ->
  622. apply(?config(mock, Config), []),
  623. {ok, TopConfig} = file:consult(?config(rebarconfig, Config)),
  624. %% Install dependencies before re-mocking for an upgrade
  625. rebar_test_utils:run_and_check(Config, TopConfig, ["lock"], {ok, []}),
  626. {App, Unlocks} = ?config(expected, Config),
  627. ct:pal("Upgrades: ~p -> ~p", [App, Unlocks]),
  628. Expectation = case Unlocks of
  629. {error, Term} -> {error, Term};
  630. _ -> {ok, Unlocks}
  631. end,
  632. meck:new(rebar_prv_upgrade, [passthrough]),
  633. meck:expect(rebar_prv_upgrade, do, fun(S) ->
  634. apply(?config(mock_update, Config), []),
  635. meck:passthrough([S])
  636. end),
  637. _NewRebarConf = rebar_test_utils:create_config(filename:dirname(?config(rebarumbrella, Config)),
  638. [{deps, ?config(next_top_deps, Config)}]),
  639. %% re-run from the top-level with the old config still in place;
  640. %% detection must happen when going for umbrella apps!
  641. rebar_test_utils:run_and_check(
  642. Config, TopConfig, ["upgrade", App], Expectation
  643. ),
  644. meck:unload(rebar_prv_upgrade).
  645. profiles(Config) ->
  646. apply(?config(mock, Config), []),
  647. {ok, TopConfig} = file:consult(?config(rebarconfig, Config)),
  648. %% Install dependencies before re-mocking for an upgrade
  649. rebar_test_utils:run_and_check(Config, TopConfig, ["lock"], {ok, []}),
  650. %% Install test deps along with them
  651. rebar_test_utils:run_and_check(Config, TopConfig, ["as","fake","lock"], {ok, []}),
  652. {App, Unlocks} = ?config(expected, Config),
  653. ct:pal("Upgrades: ~p -> ~p", [App, Unlocks]),
  654. Expectation = case Unlocks of
  655. {error, Term} -> {error, Term};
  656. _ -> {ok, [T || T <- Unlocks,
  657. element(1,T) == dep orelse
  658. lists:member(element(2,T), ["A","D","E"])]}
  659. end,
  660. meck:new(rebar_prv_app_discovery, [passthrough]),
  661. meck:expect(rebar_prv_app_discovery, do, fun(S) ->
  662. apply(?config(mock_update, Config), []),
  663. meck:passthrough([S])
  664. end),
  665. NewRebarConf = rebar_test_utils:create_config(?config(apps, Config),
  666. ?config(next_config, Config)),
  667. {ok, NewRebarConfig} = file:consult(NewRebarConf),
  668. rebar_test_utils:run_and_check(
  669. Config, NewRebarConfig, ["as","fake","upgrade", App], Expectation
  670. ),
  671. meck:unload(rebar_prv_app_discovery).
  672. profiles_exclusion(Config) -> profiles(Config).
  673. run(Config) ->
  674. apply(?config(mock, Config), []),
  675. ConfigPath = ?config(rebarconfig, Config),
  676. {ok, RebarConfig} = file:consult(ConfigPath),
  677. %% Install dependencies before re-mocking for an upgrade
  678. rebar_test_utils:run_and_check(Config, RebarConfig, ["lock"], {ok, []}),
  679. {App, Unlocks} = ?config(expected, Config),
  680. ct:pal("Upgrades: ~p -> ~p", [App, Unlocks]),
  681. Expectation = case Unlocks of
  682. {error, Term} -> {error, Term};
  683. _ -> {ok, Unlocks}
  684. end,
  685. meck:new(rebar_prv_upgrade, [passthrough]),
  686. meck:expect(rebar_prv_upgrade, do, fun(S) ->
  687. apply(?config(mock_update, Config), []),
  688. meck:passthrough([S])
  689. end),
  690. NewRebarConf = rebar_test_utils:create_config(filename:dirname(ConfigPath),
  691. [{deps, ?config(next_top_deps, Config)}]),
  692. {ok, NewRebarConfig} = file:consult(NewRebarConf),
  693. rebar_test_utils:run_and_check(
  694. Config, NewRebarConfig, ["upgrade", App], Expectation
  695. ),
  696. meck:unload(rebar_prv_upgrade).
  697. novsn_pkg(Config) ->
  698. apply(?config(mock, Config), []),
  699. {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)),
  700. %% Install dependencies before re-mocking for an upgrade
  701. rebar_test_utils:run_and_check(Config, RebarConfig, ["lock"], {ok, []}),
  702. Expectation = ?config(expected, Config),
  703. apply(?config(mock_update, Config), []),
  704. rebar_test_utils:run_and_check(
  705. Config, RebarConfig, ["upgrade"], Expectation
  706. ),
  707. ok.
  708. rewrite_locks({ok, Expectations}, Config) ->
  709. AppDir = ?config(apps, Config),
  710. LockFile = filename:join([AppDir, "rebar.lock"]),
  711. Locks = case ?config(deps_type, Config) of
  712. git ->
  713. {ok, [LockData]} = file:consult(LockFile),
  714. LockData;
  715. pkg ->
  716. {ok, [{_Vsn, LockData}|_]} = file:consult(LockFile),
  717. LockData
  718. end,
  719. ExpLocks = [{list_to_binary(Name), Vsn}
  720. || {lock, Name, Vsn} <- Expectations],
  721. NewLocks = lists:foldl(
  722. fun({App, {pkg, Name, _}, Lvl}, Acc) ->
  723. Vsn = list_to_binary(proplists:get_value(App,ExpLocks)),
  724. [{App, {pkg, Name, Vsn}, Lvl} | Acc]
  725. ; ({App, {git, URL, {ref, _}}, Lvl}, Acc) ->
  726. Vsn = proplists:get_value(App,ExpLocks),
  727. [{App, {git, URL, {ref, Vsn}}, Lvl} | Acc]
  728. end, [], Locks),
  729. ct:pal("rewriting locks from ~p to~n~p", [Locks, NewLocks]),
  730. file:write_file(LockFile, io_lib:format("~p.~n", [NewLocks])).