Newer
Older
dub_jkp / source / dub / test / selections_from_parent_dir.d
  1. /*******************************************************************************
  2.  
  3. Test inheritable flag of selections file
  4.  
  5. Selections files can have an `inheritable` flag that is used to have
  6. a central selections file, e.g. in the case of a monorepo.
  7.  
  8. *******************************************************************************/
  9.  
  10. module dub.test.selections_from_parent_dir;
  11.  
  12. version (unittest):
  13.  
  14. import dub.test.base;
  15. import std.string : replace;
  16.  
  17. // dub.selections.json can be inherited from parent directories
  18. unittest
  19. {
  20. const pkg1Dir = TestDub.ProjectPath ~ "pkg1";
  21. const pkg2Dir = TestDub.ProjectPath ~ "pkg2";
  22. const path = TestDub.ProjectPath ~ "dub.selections.json";
  23. const dubSelectionsJsonContent = `{
  24. "fileVersion": 1,
  25. "inheritable": true,
  26. "versions": {
  27. "pkg1": {"path":"pkg1"}
  28. }
  29. }
  30. `;
  31.  
  32. scope dub = new TestDub((scope Filesystem fs) {
  33. fs.mkdir(pkg1Dir);
  34. fs.writeFile(pkg1Dir ~ "dub.sdl", `name "pkg1"
  35. targetType "none"`);
  36. fs.mkdir(pkg2Dir);
  37. fs.writeFile(pkg2Dir ~ "dub.sdl", `name "pkg2"
  38. targetType "library"
  39.  
  40. # don't specify a path, require inherited dub.selections.json to make it path-based (../pkg1)
  41. dependency "pkg1" version="*"`);
  42.  
  43. // important: dub.selections.json in *parent* directory
  44. fs.writeFile(path, dubSelectionsJsonContent);
  45. }, pkg2Dir.toNativeString()); // pkg2 is our root package
  46.  
  47. dub.loadPackage();
  48. assert(dub.project.hasAllDependencies());
  49. // the relative path should have been adjusted (`pkg1` => `../pkg1`)
  50. assert(dub.project.selections.getSelectedVersion(PackageName("pkg1")).path == NativePath("../pkg1"));
  51.  
  52. // invoking `dub upgrade` for the pkg2 root package should generate a local dub.selections.json,
  53. // leaving the inherited one untouched
  54. dub.upgrade(UpgradeOptions.select);
  55. const nestedPath = pkg2Dir ~ "dub.selections.json";
  56. assert(dub.fs.existsFile(nestedPath));
  57. assert(dub.fs.readFile(path) == dubSelectionsJsonContent,
  58. "Inherited dub.selections.json modified after dub upgrade!");
  59. const nestedContent = dub.fs.readText(nestedPath);
  60. assert(nestedContent == dubSelectionsJsonContent.replace(`{"path":"pkg1"}`, `{"path":"../pkg1"}`),
  61. "Unexpected nestedContent:\n" ~ nestedContent);
  62. }
  63.  
  64. // a non-inheritable dub.selections.json breaks the inheritance chain
  65. unittest
  66. {
  67. const root = TestDub.ProjectPath ~ "root";
  68. const root_a = root ~ "a";
  69. const root_a_b = root_a ~ "b";
  70.  
  71. scope dub_ = new TestDub((scope Filesystem fs) {
  72. // inheritable root/dub.selections.json
  73. fs.mkdir(root);
  74. fs.writeFile(root ~ "dub.selections.json", `{
  75. "fileVersion": 1,
  76. "inheritable": true,
  77. "versions": {
  78. "dub": "1.38.0"
  79. }
  80. }
  81. `);
  82. // non-inheritable root/a/dub.selections.json
  83. fs.mkdir(root_a);
  84. fs.writeFile(root_a ~ "dub.selections.json", `{
  85. "fileVersion": 1,
  86. "versions": {
  87. "dub": "1.37.0"
  88. }
  89. }
  90. `);
  91. // We need packages for `loadPackage`
  92. fs.mkdir(root_a_b);
  93. fs.writeFile(root_a_b ~ `dub.json`,
  94. `{"name":"ab","dependencies":{"dub":"~>1.0"}}`);
  95. fs.writeFile(root_a ~ `dub.json`,
  96. `{"name":"a","dependencies":{"dub":"~>1.0"}}`);
  97. fs.writeFile(root ~ `dub.json`,
  98. `{"name":"r","dependencies":{"dub":"~>1.0"}}`);
  99. fs.writePackageFile(`dub`, `1.37.0`, `{"name":"dub","version":"1.37.0"}`);
  100. fs.writePackageFile(`dub`, `1.38.0`, `{"name":"dub","version":"1.38.0"}`);
  101. });
  102.  
  103. // no selections for root/a/b/
  104. {
  105. auto dub = dub_.newTest();
  106. const result = dub.packageManager.readSelections(root_a_b);
  107. assert(result.isNull());
  108. dub.loadPackage(root_a_b);
  109. assert(!dub.project.hasAllDependencies());
  110. }
  111.  
  112. // local selections for root/a/
  113. {
  114. auto dub = dub_.newTest();
  115. const result = dub.packageManager.readSelections(root_a);
  116. assert(!result.isNull());
  117. assert(result.get().absolutePath == root_a ~ "dub.selections.json");
  118. assert(!result.get().selectionsFile.inheritable);
  119. dub.loadPackage(root_a);
  120. assert(dub.project.hasAllDependencies());
  121. assert(dub.project.dependencies()[0].name == "dub");
  122. assert(dub.project.dependencies()[0].version_ == Version("1.37.0"));
  123. }
  124.  
  125. // local selections for root/
  126. {
  127. auto dub = dub_.newTest();
  128. const result = dub.packageManager.readSelections(root);
  129. assert(!result.isNull());
  130. assert(result.get().absolutePath == root ~ "dub.selections.json");
  131. assert(result.get().selectionsFile.inheritable);
  132. dub.loadPackage(root);
  133. assert(dub.project.hasAllDependencies());
  134. assert(dub.project.dependencies()[0].name == "dub");
  135. assert(dub.project.dependencies()[0].version_ == Version("1.38.0"));
  136. }
  137.  
  138. // after removing non-inheritable root/a/dub.selections.json: inherited root selections for root/a/b/
  139. {
  140. auto dub = dub_.newTest((scope Filesystem fs) {
  141. fs.removeFile(root_a ~ "dub.selections.json");
  142. });
  143. const result = dub.packageManager.readSelections(root_a_b);
  144. assert(!result.isNull());
  145. assert(result.get().absolutePath == root ~ "dub.selections.json");
  146. assert(result.get().selectionsFile.inheritable);
  147. dub.loadPackage(root_a_b);
  148. assert(dub.project.hasAllDependencies());
  149. assert(dub.project.dependencies()[0].name == "dub");
  150. assert(dub.project.dependencies()[0].version_ == Version("1.38.0"));
  151. }
  152. }