| 1 | // vtest build: !musl? && !sanitized_job? |
| 2 | // vtest retry: 3 |
| 3 | module main |
| 4 | |
| 5 | import os |
| 6 | import rand |
| 7 | import v.vmod |
| 8 | import test_utils { cmd_fail, cmd_ok } |
| 9 | |
| 10 | // Running tests appends a tsession path to VTMP, which is automatically cleaned up after the test. |
| 11 | // The following will result in e.g. `$VTMP/tsession_7fe8e93bd740_1612958707536/test-vmodules/`. |
| 12 | const test_path = os.join_path(os.vtmp_dir(), 'vpm_install_test_${rand.ulid()}') |
| 13 | |
| 14 | fn testsuite_begin() { |
| 15 | $if !network ? { |
| 16 | eprintln('> skipping ${@FILE}, when `-d network` is missing') |
| 17 | exit(0) |
| 18 | } |
| 19 | dump(test_path) |
| 20 | test_utils.set_test_env(test_path) |
| 21 | } |
| 22 | |
| 23 | fn testsuite_end() { |
| 24 | os.rmdir_all(test_path) or {} |
| 25 | } |
| 26 | |
| 27 | fn get_vmod(path string) vmod.Manifest { |
| 28 | return vmod.from_file(os.join_path(test_path, path, 'v.mod')) or { |
| 29 | eprintln('Failed to parse v.mod for `${path}`. ${err}') |
| 30 | exit(1) |
| 31 | } |
| 32 | } |
| 33 | |
| 34 | fn test_install_from_vpm_ident() { |
| 35 | res := cmd_ok(@LOCATION, '${vexe} install nedpals.args') |
| 36 | assert res.output.contains('Skipping download count increment for `nedpals.args`.'), res.output |
| 37 | manifest := get_vmod(os.join_path('nedpals', 'args')) |
| 38 | assert manifest.name == 'nedpals.args' |
| 39 | assert manifest.dependencies == []string{} |
| 40 | } |
| 41 | |
| 42 | fn test_install_from_vpm_short_ident() { |
| 43 | cmd_ok(@LOCATION, '${vexe} install pcre') |
| 44 | manifest := get_vmod('pcre') |
| 45 | assert manifest.name == 'pcre' |
| 46 | assert manifest.description == 'A simple regex library for V.' |
| 47 | } |
| 48 | |
| 49 | fn test_install_from_git_url() { |
| 50 | mut res := cmd_ok(@LOCATION, '${vexe} install https://github.com/vlang/markdown') |
| 51 | assert res.output.contains('Installing `markdown`'), res.output |
| 52 | mut manifest := get_vmod('markdown') |
| 53 | assert manifest.name == 'markdown' |
| 54 | assert manifest.dependencies == []string{} |
| 55 | res = cmd_ok(@LOCATION, '${vexe} install http://github.com/Wertzui123/HashMap') |
| 56 | assert res.output.contains('Installing `HashMap`'), res.output |
| 57 | assert res.output.contains('`http` is deprecated'), res.output |
| 58 | manifest = get_vmod(os.join_path('wertzui123', 'hashmap')) |
| 59 | res = cmd_ok(@LOCATION, '${vexe} install http://github.com/Wertzui123/HashMap') |
| 60 | assert res.output.contains('Updating module `wertzui123.hashmap`'), res.output |
| 61 | assert res.output.contains('`http` is deprecated'), res.output |
| 62 | res = cmd_ok(@LOCATION, '${vexe} install https://gitlab.com/tobealive/webview') |
| 63 | assert res.output.contains('Installed `webview`'), res.output |
| 64 | } |
| 65 | |
| 66 | fn test_install_from_git_url_uses_registered_package_name() { |
| 67 | mut res := cmd_ok(@LOCATION, '${vexe} install https://github.com/nedpals/v-args') |
| 68 | assert res.output.contains('Installing `nedpals.args`'), res.output |
| 69 | assert res.output.contains('Installed `nedpals.args`'), res.output |
| 70 | mut manifest := get_vmod(os.join_path('nedpals', 'args')) |
| 71 | assert manifest.name == 'nedpals.args' |
| 72 | |
| 73 | res = cmd_ok(@LOCATION, '${vexe} install https://github.com/nedpals/v-args') |
| 74 | assert res.output.contains('Updating module `nedpals.args`'), res.output |
| 75 | manifest = get_vmod(os.join_path('nedpals', 'args')) |
| 76 | assert manifest.name == 'nedpals.args' |
| 77 | } |
| 78 | |
| 79 | fn test_install_already_existent() { |
| 80 | mut res := cmd_ok(@LOCATION, '${vexe} install https://github.com/vlang/markdown') |
| 81 | assert res.output.contains('Updating module `markdown`'), res.output |
| 82 | manifest := get_vmod('markdown') |
| 83 | assert manifest.name == 'markdown' |
| 84 | assert manifest.dependencies == []string{} |
| 85 | // The same module but with the `.git` extension added. |
| 86 | res = cmd_ok(@LOCATION, '${vexe} install https://github.com/vlang/markdown.git') |
| 87 | assert res.output.contains('Updating module `markdown`'), res.output |
| 88 | } |
| 89 | |
| 90 | fn test_install_once() { |
| 91 | // Start with a clean test path. |
| 92 | rmdir_all(test_path) or {} |
| 93 | os.mkdir_all(test_path) or {} |
| 94 | |
| 95 | // Install markdown module. |
| 96 | mut res := cmd_ok(@LOCATION, '${vexe} install markdown') |
| 97 | // Keep track of the last modified state of the v.mod file of the installed markdown module. |
| 98 | md_last_modified := os.file_last_mod_unix(os.join_path(test_path, 'markdown', 'v.mod')) |
| 99 | |
| 100 | install_cmd := '${@VEXE} install https://github.com/vlang/markdown https://github.com/vlang/pcre --once -v' |
| 101 | // Try installing two modules, one of which is already installed. |
| 102 | res = cmd_ok(@LOCATION, install_cmd) |
| 103 | assert res.output.contains("Already installed modules: ['markdown']"), res.output |
| 104 | manifest := get_vmod('pcre') |
| 105 | assert manifest.name == 'pcre' |
| 106 | assert manifest.description == 'A simple regex library for V.' |
| 107 | // Ensure the before installed markdown module wasn't modified. |
| 108 | assert md_last_modified == os.file_last_mod_unix(os.join_path(test_path, 'markdown', 'v.mod')) |
| 109 | |
| 110 | // Try installing two modules that are both already installed. |
| 111 | res = cmd_ok(@LOCATION, install_cmd) |
| 112 | assert res.output.contains('All modules are already installed.'), res.output |
| 113 | assert md_last_modified == os.file_last_mod_unix(os.join_path(test_path, 'markdown', 'v.mod')) |
| 114 | } |
| 115 | |
| 116 | fn test_missing_repo_name_in_url() { |
| 117 | incomplete_url := 'https://github.com/vlang' |
| 118 | res := cmd_fail(@LOCATION, '${vexe} install ${incomplete_url}') |
| 119 | assert res.output.contains('failed to retrieve module name for `${incomplete_url}`'), res.output |
| 120 | } |
| 121 | |
| 122 | fn test_manifest_detection() { |
| 123 | mut res := cmd_fail(@LOCATION, '${vexe} install https://github.com/octocat/octocat.github.io') |
| 124 | assert res.output.contains('failed to find `v.mod` for `https://github.com/octocat/octocat.github.io`'), res.output |
| 125 | // No error for vpm modules yet. |
| 126 | res = cmd_ok(@LOCATION, '${vexe} install spytheman.regex') |
| 127 | assert res.output.contains('`spytheman.regex` is missing a manifest file'), res.output |
| 128 | assert res.output.contains('Installing `spytheman.regex`'), res.output |
| 129 | } |
| 130 | |
| 131 | fn test_install_potentially_conflicting() { |
| 132 | mut res := os.execute('${vexe} install ui') |
| 133 | assert res.output.contains('Installed `ui`') |
| 134 | mut manifest := get_vmod('ui') |
| 135 | assert manifest.name == 'ui' |
| 136 | res = os.execute('${vexe} install https://github.com/isaiahpatton/ui') |
| 137 | // The VPM registry maps `github.com/isaiahPatton/ui` (whose manifest is |
| 138 | // named `iui`) to the registered name `IsaiahPatton.iui`, so the install |
| 139 | // now uses the registered name and the publisher-prefixed path. |
| 140 | assert res.output.contains('Installed `IsaiahPatton.iui`'), res.output |
| 141 | manifest = get_vmod(os.join_path('isaiahpatton', 'iui')) |
| 142 | assert manifest.name == 'iui' |
| 143 | } |
| 144 | |
| 145 | fn test_get_installed_version() { |
| 146 | test_project_path := os.join_path(test_path, 'test_project') |
| 147 | // Force the initial branch name; CI ships with git's traditional `master` |
| 148 | // default, but newer git installs (and many dev machines) default to |
| 149 | // `main`, which makes the `git branch -D master` step below fail. |
| 150 | mut res := cmd_ok(@LOCATION, 'git init -b master ${test_project_path}') |
| 151 | os.chdir(test_project_path)! |
| 152 | if os.execute('git config user.name').exit_code == 1 { |
| 153 | os.execute_or_exit('git config user.email "[email protected]"') |
| 154 | os.execute_or_exit('git config user.name "V CI"') |
| 155 | } |
| 156 | os.write_file('v.mod', '')! |
| 157 | res = cmd_ok(@LOCATION, 'git add .') |
| 158 | res = cmd_ok(@LOCATION, 'git commit -m "initial commit"') |
| 159 | mut mod := Module{ |
| 160 | install_path: test_project_path |
| 161 | } |
| 162 | mod.get_installed() |
| 163 | assert mod.is_installed |
| 164 | assert mod.installed_version == '' |
| 165 | |
| 166 | // Create a tag -> latests commit and tag are at the same state, |
| 167 | // but it should not be treated as a version installation, when there is another head branch. |
| 168 | res = |
| 169 | cmd_ok(@LOCATION, 'git tag v0.1.0 -m "some tag message"') // note: without a tag message, git will try to start an editor when you run this test locally, which will block |
| 170 | mod.is_installed = false |
| 171 | mod.get_installed() |
| 172 | assert mod.is_installed |
| 173 | assert mod.installed_version == '' |
| 174 | |
| 175 | cmd_ok(@LOCATION, 'git checkout v0.1.0') |
| 176 | mod.is_installed = false |
| 177 | mod.get_installed() |
| 178 | assert mod.is_installed |
| 179 | assert mod.installed_version == '' |
| 180 | |
| 181 | cmd_ok(@LOCATION, 'git branch -D master') |
| 182 | cmd_ok(@LOCATION, 'git reset --hard v0.1.0') |
| 183 | mod.is_installed = false |
| 184 | mod.get_installed() |
| 185 | assert mod.is_installed |
| 186 | assert mod.installed_version == 'v0.1.0' |
| 187 | } |
| 188 | |
| 189 | fn test_install_from_hg_url() ! { |
| 190 | hg_path := os.find_abs_path_of_executable('hg') or { |
| 191 | eprintln('skipping test, since `hg` is not executable.') |
| 192 | return |
| 193 | } |
| 194 | test_module_path := os.join_path(os.temp_dir(), rand.ulid(), 'hg_test_module') |
| 195 | defer { |
| 196 | os.rmdir_all(test_module_path) or {} |
| 197 | } |
| 198 | // Initialize project without manifest file. |
| 199 | mut res := cmd_ok(@LOCATION, 'hg init ${test_module_path}') |
| 200 | |
| 201 | println('> writing .hg/hgrc to the new mercurial repo ...') |
| 202 | os.mkdir_all(os.join_path(test_module_path, '.hg'))! |
| 203 | os.write_file(os.join_path(test_module_path, '.hg/hgrc'), |
| 204 | '[ui]\nusername = v_ci <[email protected]>\nverbose = False\n')! |
| 205 | println('> writing .hg/hgrc done.') |
| 206 | |
| 207 | mut p, mut port := test_utils.hg_serve(hg_path, test_module_path, 2000) |
| 208 | // Trying to install it should fail. |
| 209 | res = os.execute('${vexe} install --hg http://127.0.0.1:${port}') |
| 210 | p.signal_kill() |
| 211 | assert res.output.contains('failed to find `v.mod`'), res.output |
| 212 | // Create and commit manifest. |
| 213 | name := 'my_awesome_v_module' |
| 214 | version := '1.0.0' |
| 215 | os.write_file(os.join_path(test_module_path, 'v.mod'), "Module{ |
| 216 | name: '${name}' |
| 217 | version: '${version}' |
| 218 | }")! |
| 219 | os.chdir(test_module_path)! |
| 220 | cmd_ok(@LOCATION, 'hg add') |
| 221 | cmd_ok(@LOCATION, 'hg commit -m "add v.mod"') |
| 222 | p, port = test_utils.hg_serve(hg_path, test_module_path, 3000) |
| 223 | // Trying to install the module should work now. |
| 224 | res = cmd_ok(@LOCATION, '${vexe} install --hg http://127.0.0.1:${port}') |
| 225 | p.signal_kill() |
| 226 | // Get manifest from the vmodules directory. |
| 227 | manifest := get_vmod(name) |
| 228 | assert manifest.name == name |
| 229 | assert manifest.version == version |
| 230 | } |
| 231 | |