25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

599 lines
20 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_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_ac) ->
  318. {[{"A", "1", [{"D",[{"J",[]}]},
  319. {"E",[{"I","1",[]}]}]},
  320. {"B", "1", [{"F",[]},
  321. {"G",[]}]},
  322. {"C", "1", [{"H",[]},
  323. {"I","2",[]}]}
  324. ],
  325. [{"A", "1", [{"D",[{"J",[]}]},
  326. {"E",[{"I","1",[]}]}]},
  327. {"B", "1", [{"F",[]},
  328. {"G",[]}]},
  329. {"C", "1", [{"H",[]}]}
  330. ],
  331. ["C","I"],
  332. {"C, A", [{"A","1"}, "D", "J", "E", {"I","1"},
  333. {"B","1"}, "F", "G",
  334. {"C","1"}, "H"]}};
  335. upgrades(tree_all) ->
  336. {[{"A", "1", [{"D",[{"J",[]}]},
  337. {"E",[{"I","1",[]}]}]},
  338. {"B", "1", [{"F",[]},
  339. {"G",[]}]},
  340. {"C", "1", [{"H",[]},
  341. {"I","2",[]}]}
  342. ],
  343. [{"A", "1", [{"D",[{"J",[]}]},
  344. {"E",[{"I","1",[]}]}]},
  345. {"B", "1", [{"F",[]},
  346. {"G",[]}]},
  347. {"C", "1", [{"H",[]}]}
  348. ],
  349. ["C","I"],
  350. {"", [{"A","1"}, "D", "J", "E", {"I","1"},
  351. {"B","1"}, "F", "G",
  352. {"C","1"}, "H"]}};
  353. upgrades(delete_d) ->
  354. {[{"A", "1", [{"B", [{"D", "1", []}]},
  355. {"C", [{"D", "2", []}]}]}
  356. ],
  357. [{"A", "2", [{"B", []},
  358. {"C", []}]}
  359. ],
  360. ["A","B", "C"],
  361. %% upgrade vs. new tree
  362. {"", [{"A","2"}, "B", "C"]}};
  363. upgrades(promote) ->
  364. {[{"A", "1", [{"C", "1", []}]},
  365. {"B", "1", [{"D", "1", []}]}
  366. ],
  367. [{"A", "2", [{"C", "2", []}]},
  368. {"B", "2", [{"D", "2", []}]},
  369. {"C", "3", []}
  370. ],
  371. ["A","B","C","D"],
  372. {"C", [{"A","1"},{"C","3"},{"B","1"},{"D","1"}]}};
  373. upgrades(stable_lock) ->
  374. {[{"A", "1", [{"C", "1", []}]},
  375. {"B", "1", [{"D", "1", []}]}
  376. ], % lock after this
  377. [{"A", "2", [{"C", "2", []}]},
  378. {"B", "2", [{"D", "2", []}]}
  379. ],
  380. [],
  381. %% Run a regular lock and no app should be upgraded
  382. {"any", [{"A","1"},{"C","1"},{"B","1"},{"D","1"}]}};
  383. upgrades(fwd_lock) ->
  384. {[{"A", "1", [{"C", "1", []}]},
  385. {"B", "1", [{"D", "1", []}]}
  386. ],
  387. [{"A", "2", [{"C", "2", []}]},
  388. {"B", "2", [{"D", "2", []}]}
  389. ],
  390. ["A","B","C","D"],
  391. %% For this one, we should build, rewrite the lock
  392. %% file to include the result post-upgrade, and then
  393. %% run a regular lock to see that the lock file is respected
  394. %% in deps.
  395. {"any", [{"A","2"},{"C","2"},{"B","2"},{"D","2"}]}};
  396. upgrades(compile_upgrade_parity) ->
  397. {[{"A", "1", [{"D",[{"J",[]}]},
  398. {"E",[{"I","1",[]}]}]},
  399. {"B", "1", [{"F",[]},
  400. {"G",[]}]},
  401. {"C", "1", [{"H",[]},
  402. {"I","2",[]}]}
  403. ],
  404. [],
  405. [],
  406. {"", [{"A","1"}, "D", "J", "E", {"I","1"},
  407. {"B","1"}, "F", "G",
  408. {"C","1"}, "H"]}}.
  409. %% TODO: add a test that verifies that unlocking files and then
  410. %% running the upgrade code is enough to properly upgrade things.
  411. mock_deps(git, Deps, Upgrades) ->
  412. catch mock_git_resource:unmock(),
  413. {SrcDeps, _} = rebar_test_utils:flat_deps(Deps),
  414. mock_git_resource:mock([{deps, SrcDeps}, {upgrade, Upgrades}]);
  415. mock_deps(pkg, Deps, Upgrades) ->
  416. catch mock_pkg_resource:unmock(),
  417. {_, PkgDeps} = rebar_test_utils:flat_deps(Deps),
  418. mock_pkg_resource:mock([{pkgdeps, PkgDeps}, {upgrade, Upgrades}]).
  419. mock_deps(git, OldDeps, Deps, Upgrades) ->
  420. catch mock_git_resource:unmock(),
  421. {SrcDeps, _} = rebar_test_utils:flat_deps(Deps++OldDeps),
  422. mock_git_resource:mock([{deps, SrcDeps}, {upgrade, Upgrades}]);
  423. mock_deps(pkg, OldDeps, Deps, Upgrades) ->
  424. catch mock_pkg_resource:unmock(),
  425. {_, PkgDeps} = rebar_test_utils:flat_deps(Deps++OldDeps),
  426. mock_pkg_resource:mock([{pkgdeps, PkgDeps}, {upgrade, Upgrades}]).
  427. normalize_unlocks({App, Locks}) ->
  428. {iolist_to_binary(App),
  429. normalize_unlocks_expect(Locks)};
  430. normalize_unlocks({App, Vsn, Locks}) ->
  431. {iolist_to_binary(App), iolist_to_binary(Vsn),
  432. normalize_unlocks_expect(Locks)}.
  433. normalize_unlocks_expect({error, Reason}) ->
  434. {error, Reason};
  435. normalize_unlocks_expect([]) ->
  436. [];
  437. normalize_unlocks_expect([{App,Vsn} | Rest]) ->
  438. [{dep, App, Vsn},
  439. {lock, App, Vsn}
  440. | normalize_unlocks_expect(Rest)];
  441. normalize_unlocks_expect([App | Rest]) ->
  442. [{dep, App},
  443. {lock, App} | normalize_unlocks_expect(Rest)].
  444. top_a(Config) -> run(Config).
  445. top_b(Config) -> run(Config).
  446. top_c(Config) -> run(Config).
  447. top_d1(Config) -> run(Config).
  448. top_d2(Config) -> run(Config).
  449. top_e(Config) -> run(Config).
  450. pair_a(Config) -> run(Config).
  451. pair_b(Config) -> run(Config).
  452. pair_ab(Config) -> run(Config).
  453. pair_c(Config) -> run(Config).
  454. pair_all(Config) -> run(Config).
  455. triplet_a(Config) -> run(Config).
  456. triplet_b(Config) -> run(Config).
  457. triplet_c(Config) -> run(Config).
  458. tree_a(Config) -> run(Config).
  459. tree_b(Config) -> run(Config).
  460. tree_c(Config) -> run(Config).
  461. tree_c2(Config) -> run(Config).
  462. tree_ac(Config) -> run(Config).
  463. tree_all(Config) -> run(Config).
  464. promote(Config) -> run(Config).
  465. delete_d(Config) ->
  466. meck:new(rebar_log, [no_link, passthrough]),
  467. run(Config),
  468. Infos = [{Str, Args}
  469. || {_, {rebar_log, log, [info, Str, Args]}, _} <- meck:history(rebar_log)],
  470. meck:unload(rebar_log),
  471. ?assertNotEqual([],
  472. [1 || {"App ~ts is no longer needed and can be deleted.",
  473. [<<"D">>]} <- Infos]).
  474. stable_lock(Config) ->
  475. apply(?config(mock, Config), []),
  476. {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)),
  477. %% Install dependencies before re-mocking for an upgrade
  478. rebar_test_utils:run_and_check(Config, RebarConfig, ["lock"], {ok, []}),
  479. {App, Unlocks} = ?config(expected, Config),
  480. ct:pal("Upgrades: ~p -> ~p", [App, Unlocks]),
  481. Expectation = case Unlocks of
  482. {error, Term} -> {error, Term};
  483. _ -> {ok, Unlocks}
  484. end,
  485. apply(?config(mock_update, Config), []),
  486. NewRebarConf = rebar_test_utils:create_config(?config(apps, Config),
  487. [{deps, ?config(next_top_deps, Config)}]),
  488. {ok, NewRebarConfig} = file:consult(NewRebarConf),
  489. rebar_test_utils:run_and_check(
  490. Config, NewRebarConfig, ["lock", App], Expectation
  491. ).
  492. fwd_lock(Config) ->
  493. apply(?config(mock, Config), []),
  494. {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)),
  495. %% Install dependencies before re-mocking for an upgrade
  496. rebar_test_utils:run_and_check(Config, RebarConfig, ["lock"], {ok, []}),
  497. {App, Unlocks} = ?config(expected, Config),
  498. ct:pal("Upgrades: ~p -> ~p", [App, Unlocks]),
  499. Expectation = case Unlocks of
  500. {error, Term} -> {error, Term};
  501. _ -> {ok, Unlocks}
  502. end,
  503. rewrite_locks(Expectation, Config),
  504. apply(?config(mock_update, Config), []),
  505. NewRebarConf = rebar_test_utils:create_config(?config(apps, Config),
  506. [{deps, ?config(next_top_deps, Config)}]),
  507. {ok, NewRebarConfig} = file:consult(NewRebarConf),
  508. rebar_test_utils:run_and_check(
  509. Config, NewRebarConfig, ["lock", App], Expectation
  510. ).
  511. compile_upgrade_parity(Config) ->
  512. AppDir = ?config(apps, Config),
  513. apply(?config(mock, Config), []),
  514. {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)),
  515. %% compiling and upgrading should generate the same lockfiles when
  516. %% deps are identical
  517. Lockfile = filename:join([AppDir, "rebar.lock"]),
  518. rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, []}),
  519. {ok, CompileLockData1} = file:read_file(Lockfile),
  520. rebar_test_utils:run_and_check(Config, RebarConfig, ["upgrade"], {ok, []}),
  521. {ok, UpgradeLockData} = file:read_file(Lockfile),
  522. rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, []}),
  523. {ok, CompileLockData2} = file:read_file(Lockfile),
  524. ?assertEqual(CompileLockData1, CompileLockData2),
  525. ?assertEqual(CompileLockData1, UpgradeLockData).
  526. run(Config) ->
  527. apply(?config(mock, Config), []),
  528. {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)),
  529. %% Install dependencies before re-mocking for an upgrade
  530. rebar_test_utils:run_and_check(Config, RebarConfig, ["lock"], {ok, []}),
  531. {App, Unlocks} = ?config(expected, Config),
  532. ct:pal("Upgrades: ~p -> ~p", [App, Unlocks]),
  533. Expectation = case Unlocks of
  534. {error, Term} -> {error, Term};
  535. _ -> {ok, Unlocks}
  536. end,
  537. apply(?config(mock_update, Config), []),
  538. NewRebarConf = rebar_test_utils:create_config(?config(apps, Config),
  539. [{deps, ?config(next_top_deps, Config)}]),
  540. {ok, NewRebarConfig} = file:consult(NewRebarConf),
  541. rebar_test_utils:run_and_check(
  542. Config, NewRebarConfig, ["upgrade", App], Expectation
  543. ).
  544. novsn_pkg(Config) ->
  545. apply(?config(mock, Config), []),
  546. {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)),
  547. %% Install dependencies before re-mocking for an upgrade
  548. rebar_test_utils:run_and_check(Config, RebarConfig, ["lock"], {ok, []}),
  549. Expectation = ?config(expected, Config),
  550. apply(?config(mock_update, Config), []),
  551. rebar_test_utils:run_and_check(
  552. Config, RebarConfig, ["upgrade"], Expectation
  553. ),
  554. ok.
  555. rewrite_locks({ok, Expectations}, Config) ->
  556. AppDir = ?config(apps, Config),
  557. LockFile = filename:join([AppDir, "rebar.lock"]),
  558. {ok, [Locks]} = file:consult(LockFile),
  559. ExpLocks = [{list_to_binary(Name), Vsn}
  560. || {lock, Name, Vsn} <- Expectations],
  561. NewLocks = lists:foldl(
  562. fun({App, {pkg, Name, _}, Lvl}, Acc) ->
  563. Vsn = list_to_binary(proplists:get_value(App,ExpLocks)),
  564. [{App, {pkg, Name, Vsn}, Lvl} | Acc]
  565. ; ({App, {git, URL, {ref, _}}, Lvl}, Acc) ->
  566. Vsn = proplists:get_value(App,ExpLocks),
  567. [{App, {git, URL, {ref, Vsn}}, Lvl} | Acc]
  568. end, [], Locks),
  569. ct:pal("rewriting locks from ~p to~n~p", [Locks, NewLocks]),
  570. file:write_file(LockFile, io_lib:format("~p.~n", [NewLocks])).