Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.

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