summaryrefslogtreecommitdiffstats
path: root/src/cmd/go/testdata/script
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/go/testdata/script')
-rw-r--r--src/cmd/go/testdata/script/README425
-rw-r--r--src/cmd/go/testdata/script/autocgo.txt29
-rw-r--r--src/cmd/go/testdata/script/badgo.txt50
-rw-r--r--src/cmd/go/testdata/script/bug.txt58
-rw-r--r--src/cmd/go/testdata/script/build_GOTMPDIR.txt50
-rw-r--r--src/cmd/go/testdata/script/build_acl_windows.txt44
-rw-r--r--src/cmd/go/testdata/script/build_arm.txt13
-rw-r--r--src/cmd/go/testdata/script/build_buildvcs_auto.txt91
-rw-r--r--src/cmd/go/testdata/script/build_cache_arch_mode.txt21
-rw-r--r--src/cmd/go/testdata/script/build_cache_compile.txt21
-rw-r--r--src/cmd/go/testdata/script/build_cache_disabled.txt50
-rw-r--r--src/cmd/go/testdata/script/build_cache_gomips.txt40
-rw-r--r--src/cmd/go/testdata/script/build_cache_link.txt26
-rw-r--r--src/cmd/go/testdata/script/build_cache_output.txt67
-rw-r--r--src/cmd/go/testdata/script/build_cache_trimpath.txt47
-rw-r--r--src/cmd/go/testdata/script/build_cc_cache_issue64423.txt121
-rw-r--r--src/cmd/go/testdata/script/build_cd_gopath_different.txt73
-rw-r--r--src/cmd/go/testdata/script/build_cgo_consistent_results.txt23
-rw-r--r--src/cmd/go/testdata/script/build_cgo_error.txt17
-rw-r--r--src/cmd/go/testdata/script/build_concurrent_backend.txt10
-rw-r--r--src/cmd/go/testdata/script/build_cwd_newline.txt138
-rw-r--r--src/cmd/go/testdata/script/build_darwin_cc_arch.txt24
-rw-r--r--src/cmd/go/testdata/script/build_dash_n_cgo.txt18
-rw-r--r--src/cmd/go/testdata/script/build_dash_o_dev_null.txt13
-rw-r--r--src/cmd/go/testdata/script/build_dash_x.txt48
-rw-r--r--src/cmd/go/testdata/script/build_exe.txt25
-rw-r--r--src/cmd/go/testdata/script/build_gcflags.txt22
-rw-r--r--src/cmd/go/testdata/script/build_gcflags_order.txt22
-rw-r--r--src/cmd/go/testdata/script/build_gopath_order.txt36
-rw-r--r--src/cmd/go/testdata/script/build_ignore_leading_bom.txt27
-rw-r--r--src/cmd/go/testdata/script/build_import_comment.txt68
-rw-r--r--src/cmd/go/testdata/script/build_import_cycle.txt13
-rw-r--r--src/cmd/go/testdata/script/build_internal.txt65
-rw-r--r--src/cmd/go/testdata/script/build_issue48319.txt46
-rw-r--r--src/cmd/go/testdata/script/build_issue59571.txt40
-rw-r--r--src/cmd/go/testdata/script/build_issue62156.txt27
-rw-r--r--src/cmd/go/testdata/script/build_issue6480.txt128
-rw-r--r--src/cmd/go/testdata/script/build_issue_65528.txt9
-rw-r--r--src/cmd/go/testdata/script/build_link_x_import_path_escape.txt22
-rw-r--r--src/cmd/go/testdata/script/build_multi_main.txt43
-rw-r--r--src/cmd/go/testdata/script/build_n_cgo.txt18
-rw-r--r--src/cmd/go/testdata/script/build_negative_p.txt5
-rw-r--r--src/cmd/go/testdata/script/build_no_go.txt41
-rw-r--r--src/cmd/go/testdata/script/build_nocache.txt40
-rw-r--r--src/cmd/go/testdata/script/build_output.txt117
-rw-r--r--src/cmd/go/testdata/script/build_overlay.txt313
-rw-r--r--src/cmd/go/testdata/script/build_patterns_outside_gopath.txt36
-rw-r--r--src/cmd/go/testdata/script/build_pgo.txt74
-rw-r--r--src/cmd/go/testdata/script/build_pgo_auto.txt97
-rw-r--r--src/cmd/go/testdata/script/build_pgo_auto_multi.txt109
-rw-r--r--src/cmd/go/testdata/script/build_pie_race.txt30
-rw-r--r--src/cmd/go/testdata/script/build_plugin_non_main.txt13
-rw-r--r--src/cmd/go/testdata/script/build_plugin_reproducible.txt11
-rw-r--r--src/cmd/go/testdata/script/build_relative_pkgdir.txt9
-rw-r--r--src/cmd/go/testdata/script/build_relative_tmpdir.txt18
-rw-r--r--src/cmd/go/testdata/script/build_runtime_gcflags.txt11
-rw-r--r--src/cmd/go/testdata/script/build_shorten_pkg.txt81
-rw-r--r--src/cmd/go/testdata/script/build_single_error.txt18
-rw-r--r--src/cmd/go/testdata/script/build_static.txt44
-rw-r--r--src/cmd/go/testdata/script/build_tag_goexperiment.txt31
-rw-r--r--src/cmd/go/testdata/script/build_tags_no_comma.txt4
-rw-r--r--src/cmd/go/testdata/script/build_test_only.txt19
-rw-r--r--src/cmd/go/testdata/script/build_trimpath.txt164
-rw-r--r--src/cmd/go/testdata/script/build_trimpath_cgo.txt184
-rw-r--r--src/cmd/go/testdata/script/build_trimpath_goroot.txt103
-rw-r--r--src/cmd/go/testdata/script/build_unsupported_goos.txt6
-rw-r--r--src/cmd/go/testdata/script/build_vendor.txt42
-rw-r--r--src/cmd/go/testdata/script/cache_unix.txt37
-rw-r--r--src/cmd/go/testdata/script/cache_vet.txt22
-rw-r--r--src/cmd/go/testdata/script/cgo_asm_error.txt25
-rw-r--r--src/cmd/go/testdata/script/cgo_bad_directives.txt129
-rw-r--r--src/cmd/go/testdata/script/cgo_badmethod_issue57926.txt31
-rw-r--r--src/cmd/go/testdata/script/cgo_depends_on_syscall.txt15
-rw-r--r--src/cmd/go/testdata/script/cgo_flag_contains_space.txt16
-rw-r--r--src/cmd/go/testdata/script/cgo_path.txt41
-rw-r--r--src/cmd/go/testdata/script/cgo_path_space.txt56
-rw-r--r--src/cmd/go/testdata/script/cgo_path_space_quote.txt58
-rw-r--r--src/cmd/go/testdata/script/cgo_stale.txt39
-rw-r--r--src/cmd/go/testdata/script/cgo_stale_precompiled.txt40
-rw-r--r--src/cmd/go/testdata/script/cgo_suspect_flag_force_external.txt201
-rw-r--r--src/cmd/go/testdata/script/cgo_syso_issue29253.txt31
-rw-r--r--src/cmd/go/testdata/script/cgo_trimpath_macro.txt71
-rw-r--r--src/cmd/go/testdata/script/cgo_undef.txt68
-rw-r--r--src/cmd/go/testdata/script/chdir.txt35
-rw-r--r--src/cmd/go/testdata/script/check_goexperiment.txt10
-rw-r--r--src/cmd/go/testdata/script/clean_binary.txt78
-rw-r--r--src/cmd/go/testdata/script/clean_cache_n.txt28
-rw-r--r--src/cmd/go/testdata/script/clean_testcache.txt28
-rw-r--r--src/cmd/go/testdata/script/cmd_import_error.txt16
-rw-r--r--src/cmd/go/testdata/script/cover_asm.txt33
-rw-r--r--src/cmd/go/testdata/script/cover_atomic_pkgall.txt25
-rw-r--r--src/cmd/go/testdata/script/cover_blank_func_decl.txt35
-rw-r--r--src/cmd/go/testdata/script/cover_build_cmdline_pkgs.txt73
-rw-r--r--src/cmd/go/testdata/script/cover_build_pkg_select.txt114
-rw-r--r--src/cmd/go/testdata/script/cover_build_simple.txt149
-rw-r--r--src/cmd/go/testdata/script/cover_cgo.txt42
-rw-r--r--src/cmd/go/testdata/script/cover_cgo_extra_file.txt48
-rw-r--r--src/cmd/go/testdata/script/cover_cgo_extra_test.txt49
-rw-r--r--src/cmd/go/testdata/script/cover_cgo_xtest.txt45
-rw-r--r--src/cmd/go/testdata/script/cover_coverpkg_partial.txt141
-rw-r--r--src/cmd/go/testdata/script/cover_coverpkg_with_init.txt130
-rw-r--r--src/cmd/go/testdata/script/cover_coverprofile_multipkg.txt193
-rw-r--r--src/cmd/go/testdata/script/cover_dash_c.txt31
-rw-r--r--src/cmd/go/testdata/script/cover_dep_loop.txt36
-rw-r--r--src/cmd/go/testdata/script/cover_dot_import.txt29
-rw-r--r--src/cmd/go/testdata/script/cover_error.txt45
-rw-r--r--src/cmd/go/testdata/script/cover_import_main_loop.txt26
-rw-r--r--src/cmd/go/testdata/script/cover_list.txt65
-rw-r--r--src/cmd/go/testdata/script/cover_main_import_path.txt55
-rw-r--r--src/cmd/go/testdata/script/cover_mod_empty.txt9
-rw-r--r--src/cmd/go/testdata/script/cover_modes.txt25
-rw-r--r--src/cmd/go/testdata/script/cover_pattern.txt41
-rw-r--r--src/cmd/go/testdata/script/cover_pkgall_imports.txt48
-rw-r--r--src/cmd/go/testdata/script/cover_pkgall_multiple_mains.txt46
-rw-r--r--src/cmd/go/testdata/script/cover_pkgall_runtime.txt23
-rw-r--r--src/cmd/go/testdata/script/cover_runs.txt13
-rw-r--r--src/cmd/go/testdata/script/cover_statements.txt96
-rw-r--r--src/cmd/go/testdata/script/cover_swig.txt72
-rw-r--r--src/cmd/go/testdata/script/cover_sync_atomic_import.txt44
-rw-r--r--src/cmd/go/testdata/script/cover_test_localpkg_filepath.txt40
-rw-r--r--src/cmd/go/testdata/script/cover_test_pkgselect.txt80
-rw-r--r--src/cmd/go/testdata/script/cover_test_race_issue56370.txt54
-rw-r--r--src/cmd/go/testdata/script/cover_var_init_order.txt55
-rw-r--r--src/cmd/go/testdata/script/cpu_profile_twice.txt22
-rw-r--r--src/cmd/go/testdata/script/devnull.txt26
-rw-r--r--src/cmd/go/testdata/script/dist_list_missing.txt57
-rw-r--r--src/cmd/go/testdata/script/doc.txt75
-rw-r--r--src/cmd/go/testdata/script/embed.txt130
-rw-r--r--src/cmd/go/testdata/script/embed_brackets.txt18
-rw-r--r--src/cmd/go/testdata/script/embed_fmt.txt22
-rw-r--r--src/cmd/go/testdata/script/env_cache.txt5
-rw-r--r--src/cmd/go/testdata/script/env_cross_build.txt29
-rw-r--r--src/cmd/go/testdata/script/env_exp.txt17
-rw-r--r--src/cmd/go/testdata/script/env_issue46807.txt12
-rw-r--r--src/cmd/go/testdata/script/env_sanitize.txt5
-rw-r--r--src/cmd/go/testdata/script/env_unset.txt30
-rw-r--r--src/cmd/go/testdata/script/env_write.txt206
-rw-r--r--src/cmd/go/testdata/script/fileline.txt8
-rw-r--r--src/cmd/go/testdata/script/fmt_load_errors.txt38
-rw-r--r--src/cmd/go/testdata/script/fsys_walk.txt6
-rw-r--r--src/cmd/go/testdata/script/gccgo_link_c.txt20
-rw-r--r--src/cmd/go/testdata/script/gccgo_link_ldflags.txt23
-rw-r--r--src/cmd/go/testdata/script/gccgo_m.txt20
-rw-r--r--src/cmd/go/testdata/script/gccgo_mangle.txt15
-rw-r--r--src/cmd/go/testdata/script/gcflags_patterns.txt93
-rw-r--r--src/cmd/go/testdata/script/generate.txt107
-rw-r--r--src/cmd/go/testdata/script/generate_bad_imports.txt15
-rw-r--r--src/cmd/go/testdata/script/generate_env.txt32
-rw-r--r--src/cmd/go/testdata/script/generate_goroot_PATH.txt38
-rw-r--r--src/cmd/go/testdata/script/generate_invalid.txt208
-rw-r--r--src/cmd/go/testdata/script/generate_workspace.txt27
-rw-r--r--src/cmd/go/testdata/script/get_404_meta.txt15
-rw-r--r--src/cmd/go/testdata/script/get_insecure.txt41
-rw-r--r--src/cmd/go/testdata/script/get_insecure_no_longer_supported.txt13
-rw-r--r--src/cmd/go/testdata/script/get_issue53955.txt79
-rw-r--r--src/cmd/go/testdata/script/go_badcmd.txt2
-rw-r--r--src/cmd/go/testdata/script/go_version.txt9
-rw-r--r--src/cmd/go/testdata/script/godebug_default.txt114
-rw-r--r--src/cmd/go/testdata/script/godebug_unknown.txt9
-rw-r--r--src/cmd/go/testdata/script/goflags.txt64
-rw-r--r--src/cmd/go/testdata/script/goline_order.txt74
-rw-r--r--src/cmd/go/testdata/script/gopath_install.txt53
-rw-r--r--src/cmd/go/testdata/script/gopath_local.txt117
-rw-r--r--src/cmd/go/testdata/script/gopath_paths.txt43
-rw-r--r--src/cmd/go/testdata/script/gopath_std_vendor.txt44
-rw-r--r--src/cmd/go/testdata/script/gopath_vendor_dup_err.txt24
-rw-r--r--src/cmd/go/testdata/script/goroot_executable.txt115
-rw-r--r--src/cmd/go/testdata/script/goroot_executable_trimpath.txt101
-rw-r--r--src/cmd/go/testdata/script/gotoolchain_local.txt256
-rw-r--r--src/cmd/go/testdata/script/gotoolchain_loop.txt65
-rw-r--r--src/cmd/go/testdata/script/gotoolchain_modcmds.txt45
-rw-r--r--src/cmd/go/testdata/script/gotoolchain_net.txt70
-rw-r--r--src/cmd/go/testdata/script/gotoolchain_path.txt86
-rw-r--r--src/cmd/go/testdata/script/gotoolchain_version.txt22
-rw-r--r--src/cmd/go/testdata/script/govcs.txt91
-rw-r--r--src/cmd/go/testdata/script/help.txt51
-rw-r--r--src/cmd/go/testdata/script/import_cycle.txt12
-rw-r--r--src/cmd/go/testdata/script/import_ignore.txt11
-rw-r--r--src/cmd/go/testdata/script/import_main.txt114
-rw-r--r--src/cmd/go/testdata/script/import_unix_tag.txt32
-rw-r--r--src/cmd/go/testdata/script/index.txt6
-rw-r--r--src/cmd/go/testdata/script/install_cgo_excluded.txt15
-rw-r--r--src/cmd/go/testdata/script/install_cleans_build.txt25
-rw-r--r--src/cmd/go/testdata/script/install_cmd_gobin.txt10
-rw-r--r--src/cmd/go/testdata/script/install_cross_gobin.txt25
-rw-r--r--src/cmd/go/testdata/script/install_dep_version.txt8
-rw-r--r--src/cmd/go/testdata/script/install_goroot_targets.txt27
-rw-r--r--src/cmd/go/testdata/script/install_modcacherw_issue64282.txt45
-rw-r--r--src/cmd/go/testdata/script/install_move_not_stale.txt26
-rw-r--r--src/cmd/go/testdata/script/install_msan_and_race_and_asan_require_cgo.txt22
-rw-r--r--src/cmd/go/testdata/script/install_rebuild_removed.txt44
-rw-r--r--src/cmd/go/testdata/script/install_relative_gobin_fail.txt12
-rw-r--r--src/cmd/go/testdata/script/install_shadow_gopath.txt18
-rw-r--r--src/cmd/go/testdata/script/issue36000.txt6
-rw-r--r--src/cmd/go/testdata/script/issue53586.txt18
-rw-r--r--src/cmd/go/testdata/script/ldflag.txt44
-rw-r--r--src/cmd/go/testdata/script/link_external_undef.txt48
-rw-r--r--src/cmd/go/testdata/script/link_matching_actionid.txt38
-rw-r--r--src/cmd/go/testdata/script/link_syso_deps.txt55
-rw-r--r--src/cmd/go/testdata/script/link_syso_issue33139.txt45
-rw-r--r--src/cmd/go/testdata/script/linkname.txt9
-rw-r--r--src/cmd/go/testdata/script/list_all_gobuild.txt42
-rw-r--r--src/cmd/go/testdata/script/list_ambiguous_path.txt38
-rw-r--r--src/cmd/go/testdata/script/list_bad_import.txt72
-rw-r--r--src/cmd/go/testdata/script/list_case_collision.txt41
-rw-r--r--src/cmd/go/testdata/script/list_cgo_compiled_importmap.txt41
-rw-r--r--src/cmd/go/testdata/script/list_compiled_files_issue28749.txt10
-rw-r--r--src/cmd/go/testdata/script/list_compiled_imports.txt31
-rw-r--r--src/cmd/go/testdata/script/list_compiler_output.txt16
-rw-r--r--src/cmd/go/testdata/script/list_constraints.txt86
-rw-r--r--src/cmd/go/testdata/script/list_dedup_packages.txt31
-rw-r--r--src/cmd/go/testdata/script/list_empty_import.txt9
-rw-r--r--src/cmd/go/testdata/script/list_err_cycle.txt15
-rw-r--r--src/cmd/go/testdata/script/list_err_stack.txt27
-rw-r--r--src/cmd/go/testdata/script/list_export_e.txt30
-rw-r--r--src/cmd/go/testdata/script/list_export_embed.txt17
-rw-r--r--src/cmd/go/testdata/script/list_find.txt22
-rw-r--r--src/cmd/go/testdata/script/list_find_nodeps.txt49
-rw-r--r--src/cmd/go/testdata/script/list_gofile_in_goroot.txt76
-rw-r--r--src/cmd/go/testdata/script/list_gomod_in_gopath.txt23
-rw-r--r--src/cmd/go/testdata/script/list_goroot_symlink.txt62
-rw-r--r--src/cmd/go/testdata/script/list_import_cycle_deps_errors.txt75
-rw-r--r--src/cmd/go/testdata/script/list_import_err.txt22
-rw-r--r--src/cmd/go/testdata/script/list_importmap.txt27
-rw-r--r--src/cmd/go/testdata/script/list_issue_56509.txt35
-rw-r--r--src/cmd/go/testdata/script/list_issue_59905.txt88
-rw-r--r--src/cmd/go/testdata/script/list_json_fields.txt113
-rw-r--r--src/cmd/go/testdata/script/list_json_with_f.txt20
-rw-r--r--src/cmd/go/testdata/script/list_legacy_mod.txt48
-rw-r--r--src/cmd/go/testdata/script/list_linkshared.txt16
-rw-r--r--src/cmd/go/testdata/script/list_load_err.txt95
-rw-r--r--src/cmd/go/testdata/script/list_module_when_error.txt19
-rw-r--r--src/cmd/go/testdata/script/list_overlay.txt63
-rw-r--r--src/cmd/go/testdata/script/list_parse_err.txt45
-rw-r--r--src/cmd/go/testdata/script/list_perm.txt83
-rw-r--r--src/cmd/go/testdata/script/list_pkgconfig_error.txt16
-rw-r--r--src/cmd/go/testdata/script/list_replace_absolute_windows.txt38
-rw-r--r--src/cmd/go/testdata/script/list_reserved.txt7
-rw-r--r--src/cmd/go/testdata/script/list_shadow.txt25
-rw-r--r--src/cmd/go/testdata/script/list_split_main.txt25
-rw-r--r--src/cmd/go/testdata/script/list_std.txt25
-rw-r--r--src/cmd/go/testdata/script/list_std_vendor.txt33
-rw-r--r--src/cmd/go/testdata/script/list_swigcxx.txt30
-rw-r--r--src/cmd/go/testdata/script/list_symlink.txt12
-rw-r--r--src/cmd/go/testdata/script/list_symlink_dotdotdot.txt20
-rw-r--r--src/cmd/go/testdata/script/list_symlink_internal.txt27
-rw-r--r--src/cmd/go/testdata/script/list_symlink_issue35941.txt18
-rw-r--r--src/cmd/go/testdata/script/list_symlink_vendor_issue14054.txt28
-rw-r--r--src/cmd/go/testdata/script/list_symlink_vendor_issue15201.txt21
-rw-r--r--src/cmd/go/testdata/script/list_test_cycle.txt34
-rw-r--r--src/cmd/go/testdata/script/list_test_e.txt11
-rw-r--r--src/cmd/go/testdata/script/list_test_err.txt118
-rw-r--r--src/cmd/go/testdata/script/list_test_imports.txt21
-rw-r--r--src/cmd/go/testdata/script/list_test_non_go_files.txt13
-rw-r--r--src/cmd/go/testdata/script/list_test_simple.txt67
-rw-r--r--src/cmd/go/testdata/script/list_wildcard_skip_nonmatching.txt17
-rw-r--r--src/cmd/go/testdata/script/load_test_pkg_err.txt30
-rw-r--r--src/cmd/go/testdata/script/malformed_gosum_issue62345.txt51
-rw-r--r--src/cmd/go/testdata/script/mod_all.txt531
-rw-r--r--src/cmd/go/testdata/script/mod_alt_goroot.txt20
-rw-r--r--src/cmd/go/testdata/script/mod_ambiguous_import.txt48
-rw-r--r--src/cmd/go/testdata/script/mod_auth.txt35
-rw-r--r--src/cmd/go/testdata/script/mod_bad_domain.txt47
-rw-r--r--src/cmd/go/testdata/script/mod_bad_filenames.txt11
-rw-r--r--src/cmd/go/testdata/script/mod_build_info_err.txt33
-rw-r--r--src/cmd/go/testdata/script/mod_build_tags.txt33
-rw-r--r--src/cmd/go/testdata/script/mod_build_trimpath_issue48557.txt52
-rw-r--r--src/cmd/go/testdata/script/mod_build_versioned.txt17
-rw-r--r--src/cmd/go/testdata/script/mod_cache_dir.txt11
-rw-r--r--src/cmd/go/testdata/script/mod_cache_rw.txt49
-rw-r--r--src/cmd/go/testdata/script/mod_case.txt25
-rw-r--r--src/cmd/go/testdata/script/mod_case_cgo.txt11
-rw-r--r--src/cmd/go/testdata/script/mod_clean_cache.txt61
-rw-r--r--src/cmd/go/testdata/script/mod_concurrent.txt32
-rw-r--r--src/cmd/go/testdata/script/mod_convert_git.txt40
-rw-r--r--src/cmd/go/testdata/script/mod_deprecate_message.txt73
-rw-r--r--src/cmd/go/testdata/script/mod_dir.txt20
-rw-r--r--src/cmd/go/testdata/script/mod_doc.txt90
-rw-r--r--src/cmd/go/testdata/script/mod_doc_path.txt30
-rw-r--r--src/cmd/go/testdata/script/mod_domain_root.txt12
-rw-r--r--src/cmd/go/testdata/script/mod_dot.txt132
-rw-r--r--src/cmd/go/testdata/script/mod_download.txt214
-rw-r--r--src/cmd/go/testdata/script/mod_download_concurrent_read.txt110
-rw-r--r--src/cmd/go/testdata/script/mod_download_exec_toolchain.txt107
-rw-r--r--src/cmd/go/testdata/script/mod_download_git_bareRepository.txt28
-rw-r--r--src/cmd/go/testdata/script/mod_download_git_decorate_full.txt34
-rw-r--r--src/cmd/go/testdata/script/mod_download_hash.txt24
-rw-r--r--src/cmd/go/testdata/script/mod_download_insecure_redirect.txt32
-rw-r--r--src/cmd/go/testdata/script/mod_download_issue51114.txt29
-rw-r--r--src/cmd/go/testdata/script/mod_download_json.txt9
-rw-r--r--src/cmd/go/testdata/script/mod_download_partial.txt69
-rw-r--r--src/cmd/go/testdata/script/mod_download_private_vcs.txt48
-rw-r--r--src/cmd/go/testdata/script/mod_download_replace_file.txt16
-rw-r--r--src/cmd/go/testdata/script/mod_download_svn.txt29
-rw-r--r--src/cmd/go/testdata/script/mod_download_too_many_redirects.txt10
-rw-r--r--src/cmd/go/testdata/script/mod_e.txt96
-rw-r--r--src/cmd/go/testdata/script/mod_edit.txt340
-rw-r--r--src/cmd/go/testdata/script/mod_edit_go.txt26
-rw-r--r--src/cmd/go/testdata/script/mod_edit_no_modcache.txt15
-rw-r--r--src/cmd/go/testdata/script/mod_edit_toolchain.txt18
-rw-r--r--src/cmd/go/testdata/script/mod_empty_err.txt36
-rw-r--r--src/cmd/go/testdata/script/mod_enabled.txt93
-rw-r--r--src/cmd/go/testdata/script/mod_exclude_go121.txt34
-rw-r--r--src/cmd/go/testdata/script/mod_file_proxy.txt36
-rw-r--r--src/cmd/go/testdata/script/mod_fileproxy_vcs_missing_issue51589.txt42
-rw-r--r--src/cmd/go/testdata/script/mod_find.txt104
-rw-r--r--src/cmd/go/testdata/script/mod_fs_patterns.txt97
-rw-r--r--src/cmd/go/testdata/script/mod_get_ambiguous_arg.txt107
-rw-r--r--src/cmd/go/testdata/script/mod_get_ambiguous_import.txt60
-rw-r--r--src/cmd/go/testdata/script/mod_get_ambiguous_pkg.txt87
-rw-r--r--src/cmd/go/testdata/script/mod_get_boost.txt96
-rw-r--r--src/cmd/go/testdata/script/mod_get_changes.txt70
-rw-r--r--src/cmd/go/testdata/script/mod_get_commit.txt50
-rw-r--r--src/cmd/go/testdata/script/mod_get_deprecate_install.txt42
-rw-r--r--src/cmd/go/testdata/script/mod_get_deprecated.txt66
-rw-r--r--src/cmd/go/testdata/script/mod_get_direct.txt19
-rw-r--r--src/cmd/go/testdata/script/mod_get_downadd_indirect.txt81
-rw-r--r--src/cmd/go/testdata/script/mod_get_downgrade.txt56
-rw-r--r--src/cmd/go/testdata/script/mod_get_downgrade_missing.txt43
-rw-r--r--src/cmd/go/testdata/script/mod_get_downup_artifact.txt159
-rw-r--r--src/cmd/go/testdata/script/mod_get_downup_indirect.txt149
-rw-r--r--src/cmd/go/testdata/script/mod_get_downup_indirect_pruned.txt154
-rw-r--r--src/cmd/go/testdata/script/mod_get_downup_pseudo_artifact.txt129
-rw-r--r--src/cmd/go/testdata/script/mod_get_errors.txt57
-rw-r--r--src/cmd/go/testdata/script/mod_get_exec_toolchain.txt145
-rw-r--r--src/cmd/go/testdata/script/mod_get_extra.txt69
-rw-r--r--src/cmd/go/testdata/script/mod_get_fallback.txt16
-rw-r--r--src/cmd/go/testdata/script/mod_get_fossil.txt28
-rw-r--r--src/cmd/go/testdata/script/mod_get_future.txt13
-rw-r--r--src/cmd/go/testdata/script/mod_get_go_file.txt73
-rw-r--r--src/cmd/go/testdata/script/mod_get_hash.txt19
-rw-r--r--src/cmd/go/testdata/script/mod_get_incompatible.txt26
-rw-r--r--src/cmd/go/testdata/script/mod_get_indirect.txt59
-rw-r--r--src/cmd/go/testdata/script/mod_get_insecure_redirect.txt19
-rw-r--r--src/cmd/go/testdata/script/mod_get_issue37438.txt37
-rw-r--r--src/cmd/go/testdata/script/mod_get_issue47650.txt29
-rw-r--r--src/cmd/go/testdata/script/mod_get_issue47979.txt117
-rw-r--r--src/cmd/go/testdata/script/mod_get_issue48511.txt68
-rw-r--r--src/cmd/go/testdata/script/mod_get_issue56494.txt134
-rw-r--r--src/cmd/go/testdata/script/mod_get_issue60490.txt48
-rw-r--r--src/cmd/go/testdata/script/mod_get_latest_pseudo.txt10
-rw-r--r--src/cmd/go/testdata/script/mod_get_lazy_indirect.txt44
-rw-r--r--src/cmd/go/testdata/script/mod_get_lazy_upgrade_lazy.txt68
-rw-r--r--src/cmd/go/testdata/script/mod_get_local.txt62
-rw-r--r--src/cmd/go/testdata/script/mod_get_main.txt51
-rw-r--r--src/cmd/go/testdata/script/mod_get_major.txt23
-rw-r--r--src/cmd/go/testdata/script/mod_get_missing_ziphash.txt55
-rw-r--r--src/cmd/go/testdata/script/mod_get_moved.txt40
-rw-r--r--src/cmd/go/testdata/script/mod_get_newcycle.txt14
-rw-r--r--src/cmd/go/testdata/script/mod_get_none.txt12
-rw-r--r--src/cmd/go/testdata/script/mod_get_nopkgs.txt40
-rw-r--r--src/cmd/go/testdata/script/mod_get_patch.txt130
-rw-r--r--src/cmd/go/testdata/script/mod_get_patchbound.txt84
-rw-r--r--src/cmd/go/testdata/script/mod_get_patchcycle.txt64
-rw-r--r--src/cmd/go/testdata/script/mod_get_patchmod.txt82
-rw-r--r--src/cmd/go/testdata/script/mod_get_patterns.txt42
-rw-r--r--src/cmd/go/testdata/script/mod_get_pkgtags.txt130
-rw-r--r--src/cmd/go/testdata/script/mod_get_prefer_incompatible.txt29
-rw-r--r--src/cmd/go/testdata/script/mod_get_promote_implicit.txt92
-rw-r--r--src/cmd/go/testdata/script/mod_get_pseudo.txt82
-rw-r--r--src/cmd/go/testdata/script/mod_get_pseudo_other_branch.txt67
-rw-r--r--src/cmd/go/testdata/script/mod_get_pseudo_prefix.txt64
-rw-r--r--src/cmd/go/testdata/script/mod_get_replaced.txt111
-rw-r--r--src/cmd/go/testdata/script/mod_get_retract.txt59
-rw-r--r--src/cmd/go/testdata/script/mod_get_retract_ambiguous.txt10
-rw-r--r--src/cmd/go/testdata/script/mod_get_split.txt157
-rw-r--r--src/cmd/go/testdata/script/mod_get_sum_noroot.txt11
-rw-r--r--src/cmd/go/testdata/script/mod_get_tags.txt34
-rw-r--r--src/cmd/go/testdata/script/mod_get_test.txt58
-rw-r--r--src/cmd/go/testdata/script/mod_get_toolchain.txt129
-rw-r--r--src/cmd/go/testdata/script/mod_get_trailing_slash.txt30
-rw-r--r--src/cmd/go/testdata/script/mod_get_update_unrelated_sum.txt120
-rw-r--r--src/cmd/go/testdata/script/mod_get_upgrade.txt46
-rw-r--r--src/cmd/go/testdata/script/mod_get_upgrade_pseudo.txt70
-rw-r--r--src/cmd/go/testdata/script/mod_get_wild.txt95
-rw-r--r--src/cmd/go/testdata/script/mod_getmode_vendor.txt31
-rw-r--r--src/cmd/go/testdata/script/mod_getx.txt18
-rw-r--r--src/cmd/go/testdata/script/mod_git_export_subst.txt21
-rw-r--r--src/cmd/go/testdata/script/mod_go_version.txt29
-rw-r--r--src/cmd/go/testdata/script/mod_go_version_missing.txt122
-rw-r--r--src/cmd/go/testdata/script/mod_go_version_mixed.txt43
-rw-r--r--src/cmd/go/testdata/script/mod_gobuild_import.txt133
-rw-r--r--src/cmd/go/testdata/script/mod_gofmt_invalid.txt13
-rw-r--r--src/cmd/go/testdata/script/mod_goline.txt117
-rw-r--r--src/cmd/go/testdata/script/mod_goline_old.txt72
-rw-r--r--src/cmd/go/testdata/script/mod_goline_too_new.txt50
-rw-r--r--src/cmd/go/testdata/script/mod_gomodcache.txt74
-rw-r--r--src/cmd/go/testdata/script/mod_gonoproxy.txt55
-rw-r--r--src/cmd/go/testdata/script/mod_gopkg_unstable.txt26
-rw-r--r--src/cmd/go/testdata/script/mod_goroot_errors.txt53
-rw-r--r--src/cmd/go/testdata/script/mod_graph.txt15
-rw-r--r--src/cmd/go/testdata/script/mod_graph_version.txt101
-rw-r--r--src/cmd/go/testdata/script/mod_help.txt6
-rw-r--r--src/cmd/go/testdata/script/mod_import.txt18
-rw-r--r--src/cmd/go/testdata/script/mod_import_cycle.txt40
-rw-r--r--src/cmd/go/testdata/script/mod_import_issue41113.txt28
-rw-r--r--src/cmd/go/testdata/script/mod_import_issue42891.txt14
-rw-r--r--src/cmd/go/testdata/script/mod_import_meta.txt45
-rw-r--r--src/cmd/go/testdata/script/mod_import_mod.txt7
-rw-r--r--src/cmd/go/testdata/script/mod_import_toolchain.txt192
-rw-r--r--src/cmd/go/testdata/script/mod_import_v1suffix.txt11
-rw-r--r--src/cmd/go/testdata/script/mod_in_testdata_dir.txt45
-rw-r--r--src/cmd/go/testdata/script/mod_indirect.txt81
-rw-r--r--src/cmd/go/testdata/script/mod_indirect_main.txt66
-rw-r--r--src/cmd/go/testdata/script/mod_indirect_nospace.txt32
-rw-r--r--src/cmd/go/testdata/script/mod_indirect_tidy.txt60
-rw-r--r--src/cmd/go/testdata/script/mod_init_empty.txt21
-rw-r--r--src/cmd/go/testdata/script/mod_init_invalid_major.txt82
-rw-r--r--src/cmd/go/testdata/script/mod_init_path.txt20
-rw-r--r--src/cmd/go/testdata/script/mod_init_tidy.txt30
-rw-r--r--src/cmd/go/testdata/script/mod_insecure_issue63845.txt28
-rw-r--r--src/cmd/go/testdata/script/mod_install_hint.txt5
-rw-r--r--src/cmd/go/testdata/script/mod_install_pkg_version.txt204
-rw-r--r--src/cmd/go/testdata/script/mod_install_versioned.txt14
-rw-r--r--src/cmd/go/testdata/script/mod_internal.txt96
-rw-r--r--src/cmd/go/testdata/script/mod_invalid_path.txt61
-rw-r--r--src/cmd/go/testdata/script/mod_invalid_path_dotname.txt46
-rw-r--r--src/cmd/go/testdata/script/mod_invalid_path_plus.txt36
-rw-r--r--src/cmd/go/testdata/script/mod_invalid_version.txt253
-rw-r--r--src/cmd/go/testdata/script/mod_issue35270.txt57
-rw-r--r--src/cmd/go/testdata/script/mod_issue35317.txt8
-rw-r--r--src/cmd/go/testdata/script/mod_lazy_consistency.txt95
-rw-r--r--src/cmd/go/testdata/script/mod_lazy_downgrade.txt183
-rw-r--r--src/cmd/go/testdata/script/mod_lazy_import_allmod.txt191
-rw-r--r--src/cmd/go/testdata/script/mod_lazy_new_import.txt155
-rw-r--r--src/cmd/go/testdata/script/mod_lazy_test_horizon.txt131
-rw-r--r--src/cmd/go/testdata/script/mod_lazy_test_of_test_dep.txt224
-rw-r--r--src/cmd/go/testdata/script/mod_list.txt62
-rw-r--r--src/cmd/go/testdata/script/mod_list_bad_import.txt75
-rw-r--r--src/cmd/go/testdata/script/mod_list_command_line_arguments.txt35
-rw-r--r--src/cmd/go/testdata/script/mod_list_compiled_concurrent.txt21
-rw-r--r--src/cmd/go/testdata/script/mod_list_deprecated.txt52
-rw-r--r--src/cmd/go/testdata/script/mod_list_deprecated_replace.txt68
-rw-r--r--src/cmd/go/testdata/script/mod_list_dir.txt36
-rw-r--r--src/cmd/go/testdata/script/mod_list_direct.txt24
-rw-r--r--src/cmd/go/testdata/script/mod_list_e_readonly.txt15
-rw-r--r--src/cmd/go/testdata/script/mod_list_issue61415.txt76
-rw-r--r--src/cmd/go/testdata/script/mod_list_issue61423.txt100
-rw-r--r--src/cmd/go/testdata/script/mod_list_odd_tags.txt12
-rw-r--r--src/cmd/go/testdata/script/mod_list_pseudo.txt39
-rw-r--r--src/cmd/go/testdata/script/mod_list_replace_dir.txt27
-rw-r--r--src/cmd/go/testdata/script/mod_list_retract.txt110
-rw-r--r--src/cmd/go/testdata/script/mod_list_std.txt93
-rw-r--r--src/cmd/go/testdata/script/mod_list_sums.txt32
-rw-r--r--src/cmd/go/testdata/script/mod_list_test.txt30
-rw-r--r--src/cmd/go/testdata/script/mod_list_test_cycle.txt23
-rw-r--r--src/cmd/go/testdata/script/mod_list_update_nolatest.txt55
-rw-r--r--src/cmd/go/testdata/script/mod_list_upgrade.txt12
-rw-r--r--src/cmd/go/testdata/script/mod_list_upgrade_pseudo.txt26
-rw-r--r--src/cmd/go/testdata/script/mod_load_badchain.txt110
-rw-r--r--src/cmd/go/testdata/script/mod_load_badmod.txt25
-rw-r--r--src/cmd/go/testdata/script/mod_load_badzip.txt13
-rw-r--r--src/cmd/go/testdata/script/mod_load_replace_mismatch.txt23
-rw-r--r--src/cmd/go/testdata/script/mod_local_replace.txt23
-rw-r--r--src/cmd/go/testdata/script/mod_missing_repo.txt15
-rw-r--r--src/cmd/go/testdata/script/mod_missingpkg_prerelease.txt17
-rw-r--r--src/cmd/go/testdata/script/mod_modinfo.txt89
-rw-r--r--src/cmd/go/testdata/script/mod_multirepo.txt41
-rw-r--r--src/cmd/go/testdata/script/mod_no_gopath.txt15
-rw-r--r--src/cmd/go/testdata/script/mod_nomod.txt43
-rw-r--r--src/cmd/go/testdata/script/mod_notall.txt99
-rw-r--r--src/cmd/go/testdata/script/mod_off.txt35
-rw-r--r--src/cmd/go/testdata/script/mod_off_init.txt5
-rw-r--r--src/cmd/go/testdata/script/mod_outside.txt315
-rw-r--r--src/cmd/go/testdata/script/mod_overlay.txt254
-rw-r--r--src/cmd/go/testdata/script/mod_patterns.txt78
-rw-r--r--src/cmd/go/testdata/script/mod_patterns_vendor.txt28
-rw-r--r--src/cmd/go/testdata/script/mod_perm.txt23
-rw-r--r--src/cmd/go/testdata/script/mod_permissions.txt57
-rw-r--r--src/cmd/go/testdata/script/mod_prefer_compatible.txt80
-rw-r--r--src/cmd/go/testdata/script/mod_proxy_errors.txt19
-rw-r--r--src/cmd/go/testdata/script/mod_proxy_https.txt20
-rw-r--r--src/cmd/go/testdata/script/mod_proxy_invalid.txt8
-rw-r--r--src/cmd/go/testdata/script/mod_proxy_list.txt37
-rw-r--r--src/cmd/go/testdata/script/mod_pseudo_cache.txt29
-rw-r--r--src/cmd/go/testdata/script/mod_query.txt43
-rw-r--r--src/cmd/go/testdata/script/mod_query_empty.txt73
-rw-r--r--src/cmd/go/testdata/script/mod_query_exclude.txt46
-rw-r--r--src/cmd/go/testdata/script/mod_query_main.txt43
-rw-r--r--src/cmd/go/testdata/script/mod_readonly.txt131
-rw-r--r--src/cmd/go/testdata/script/mod_replace.txt129
-rw-r--r--src/cmd/go/testdata/script/mod_replace_gopkgin.txt82
-rw-r--r--src/cmd/go/testdata/script/mod_replace_import.txt144
-rw-r--r--src/cmd/go/testdata/script/mod_replace_readonly.txt62
-rw-r--r--src/cmd/go/testdata/script/mod_require_exclude.txt96
-rw-r--r--src/cmd/go/testdata/script/mod_retention.txt150
-rw-r--r--src/cmd/go/testdata/script/mod_retract.txt45
-rw-r--r--src/cmd/go/testdata/script/mod_retract_fix_version.txt48
-rw-r--r--src/cmd/go/testdata/script/mod_retract_incompatible.txt15
-rw-r--r--src/cmd/go/testdata/script/mod_retract_noupgrade.txt11
-rw-r--r--src/cmd/go/testdata/script/mod_retract_pseudo_base.txt62
-rw-r--r--src/cmd/go/testdata/script/mod_retract_rationale.txt79
-rw-r--r--src/cmd/go/testdata/script/mod_retract_rename.txt28
-rw-r--r--src/cmd/go/testdata/script/mod_retract_replace.txt63
-rw-r--r--src/cmd/go/testdata/script/mod_retract_versions.txt22
-rw-r--r--src/cmd/go/testdata/script/mod_run_issue52331.txt35
-rw-r--r--src/cmd/go/testdata/script/mod_run_nonmain.txt18
-rw-r--r--src/cmd/go/testdata/script/mod_run_path.txt15
-rw-r--r--src/cmd/go/testdata/script/mod_run_pkg_version.txt104
-rw-r--r--src/cmd/go/testdata/script/mod_run_pkgerror.txt32
-rw-r--r--src/cmd/go/testdata/script/mod_skip_write.txt93
-rw-r--r--src/cmd/go/testdata/script/mod_stale.txt15
-rw-r--r--src/cmd/go/testdata/script/mod_std_vendor.txt77
-rw-r--r--src/cmd/go/testdata/script/mod_string_alias.txt14
-rw-r--r--src/cmd/go/testdata/script/mod_sum_ambiguous.txt62
-rw-r--r--src/cmd/go/testdata/script/mod_sum_issue56222.txt91
-rw-r--r--src/cmd/go/testdata/script/mod_sum_lookup.txt34
-rw-r--r--src/cmd/go/testdata/script/mod_sum_readonly.txt87
-rw-r--r--src/cmd/go/testdata/script/mod_sum_replaced.txt28
-rw-r--r--src/cmd/go/testdata/script/mod_sumdb.txt45
-rw-r--r--src/cmd/go/testdata/script/mod_sumdb_cache.txt47
-rw-r--r--src/cmd/go/testdata/script/mod_sumdb_file_path.txt58
-rw-r--r--src/cmd/go/testdata/script/mod_sumdb_golang.txt83
-rw-r--r--src/cmd/go/testdata/script/mod_sumdb_proxy.txt65
-rw-r--r--src/cmd/go/testdata/script/mod_symlink.txt45
-rw-r--r--src/cmd/go/testdata/script/mod_symlink_dotgo.txt17
-rw-r--r--src/cmd/go/testdata/script/mod_tagged_import_cycle.txt106
-rw-r--r--src/cmd/go/testdata/script/mod_test.txt130
-rw-r--r--src/cmd/go/testdata/script/mod_test_cached.txt76
-rw-r--r--src/cmd/go/testdata/script/mod_test_files.txt50
-rw-r--r--src/cmd/go/testdata/script/mod_tidy.txt72
-rw-r--r--src/cmd/go/testdata/script/mod_tidy_compat.txt95
-rw-r--r--src/cmd/go/testdata/script/mod_tidy_compat_added.txt105
-rw-r--r--src/cmd/go/testdata/script/mod_tidy_compat_ambiguous.txt97
-rw-r--r--src/cmd/go/testdata/script/mod_tidy_compat_deleted.txt128
-rw-r--r--src/cmd/go/testdata/script/mod_tidy_compat_implicit.txt128
-rw-r--r--src/cmd/go/testdata/script/mod_tidy_compat_incompatible.txt133
-rw-r--r--src/cmd/go/testdata/script/mod_tidy_compat_irrelevant.txt98
-rw-r--r--src/cmd/go/testdata/script/mod_tidy_convergence.txt202
-rw-r--r--src/cmd/go/testdata/script/mod_tidy_convergence_loop.txt329
-rw-r--r--src/cmd/go/testdata/script/mod_tidy_cycle.txt75
-rw-r--r--src/cmd/go/testdata/script/mod_tidy_downgrade_ambiguous.txt58
-rw-r--r--src/cmd/go/testdata/script/mod_tidy_duplicates.txt38
-rw-r--r--src/cmd/go/testdata/script/mod_tidy_error.txt39
-rw-r--r--src/cmd/go/testdata/script/mod_tidy_indirect.txt67
-rw-r--r--src/cmd/go/testdata/script/mod_tidy_issue60313.txt69
-rw-r--r--src/cmd/go/testdata/script/mod_tidy_lazy_self.txt66
-rw-r--r--src/cmd/go/testdata/script/mod_tidy_newroot.txt82
-rw-r--r--src/cmd/go/testdata/script/mod_tidy_old.txt46
-rw-r--r--src/cmd/go/testdata/script/mod_tidy_oldgo.txt21
-rw-r--r--src/cmd/go/testdata/script/mod_tidy_quote.txt26
-rw-r--r--src/cmd/go/testdata/script/mod_tidy_replace.txt145
-rw-r--r--src/cmd/go/testdata/script/mod_tidy_replace_old.txt34
-rw-r--r--src/cmd/go/testdata/script/mod_tidy_sum.txt33
-rw-r--r--src/cmd/go/testdata/script/mod_tidy_support_buildx.txt18
-rw-r--r--src/cmd/go/testdata/script/mod_tidy_symlink_issue35941.txt36
-rw-r--r--src/cmd/go/testdata/script/mod_tidy_temp.txt26
-rw-r--r--src/cmd/go/testdata/script/mod_tidy_version.txt394
-rw-r--r--src/cmd/go/testdata/script/mod_tidy_version_tooold.txt23
-rw-r--r--src/cmd/go/testdata/script/mod_toolchain.txt76
-rw-r--r--src/cmd/go/testdata/script/mod_toolchain_slash.txt32
-rw-r--r--src/cmd/go/testdata/script/mod_update_sum_readonly.txt34
-rw-r--r--src/cmd/go/testdata/script/mod_upgrade_patch.txt110
-rw-r--r--src/cmd/go/testdata/script/mod_vcs_missing.txt28
-rw-r--r--src/cmd/go/testdata/script/mod_vendor.txt354
-rw-r--r--src/cmd/go/testdata/script/mod_vendor_auto.txt259
-rw-r--r--src/cmd/go/testdata/script/mod_vendor_build.txt41
-rw-r--r--src/cmd/go/testdata/script/mod_vendor_embed.txt209
-rw-r--r--src/cmd/go/testdata/script/mod_vendor_gomod.txt38
-rw-r--r--src/cmd/go/testdata/script/mod_vendor_goversion.txt102
-rw-r--r--src/cmd/go/testdata/script/mod_vendor_issue46867.txt31
-rw-r--r--src/cmd/go/testdata/script/mod_vendor_nodeps.txt9
-rw-r--r--src/cmd/go/testdata/script/mod_vendor_redundant_requirement.txt29
-rw-r--r--src/cmd/go/testdata/script/mod_vendor_replace.txt89
-rw-r--r--src/cmd/go/testdata/script/mod_vendor_trimpath.txt49
-rw-r--r--src/cmd/go/testdata/script/mod_vendor_unused.txt67
-rw-r--r--src/cmd/go/testdata/script/mod_vendor_unused_only.txt19
-rw-r--r--src/cmd/go/testdata/script/mod_verify.txt82
-rw-r--r--src/cmd/go/testdata/script/mod_verify_work.txt24
-rw-r--r--src/cmd/go/testdata/script/mod_versions.txt14
-rw-r--r--src/cmd/go/testdata/script/mod_why.txt130
-rw-r--r--src/cmd/go/testdata/script/modfile_flag.txt98
-rw-r--r--src/cmd/go/testdata/script/noncanonical_import.txt19
-rw-r--r--src/cmd/go/testdata/script/old_tidy_toolchain.txt28
-rw-r--r--src/cmd/go/testdata/script/pattern_syntax_error.txt12
-rw-r--r--src/cmd/go/testdata/script/prevent_sys_unix_import.txt6
-rw-r--r--src/cmd/go/testdata/script/repro_build.txt22
-rw-r--r--src/cmd/go/testdata/script/reuse_git.txt376
-rw-r--r--src/cmd/go/testdata/script/run_dirs.txt21
-rw-r--r--src/cmd/go/testdata/script/run_hello.txt9
-rw-r--r--src/cmd/go/testdata/script/run_hello_pkg.txt17
-rw-r--r--src/cmd/go/testdata/script/run_internal.txt64
-rw-r--r--src/cmd/go/testdata/script/run_issue11709.txt15
-rw-r--r--src/cmd/go/testdata/script/run_issue51125.txt54
-rw-r--r--src/cmd/go/testdata/script/run_set_executable_name.txt50
-rw-r--r--src/cmd/go/testdata/script/run_vendor.txt34
-rw-r--r--src/cmd/go/testdata/script/run_wildcard.txt7
-rw-r--r--src/cmd/go/testdata/script/run_work_versioned.txt16
-rw-r--r--src/cmd/go/testdata/script/script_help.txt7
-rw-r--r--src/cmd/go/testdata/script/script_wait.txt28
-rw-r--r--src/cmd/go/testdata/script/slashpath.txt18
-rw-r--r--src/cmd/go/testdata/script/src_file.txt9
-rw-r--r--src/cmd/go/testdata/script/std_vendor.txt43
-rw-r--r--src/cmd/go/testdata/script/test2json_interrupt.txt58
-rw-r--r--src/cmd/go/testdata/script/test_android_issue62123.txt19
-rw-r--r--src/cmd/go/testdata/script/test_bad_example.txt13
-rw-r--r--src/cmd/go/testdata/script/test_badtest.txt49
-rw-r--r--src/cmd/go/testdata/script/test_benchmark_1x.txt37
-rw-r--r--src/cmd/go/testdata/script/test_benchmark_chatty_fail.txt32
-rw-r--r--src/cmd/go/testdata/script/test_benchmark_chatty_success.txt29
-rw-r--r--src/cmd/go/testdata/script/test_benchmark_fatal.txt19
-rw-r--r--src/cmd/go/testdata/script/test_benchmark_labels.txt23
-rw-r--r--src/cmd/go/testdata/script/test_benchmark_timeout.txt18
-rw-r--r--src/cmd/go/testdata/script/test_build_failure.txt31
-rw-r--r--src/cmd/go/testdata/script/test_buildvcs.txt104
-rw-r--r--src/cmd/go/testdata/script/test_cache_inputs.txt270
-rw-r--r--src/cmd/go/testdata/script/test_chatty_fail.txt32
-rw-r--r--src/cmd/go/testdata/script/test_chatty_parallel_fail.txt62
-rw-r--r--src/cmd/go/testdata/script/test_chatty_parallel_success.txt52
-rw-r--r--src/cmd/go/testdata/script/test_chatty_parallel_success_run.txt41
-rw-r--r--src/cmd/go/testdata/script/test_chatty_success.txt27
-rw-r--r--src/cmd/go/testdata/script/test_cleanup_failnow.txt46
-rw-r--r--src/cmd/go/testdata/script/test_compile_binary.txt8
-rw-r--r--src/cmd/go/testdata/script/test_compile_multi_pkg.txt50
-rw-r--r--src/cmd/go/testdata/script/test_compile_tempfile.txt11
-rw-r--r--src/cmd/go/testdata/script/test_deadline.txt54
-rw-r--r--src/cmd/go/testdata/script/test_empty.txt53
-rw-r--r--src/cmd/go/testdata/script/test_env_term.txt15
-rw-r--r--src/cmd/go/testdata/script/test_example_goexit.txt29
-rw-r--r--src/cmd/go/testdata/script/test_exit.txt131
-rw-r--r--src/cmd/go/testdata/script/test_fail_fast.txt113
-rw-r--r--src/cmd/go/testdata/script/test_fail_newline.txt65
-rw-r--r--src/cmd/go/testdata/script/test_finished_subtest_goroutines.txt52
-rw-r--r--src/cmd/go/testdata/script/test_flag.txt38
-rw-r--r--src/cmd/go/testdata/script/test_flags.txt131
-rw-r--r--src/cmd/go/testdata/script/test_fullpath.txt21
-rw-r--r--src/cmd/go/testdata/script/test_fuzz.txt500
-rw-r--r--src/cmd/go/testdata/script/test_fuzz_cache.txt97
-rw-r--r--src/cmd/go/testdata/script/test_fuzz_chatty.txt103
-rw-r--r--src/cmd/go/testdata/script/test_fuzz_cleanup.txt67
-rw-r--r--src/cmd/go/testdata/script/test_fuzz_cov.txt36
-rw-r--r--src/cmd/go/testdata/script/test_fuzz_deadline.txt36
-rw-r--r--src/cmd/go/testdata/script/test_fuzz_dup_cache.txt53
-rw-r--r--src/cmd/go/testdata/script/test_fuzz_err_deadlock.txt50
-rw-r--r--src/cmd/go/testdata/script/test_fuzz_fuzztime.txt120
-rw-r--r--src/cmd/go/testdata/script/test_fuzz_io_error.txt102
-rw-r--r--src/cmd/go/testdata/script/test_fuzz_limit_dup_entry.txt37
-rw-r--r--src/cmd/go/testdata/script/test_fuzz_match.txt40
-rw-r--r--src/cmd/go/testdata/script/test_fuzz_minimize.txt203
-rw-r--r--src/cmd/go/testdata/script/test_fuzz_minimize_dirty_cov.txt85
-rw-r--r--src/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt230
-rw-r--r--src/cmd/go/testdata/script/test_fuzz_modcache.txt58
-rw-r--r--src/cmd/go/testdata/script/test_fuzz_multiple.txt50
-rw-r--r--src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt323
-rw-r--r--src/cmd/go/testdata/script/test_fuzz_mutate_fail.txt103
-rw-r--r--src/cmd/go/testdata/script/test_fuzz_mutator.txt166
-rw-r--r--src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt75
-rw-r--r--src/cmd/go/testdata/script/test_fuzz_non_crash_signal.txt76
-rw-r--r--src/cmd/go/testdata/script/test_fuzz_parallel.txt67
-rw-r--r--src/cmd/go/testdata/script/test_fuzz_profile_flags.txt38
-rw-r--r--src/cmd/go/testdata/script/test_fuzz_return.txt19
-rw-r--r--src/cmd/go/testdata/script/test_fuzz_run.txt143
-rw-r--r--src/cmd/go/testdata/script/test_fuzz_seed_corpus.txt203
-rw-r--r--src/cmd/go/testdata/script/test_fuzz_setenv.txt46
-rw-r--r--src/cmd/go/testdata/script/test_fuzz_test_race.txt40
-rw-r--r--src/cmd/go/testdata/script/test_fuzz_unsupported.txt18
-rw-r--r--src/cmd/go/testdata/script/test_generated_main.txt34
-rw-r--r--src/cmd/go/testdata/script/test_go111module_cache.txt15
-rw-r--r--src/cmd/go/testdata/script/test_goroot_PATH.txt41
-rw-r--r--src/cmd/go/testdata/script/test_import_error_stack.txt31
-rw-r--r--src/cmd/go/testdata/script/test_issue45477.txt12
-rw-r--r--src/cmd/go/testdata/script/test_json.txt80
-rw-r--r--src/cmd/go/testdata/script/test_json_exit.txt102
-rw-r--r--src/cmd/go/testdata/script/test_json_interleaved.txt27
-rw-r--r--src/cmd/go/testdata/script/test_json_issue35169.txt28
-rw-r--r--src/cmd/go/testdata/script/test_json_panic_exit.txt69
-rw-r--r--src/cmd/go/testdata/script/test_json_prints.txt48
-rw-r--r--src/cmd/go/testdata/script/test_json_timeout.txt19
-rw-r--r--src/cmd/go/testdata/script/test_main.txt92
-rw-r--r--src/cmd/go/testdata/script/test_main_archive.txt32
-rw-r--r--src/cmd/go/testdata/script/test_main_panic.txt30
-rw-r--r--src/cmd/go/testdata/script/test_main_twice.txt27
-rw-r--r--src/cmd/go/testdata/script/test_match_benchmark_labels.txt18
-rw-r--r--src/cmd/go/testdata/script/test_match_no_benchmarks.txt13
-rw-r--r--src/cmd/go/testdata/script/test_match_no_subtests.txt12
-rw-r--r--src/cmd/go/testdata/script/test_match_no_subtests_failure.txt15
-rw-r--r--src/cmd/go/testdata/script/test_match_no_subtests_parallel.txt19
-rw-r--r--src/cmd/go/testdata/script/test_match_no_tests.txt11
-rw-r--r--src/cmd/go/testdata/script/test_match_no_tests_build_failure.txt19
-rw-r--r--src/cmd/go/testdata/script/test_match_no_tests_with_subtests.txt12
-rw-r--r--src/cmd/go/testdata/script/test_match_only_benchmarks.txt13
-rw-r--r--src/cmd/go/testdata/script/test_match_only_example.txt31
-rw-r--r--src/cmd/go/testdata/script/test_match_only_subtests.txt14
-rw-r--r--src/cmd/go/testdata/script/test_match_only_subtests_parallel.txt21
-rw-r--r--src/cmd/go/testdata/script/test_match_only_tests.txt13
-rw-r--r--src/cmd/go/testdata/script/test_minus_n.txt14
-rw-r--r--src/cmd/go/testdata/script/test_no_run_example.txt30
-rw-r--r--src/cmd/go/testdata/script/test_no_tests.txt15
-rw-r--r--src/cmd/go/testdata/script/test_overlay.txt24
-rw-r--r--src/cmd/go/testdata/script/test_parallel_number.txt25
-rw-r--r--src/cmd/go/testdata/script/test_ppc64_linker_funcs.txt49
-rw-r--r--src/cmd/go/testdata/script/test_ppc64le_cgo_inline_plt.txt38
-rw-r--r--src/cmd/go/testdata/script/test_profile.txt19
-rw-r--r--src/cmd/go/testdata/script/test_race.txt51
-rw-r--r--src/cmd/go/testdata/script/test_race_cover_mode_issue20435.txt48
-rw-r--r--src/cmd/go/testdata/script/test_race_install.txt12
-rw-r--r--src/cmd/go/testdata/script/test_race_install_cgo.txt91
-rw-r--r--src/cmd/go/testdata/script/test_race_tag.txt29
-rw-r--r--src/cmd/go/testdata/script/test_rebuildall.txt14
-rw-r--r--src/cmd/go/testdata/script/test_regexps.txt79
-rw-r--r--src/cmd/go/testdata/script/test_relative_cmdline.txt52
-rw-r--r--src/cmd/go/testdata/script/test_relative_import.txt31
-rw-r--r--src/cmd/go/testdata/script/test_script_cmdcd.txt13
-rw-r--r--src/cmd/go/testdata/script/test_shuffle.txt134
-rw-r--r--src/cmd/go/testdata/script/test_skip.txt45
-rw-r--r--src/cmd/go/testdata/script/test_source_order.txt54
-rw-r--r--src/cmd/go/testdata/script/test_status.txt18
-rw-r--r--src/cmd/go/testdata/script/test_syntax_error_says_fail.txt25
-rw-r--r--src/cmd/go/testdata/script/test_timeout.txt23
-rw-r--r--src/cmd/go/testdata/script/test_timeout_stdin.txt88
-rw-r--r--src/cmd/go/testdata/script/test_trimpath.txt51
-rw-r--r--src/cmd/go/testdata/script/test_trimpath_main.txt38
-rw-r--r--src/cmd/go/testdata/script/test_trimpath_test_suffix.txt40
-rw-r--r--src/cmd/go/testdata/script/test_vendor.txt57
-rw-r--r--src/cmd/go/testdata/script/test_vet.txt123
-rw-r--r--src/cmd/go/testdata/script/test_write_profiles_on_timeout.txt26
-rw-r--r--src/cmd/go/testdata/script/test_xtestonly_works.txt27
-rw-r--r--src/cmd/go/testdata/script/testing_coverage.txt57
-rw-r--r--src/cmd/go/testdata/script/testing_issue40908.txt25
-rw-r--r--src/cmd/go/testdata/script/toolexec.txt128
-rw-r--r--src/cmd/go/testdata/script/tooltags.txt57
-rw-r--r--src/cmd/go/testdata/script/trampoline_reuse_test.txt100
-rw-r--r--src/cmd/go/testdata/script/vendor_complex.txt75
-rw-r--r--src/cmd/go/testdata/script/vendor_gopath_issue11409.txt52
-rw-r--r--src/cmd/go/testdata/script/vendor_import.txt106
-rw-r--r--src/cmd/go/testdata/script/vendor_import_missing.txt7
-rw-r--r--src/cmd/go/testdata/script/vendor_import_wrong.txt20
-rw-r--r--src/cmd/go/testdata/script/vendor_internal.txt16
-rw-r--r--src/cmd/go/testdata/script/vendor_issue12156.txt16
-rw-r--r--src/cmd/go/testdata/script/vendor_list_issue11977.txt87
-rw-r--r--src/cmd/go/testdata/script/vendor_outside_module.txt36
-rw-r--r--src/cmd/go/testdata/script/vendor_resolve.txt21
-rw-r--r--src/cmd/go/testdata/script/vendor_test_issue11864.txt83
-rw-r--r--src/cmd/go/testdata/script/vendor_test_issue14613.txt52
-rw-r--r--src/cmd/go/testdata/script/version.txt92
-rw-r--r--src/cmd/go/testdata/script/version_build_settings.txt89
-rw-r--r--src/cmd/go/testdata/script/version_buildvcs_bzr.txt107
-rw-r--r--src/cmd/go/testdata/script/version_buildvcs_fossil.txt94
-rw-r--r--src/cmd/go/testdata/script/version_buildvcs_git.txt182
-rw-r--r--src/cmd/go/testdata/script/version_buildvcs_hg.txt91
-rw-r--r--src/cmd/go/testdata/script/version_buildvcs_nested.txt51
-rw-r--r--src/cmd/go/testdata/script/version_cshared.txt19
-rw-r--r--src/cmd/go/testdata/script/version_gc_sections.txt24
-rw-r--r--src/cmd/go/testdata/script/version_goexperiment.txt16
-rw-r--r--src/cmd/go/testdata/script/version_replace.txt33
-rw-r--r--src/cmd/go/testdata/script/vet.txt62
-rw-r--r--src/cmd/go/testdata/script/vet_asm.txt32
-rw-r--r--src/cmd/go/testdata/script/vet_deps.txt34
-rw-r--r--src/cmd/go/testdata/script/vet_flags.txt91
-rw-r--r--src/cmd/go/testdata/script/vet_internal.txt71
-rw-r--r--src/cmd/go/testdata/script/work.txt154
-rw-r--r--src/cmd/go/testdata/script/work_build_no_modules.txt13
-rw-r--r--src/cmd/go/testdata/script/work_disablevendor.txt56
-rw-r--r--src/cmd/go/testdata/script/work_edit.txt166
-rw-r--r--src/cmd/go/testdata/script/work_edit_toolchain.txt20
-rw-r--r--src/cmd/go/testdata/script/work_empty_panic_GOPATH.txt13
-rw-r--r--src/cmd/go/testdata/script/work_env.txt28
-rw-r--r--src/cmd/go/testdata/script/work_get_toolchain.txt24
-rw-r--r--src/cmd/go/testdata/script/work_goline_order.txt34
-rw-r--r--src/cmd/go/testdata/script/work_goproxy_off.txt59
-rw-r--r--src/cmd/go/testdata/script/work_gowork.txt24
-rw-r--r--src/cmd/go/testdata/script/work_init_gowork.txt19
-rw-r--r--src/cmd/go/testdata/script/work_init_path.txt33
-rw-r--r--src/cmd/go/testdata/script/work_init_toolchain.txt35
-rw-r--r--src/cmd/go/testdata/script/work_install_submodule.txt36
-rw-r--r--src/cmd/go/testdata/script/work_issue51204.txt57
-rw-r--r--src/cmd/go/testdata/script/work_issue54048.txt19
-rw-r--r--src/cmd/go/testdata/script/work_issue54372.txt37
-rw-r--r--src/cmd/go/testdata/script/work_module_not_in_go_work.txt40
-rw-r--r--src/cmd/go/testdata/script/work_nowork.txt20
-rw-r--r--src/cmd/go/testdata/script/work_prune.txt103
-rw-r--r--src/cmd/go/testdata/script/work_prune_all.txt176
-rw-r--r--src/cmd/go/testdata/script/work_regression_hang.txt71
-rw-r--r--src/cmd/go/testdata/script/work_reject_modfile.txt34
-rw-r--r--src/cmd/go/testdata/script/work_replace.txt55
-rw-r--r--src/cmd/go/testdata/script/work_replace_conflict.txt53
-rw-r--r--src/cmd/go/testdata/script/work_replace_conflict_override.txt57
-rw-r--r--src/cmd/go/testdata/script/work_replace_main_module.txt45
-rw-r--r--src/cmd/go/testdata/script/work_sum.txt34
-rw-r--r--src/cmd/go/testdata/script/work_sum_mismatch.txt61
-rw-r--r--src/cmd/go/testdata/script/work_sync.txt119
-rw-r--r--src/cmd/go/testdata/script/work_sync_irrelevant_dependency.txt119
-rw-r--r--src/cmd/go/testdata/script/work_sync_missing_module.txt12
-rw-r--r--src/cmd/go/testdata/script/work_sync_relevant_dependency.txt106
-rw-r--r--src/cmd/go/testdata/script/work_sync_sum.txt40
-rw-r--r--src/cmd/go/testdata/script/work_sync_toolchain.txt45
-rw-r--r--src/cmd/go/testdata/script/work_use.txt36
-rw-r--r--src/cmd/go/testdata/script/work_use_deleted.txt22
-rw-r--r--src/cmd/go/testdata/script/work_use_dot.txt49
-rw-r--r--src/cmd/go/testdata/script/work_use_issue50958.txt17
-rw-r--r--src/cmd/go/testdata/script/work_use_issue55952.txt11
-rw-r--r--src/cmd/go/testdata/script/work_use_only_dirs.txt17
-rw-r--r--src/cmd/go/testdata/script/work_use_toolchain.txt51
-rw-r--r--src/cmd/go/testdata/script/work_vendor_empty.txt16
-rw-r--r--src/cmd/go/testdata/script/work_vendor_main_module_replaced.txt46
-rw-r--r--src/cmd/go/testdata/script/work_vendor_modules_txt_conditional.txt62
-rw-r--r--src/cmd/go/testdata/script/work_vendor_modules_txt_consistent.txt141
-rw-r--r--src/cmd/go/testdata/script/work_vendor_prune.txt116
-rw-r--r--src/cmd/go/testdata/script/work_vendor_prune_all.txt201
-rw-r--r--src/cmd/go/testdata/script/work_vet.txt19
-rw-r--r--src/cmd/go/testdata/script/work_why_download_graph.txt65
801 files changed, 46731 insertions, 0 deletions
diff --git a/src/cmd/go/testdata/script/README b/src/cmd/go/testdata/script/README
new file mode 100644
index 0000000..792a158
--- /dev/null
+++ b/src/cmd/go/testdata/script/README
@@ -0,0 +1,425 @@
+This file is generated by 'go generate cmd/go'. DO NOT EDIT.
+
+This directory holds test scripts *.txt run during 'go test cmd/go'.
+To run a specific script foo.txt
+
+ go test cmd/go -run=Script/^foo$
+
+In general script files should have short names: a few words, not whole sentences.
+The first word should be the general category of behavior being tested,
+often the name of a go subcommand (list, build, test, ...) or concept (vendor, pattern).
+
+Each script is a text archive (go doc internal/txtar).
+The script begins with an actual command script to run
+followed by the content of zero or more supporting files to
+create in the script's temporary file system before it starts executing.
+
+As an example, run_hello.txt says:
+
+ # hello world
+ go run hello.go
+ stderr 'hello world'
+ ! stdout .
+
+ -- hello.go --
+ package main
+ func main() { println("hello world") }
+
+Each script runs in a fresh temporary work directory tree, available to scripts as $WORK.
+Scripts also have access to other environment variables, including:
+
+ GOARCH=<target GOARCH>
+ GOCACHE=<actual GOCACHE being used outside the test>
+ GOEXE=<executable file suffix: .exe on Windows, empty on other systems>
+ GOOS=<target GOOS>
+ GOPATH=$WORK/gopath
+ GOPROXY=<local module proxy serving from cmd/go/testdata/mod>
+ GOROOT=<actual GOROOT>
+ GOROOT_FINAL=<actual GOROOT_FINAL>
+ TESTGO_GOROOT=<GOROOT used to build cmd/go, for use in tests that may change GOROOT>
+ HOME=/no-home
+ PATH=<actual PATH>
+ TMPDIR=$WORK/tmp
+ GODEBUG=<actual GODEBUG>
+ devnull=<value of os.DevNull>
+ goversion=<current Go version; for example, 1.12>
+
+On Plan 9, the variables $path and $home are set instead of $PATH and $HOME.
+On Windows, the variables $USERPROFILE and $TMP are set instead of
+$HOME and $TMPDIR.
+
+The lines at the top of the script are a sequence of commands to be executed by
+a small script engine configured in ../../script_test.go (not the system shell).
+
+The scripts' supporting files are unpacked relative to $GOPATH/src
+(aka $WORK/gopath/src) and then the script begins execution in that directory as
+well. Thus the example above runs in $WORK/gopath/src with GOPATH=$WORK/gopath
+and $WORK/gopath/src/hello.go containing the listed contents.
+
+Each line of a script is parsed into a sequence of space-separated command
+words, with environment variable expansion within each word and # marking
+an end-of-line comment. Additional variables named ':' and '/' are expanded
+within script arguments (expanding to the value of os.PathListSeparator and
+os.PathSeparator respectively) but are not inherited in subprocess environments.
+
+Adding single quotes around text keeps spaces in that text from being treated
+as word separators and also disables environment variable expansion. Inside a
+single-quoted block of text, a repeated single quote indicates a literal single
+quote, as in:
+
+ 'Don''t communicate by sharing memory.'
+
+A line beginning with # is a comment and conventionally explains what is being
+done or tested at the start of a new section of the script.
+
+Commands are executed one at a time, and errors are checked for each command;
+if any command fails unexpectedly, no subsequent commands in the script are
+executed. The command prefix ! indicates that the command on the rest of the
+line (typically go or a matching predicate) must fail instead of succeeding.
+The command prefix ? indicates that the command may or may not succeed, but the
+script should continue regardless.
+
+The command prefix [cond] indicates that the command on the rest of the line
+should only run when the condition is satisfied.
+
+A condition can be negated: [!root] means to run the rest of the line only if
+the user is not root. Multiple conditions may be given for a single command,
+for example, '[linux] [amd64] skip'. The command will run if all conditions are
+satisfied.
+
+When TestScript runs a script and the script fails, by default TestScript shows
+the execution of the most recent phase of the script (since the last # comment)
+and only shows the # comments for earlier phases. For example, here is a
+multi-phase script with a bug in it:
+
+ # GOPATH with p1 in d2, p2 in d2
+ env GOPATH=$WORK${/}d1${:}$WORK${/}d2
+
+ # build & install p1
+ env
+ go install -i p1
+ ! stale p1
+ ! stale p2
+
+ # modify p2 - p1 should appear stale
+ cp $WORK/p2x.go $WORK/d2/src/p2/p2.go
+ stale p1 p2
+
+ # build & install p1 again
+ go install -i p11
+ ! stale p1
+ ! stale p2
+
+ -- $WORK/d1/src/p1/p1.go --
+ package p1
+ import "p2"
+ func F() { p2.F() }
+ -- $WORK/d2/src/p2/p2.go --
+ package p2
+ func F() {}
+ -- $WORK/p2x.go --
+ package p2
+ func F() {}
+ func G() {}
+
+The bug is that the final phase installs p11 instead of p1. The test failure looks like:
+
+ $ go test -run=Script
+ --- FAIL: TestScript (3.75s)
+ --- FAIL: TestScript/install_rebuild_gopath (0.16s)
+ script_test.go:223:
+ # GOPATH with p1 in d2, p2 in d2 (0.000s)
+ # build & install p1 (0.087s)
+ # modify p2 - p1 should appear stale (0.029s)
+ # build & install p1 again (0.022s)
+ > go install -i p11
+ [stderr]
+ can't load package: package p11: cannot find package "p11" in any of:
+ /Users/rsc/go/src/p11 (from $GOROOT)
+ $WORK/d1/src/p11 (from $GOPATH)
+ $WORK/d2/src/p11
+ [exit status 1]
+ FAIL: unexpected go command failure
+
+ script_test.go:73: failed at testdata/script/install_rebuild_gopath.txt:15 in $WORK/gopath/src
+
+ FAIL
+ exit status 1
+ FAIL cmd/go 4.875s
+ $
+
+Note that the commands in earlier phases have been hidden, so that the relevant
+commands are more easily found, and the elapsed time for a completed phase
+is shown next to the phase heading. To see the entire execution, use "go test -v",
+which also adds an initial environment dump to the beginning of the log.
+
+Note also that in reported output, the actual name of the per-script temporary directory
+has been consistently replaced with the literal string $WORK.
+
+The cmd/go test flag -testwork (which must appear on the "go test" command line after
+standard test flags) causes each test to log the name of its $WORK directory and other
+environment variable settings and also to leave that directory behind when it exits,
+for manual debugging of failing tests:
+
+ $ go test -run=Script -work
+ --- FAIL: TestScript (3.75s)
+ --- FAIL: TestScript/install_rebuild_gopath (0.16s)
+ script_test.go:223:
+ WORK=/tmp/cmd-go-test-745953508/script-install_rebuild_gopath
+ GOARCH=
+ GOCACHE=/Users/rsc/Library/Caches/go-build
+ GOOS=
+ GOPATH=$WORK/gopath
+ GOROOT=/Users/rsc/go
+ HOME=/no-home
+ TMPDIR=$WORK/tmp
+ exe=
+
+ # GOPATH with p1 in d2, p2 in d2 (0.000s)
+ # build & install p1 (0.085s)
+ # modify p2 - p1 should appear stale (0.030s)
+ # build & install p1 again (0.019s)
+ > go install -i p11
+ [stderr]
+ can't load package: package p11: cannot find package "p11" in any of:
+ /Users/rsc/go/src/p11 (from $GOROOT)
+ $WORK/d1/src/p11 (from $GOPATH)
+ $WORK/d2/src/p11
+ [exit status 1]
+ FAIL: unexpected go command failure
+
+ script_test.go:73: failed at testdata/script/install_rebuild_gopath.txt:15 in $WORK/gopath/src
+
+ FAIL
+ exit status 1
+ FAIL cmd/go 4.875s
+ $
+
+ $ WORK=/tmp/cmd-go-test-745953508/script-install_rebuild_gopath
+ $ cd $WORK/d1/src/p1
+ $ cat p1.go
+ package p1
+ import "p2"
+ func F() { p2.F() }
+ $
+
+The available commands are:
+cat files...
+ concatenate files and print to the script's stdout buffer
+
+
+cc args...
+ run the platform C compiler
+
+
+cd dir
+ change the working directory
+
+
+chmod perm paths...
+ change file mode bits
+
+ Changes the permissions of the named files or directories to
+ be equal to perm.
+ Only numerical permissions are supported.
+
+cmp [-q] file1 file2
+ compare files for differences
+
+ By convention, file1 is the actual data and file2 is the
+ expected data.
+ The command succeeds if the file contents are identical.
+ File1 can be 'stdout' or 'stderr' to compare the stdout or
+ stderr buffer from the most recent command.
+
+cmpenv [-q] file1 file2
+ compare files for differences, with environment expansion
+
+ By convention, file1 is the actual data and file2 is the
+ expected data.
+ The command succeeds if the file contents are identical
+ after substituting variables from the script environment.
+ File1 can be 'stdout' or 'stderr' to compare the script's
+ stdout or stderr buffer.
+
+cp src... dst
+ copy files to a target file or directory
+
+ src can include 'stdout' or 'stderr' to copy from the
+ script's stdout or stderr buffer.
+
+echo string...
+ display a line of text
+
+
+env [key[=value]...]
+ set or log the values of environment variables
+
+ With no arguments, print the script environment to the log.
+ Otherwise, add the listed key=value pairs to the environment
+ or print the listed keys.
+
+exec program [args...] [&]
+ run an executable program with arguments
+
+ Note that 'exec' does not terminate the script (unlike Unix
+ shells).
+
+exists [-readonly] [-exec] file...
+ check that files exist
+
+
+go [args...] [&]
+ run the 'go' program provided by the script host
+
+
+grep [-count=N] [-q] 'pattern' file
+ find lines in a file that match a pattern
+
+ The command succeeds if at least one match (or the exact
+ count, if given) is found.
+ The -q flag suppresses printing of matches.
+
+help [-v] name...
+ log help text for commands and conditions
+
+ To display help for a specific condition, enclose it in
+ brackets: 'help [amd64]'.
+ To display complete documentation when listing all commands,
+ pass the -v flag.
+
+mkdir path...
+ create directories, if they do not already exist
+
+ Unlike Unix mkdir, parent directories are always created if
+ needed.
+
+mv old new
+ rename a file or directory to a new path
+
+ OS-specific restrictions may apply when old and new are in
+ different directories.
+
+replace [old new]... file
+ replace strings in a file
+
+ The 'old' and 'new' arguments are unquoted as if in quoted
+ Go strings.
+
+rm path...
+ remove a file or directory
+
+ If the path is a directory, its contents are removed
+ recursively.
+
+skip [msg]
+ skip the current test
+
+
+sleep duration [&]
+ sleep for a specified duration
+
+ The duration must be given as a Go time.Duration string.
+
+stale target...
+ check that build targets are stale
+
+
+stderr [-count=N] [-q] 'pattern' file
+ find lines in the stderr buffer that match a pattern
+
+ The command succeeds if at least one match (or the exact
+ count, if given) is found.
+ The -q flag suppresses printing of matches.
+
+stdout [-count=N] [-q] 'pattern' file
+ find lines in the stdout buffer that match a pattern
+
+ The command succeeds if at least one match (or the exact
+ count, if given) is found.
+ The -q flag suppresses printing of matches.
+
+stop [msg]
+ stop execution of the script
+
+ The message is written to the script log, but no error is
+ reported from the script engine.
+
+symlink path -> target
+ create a symlink
+
+ Creates path as a symlink to target.
+ The '->' token (like in 'ls -l' output on Unix) is required.
+
+wait
+ wait for completion of background commands
+
+ Waits for all background commands to complete.
+ The output (and any error) from each command is printed to
+ the log in the order in which the commands were started.
+ After the call to 'wait', the script's stdout and stderr
+ buffers contain the concatenation of the background
+ commands' outputs.
+
+
+
+The available conditions are:
+[GOARCH:*]
+ runtime.GOARCH == <suffix>
+[GODEBUG:*]
+ GODEBUG contains <suffix>
+[GOEXPERIMENT:*]
+ GOEXPERIMENT <suffix> is enabled
+[GOOS:*]
+ runtime.GOOS == <suffix>
+[abscc]
+ default $CC path is absolute and exists
+[asan]
+ GOOS/GOARCH supports -asan
+[buildmode:*]
+ go supports -buildmode=<suffix>
+[case-sensitive]
+ $WORK filesystem is case-sensitive
+[cc:*]
+ go env CC = <suffix> (ignoring the go/env file)
+[cgo]
+ host CGO_ENABLED
+[cgolinkext]
+ platform requires external linking for cgo
+[compiler:*]
+ runtime.Compiler == <suffix>
+[cross]
+ cmd/go GOOS/GOARCH != GOHOSTOS/GOHOSTARCH
+[exec:*]
+ <suffix> names an executable in the test binary's PATH
+[fuzz]
+ GOOS/GOARCH supports -fuzz
+[fuzz-instrumented]
+ GOOS/GOARCH supports -fuzz with instrumentation
+[git]
+ the 'git' executable exists and provides the standard CLI
+[go-builder]
+ GO_BUILDER_NAME is non-empty
+[link]
+ testenv.HasLink()
+[mismatched-goroot]
+ test's GOROOT_FINAL does not match the real GOROOT
+[msan]
+ GOOS/GOARCH supports -msan
+[mustlinkext]
+ platform always requires external linking
+[net:*]
+ can connect to external network host <suffix>
+[race]
+ GOOS/GOARCH supports -race
+[root]
+ os.Geteuid() == 0
+[short]
+ testing.Short()
+[symlink]
+ testenv.HasSymlink()
+[trimpath]
+ test binary was built with -trimpath
+[verbose]
+ testing.Verbose()
+
diff --git a/src/cmd/go/testdata/script/autocgo.txt b/src/cmd/go/testdata/script/autocgo.txt
new file mode 100644
index 0000000..586c802
--- /dev/null
+++ b/src/cmd/go/testdata/script/autocgo.txt
@@ -0,0 +1,29 @@
+# Test automatic setting of CGO_ENABLED based on $CC and what's in $PATH.
+
+[!cgo] skip
+[cross] skip
+
+# Assume we're on a system that can enable cgo normally.
+env CGO_ENABLED=
+go env CGO_ENABLED
+stdout 1
+
+# Clearing CC and removing everything but Go from the PATH should usually
+# disable cgo: no C compiler anymore (unless the baked-in defaultCC is an
+# absolute path and exists.
+env CC=
+env PATH=$GOROOT/bin
+go env CGO_ENABLED
+[!abscc] stdout 0
+[abscc] stdout 1
+
+# Setting CC should re-enable cgo.
+env CC=cc
+go env CGO_ENABLED
+stdout 1
+
+# So should setting CGO_ENABLED.
+env CC=
+env CGO_ENABLED=1
+go env CGO_ENABLED
+stdout 1
diff --git a/src/cmd/go/testdata/script/badgo.txt b/src/cmd/go/testdata/script/badgo.txt
new file mode 100644
index 0000000..cf4e258
--- /dev/null
+++ b/src/cmd/go/testdata/script/badgo.txt
@@ -0,0 +1,50 @@
+go get example.net/badgo@v1.0.0
+go get example.net/badgo@v1.1.0
+go get example.net/badgo@v1.2.0
+go get example.net/badgo@v1.3.0
+go get example.net/badgo@v1.4.0
+go get example.net/badgo@v1.5.0
+! go get example.net/badgo@v1.6.0
+stderr 'invalid go version .X.Y.: must match format 1.23'
+
+-- go.mod --
+module m
+
+replace (
+ example.net/badgo v1.0.0 => ./v1.0.0
+ example.net/badgo v1.1.0 => ./v1.1.0
+ example.net/badgo v1.2.0 => ./v1.2.0
+ example.net/badgo v1.3.0 => ./v1.3.0
+ example.net/badgo v1.4.0 => ./v1.4.0
+ example.net/badgo v1.5.0 => ./v1.5.0
+ example.net/badgo v1.6.0 => ./v1.6.0
+)
+
+-- v1.0.0/go.mod --
+module example.net/badgo
+go 1.17.0
+
+-- v1.1.0/go.mod --
+module example.net/badgo
+go 1.17rc2
+
+-- v1.2.0/go.mod --
+module example.net/badgo
+go 1.17.1
+
+-- v1.3.0/go.mod --
+module example.net/badgo
+go v1.17.0
+
+-- v1.4.0/go.mod --
+module example.net/badgo
+go v1.17.0-rc.2
+
+-- v1.5.0/go.mod --
+module example.net/badgo
+go v1.17.1
+
+-- v1.6.0/go.mod --
+module example.net/badgo
+go X.Y
+
diff --git a/src/cmd/go/testdata/script/bug.txt b/src/cmd/go/testdata/script/bug.txt
new file mode 100644
index 0000000..f64fb85
--- /dev/null
+++ b/src/cmd/go/testdata/script/bug.txt
@@ -0,0 +1,58 @@
+# Verify that go bug creates the appropriate URL issue body
+
+[!GOOS:linux] skip
+[short] skip
+
+go install
+go build -o $TMPDIR/go ./go
+env BROWSER=$GOPATH/bin/browser PATH=$TMPDIR:$PATH
+go bug
+exists $TMPDIR/browser
+grep '^go version' $TMPDIR/browser
+grep '^GOROOT/bin/go version: go version' $TMPDIR/browser
+grep '^GOROOT/bin/go tool compile -V: compile version' $TMPDIR/browser
+grep '^uname -sr: Linux' $TMPDIR/browser
+
+-- go.mod --
+module browser
+
+-- main.go --
+package main
+
+import (
+ "fmt"
+ "net/url"
+ "os"
+ "path/filepath"
+)
+
+func main() {
+ u, err := url.Parse(os.Args[1])
+ if err != nil {
+ panic(err)
+ }
+ body, err := url.PathUnescape(u.Query().Get("body"))
+ if err != nil {
+ panic(err)
+ }
+ out := filepath.Join(os.TempDir(), "browser")
+ f, err := os.Create(out)
+ if err != nil {
+ panic(err)
+ }
+ fmt.Fprintln(f, body)
+ if err := f.Close(); err != nil {
+ panic(err)
+ }
+}
+
+-- go/main.go --
+package main
+
+import (
+ "os"
+)
+
+func main() {
+ os.Exit(1)
+}
diff --git a/src/cmd/go/testdata/script/build_GOTMPDIR.txt b/src/cmd/go/testdata/script/build_GOTMPDIR.txt
new file mode 100644
index 0000000..4c9129e
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_GOTMPDIR.txt
@@ -0,0 +1,50 @@
+# Set GOCACHE to a clean directory to ensure that 'go build' has work to report.
+[!GOOS:windows] env GOCACHE=$WORK/gocache
+[GOOS:windows] env GOCACHE=$WORK\gocache
+
+# 'go build' should use GOTMPDIR if set.
+[!GOOS:windows] env GOTMPDIR=$WORK/my-favorite-tmpdir
+[GOOS:windows] env GOTMPDIR=$WORK\my-favorite-tmpdir
+mkdir $GOTMPDIR
+go build -x hello.go
+stderr ^WORK=.*my-favorite-tmpdir
+
+# Make GOTMPDIR a regular file. This prevents the creation of work directories,
+# so we can check that certain commands don't create them.
+# This simulates running on a full disk or a read-only volume.
+rm $GOTMPDIR
+cp hello.go $GOTMPDIR # any file will do
+
+# 'go build' should fail if GOTMPDIR is read-only.
+! go build -x .
+stderr '^go: creating work dir: \w+ '$GOTMPDIR
+
+# 'go list' should only fail if it needs to build something.
+go list -x .
+! stderr 'creating work dir'
+stdout m
+go list -m all
+stdout m
+! go list -x -export .
+stderr '^go: creating work dir: \w+ '$GOTMPDIR
+
+# 'go clean -cache' and 'go clean -modcache' should not fail.
+go clean -x -cache
+! stderr 'creating work dir'
+go clean -x -modcache
+! stderr 'creating work dir'
+
+# 'go env' should not fail for specific variables.
+# Without arguments, it needs to initialize a builder to load cgo flags, and
+# that uses a temporary directory.
+! go env
+stderr '^go: creating work dir: \w+ '$GOTMPDIR
+go env GOROOT
+
+-- go.mod --
+module m
+
+go 1.15
+-- hello.go --
+package main
+func main() { println("hello") }
diff --git a/src/cmd/go/testdata/script/build_acl_windows.txt b/src/cmd/go/testdata/script/build_acl_windows.txt
new file mode 100644
index 0000000..2cb60e0
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_acl_windows.txt
@@ -0,0 +1,44 @@
+[!GOOS:windows] stop
+[!exec:icacls] skip
+[!exec:powershell] skip
+
+# Create $WORK\guest and give the Guests group full access.
+# Files created within that directory will have different security attributes by default.
+mkdir $WORK\guest
+exec icacls $WORK\guest /grant '*S-1-5-32-546:(oi)(ci)f'
+
+env TMP=$WORK\guest
+env TEMP=$WORK\guest
+
+# Build a binary using the guest directory as an intermediate
+cd TestACL
+go build -o main.exe main.go
+# Build the same binary, but write it to the guest directory.
+go build -o $TMP\main.exe main.go
+
+# Read ACLs for the files.
+exec powershell -Command 'Get-Acl main.exe | Select -expand AccessToString'
+cp stdout $WORK\exe-acl.txt
+exec powershell -Command 'Get-Acl main.go | Select -expand AccessToString'
+cp stdout $WORK\src-acl.txt
+cd $TMP
+exec powershell -Command 'Get-Acl main.exe | Select -expand AccessToString'
+cp stdout $WORK\guest-acl.txt
+
+cd $WORK
+
+# The executable written to the source directory should have the same ACL as the source file.
+cmp $WORK\exe-acl.txt $WORK\src-acl.txt
+
+# The file written to the guest-allowed directory should give Guests control.
+grep 'BUILTIN\\Guests\s+Allow' $WORK\guest-acl.txt
+
+# The file written to the ordinary directory should not.
+! grep 'BUILTIN\\Guests\s+Allow' $WORK\exe-acl.txt
+
+
+-- TestACL/go.mod --
+module TestACL
+-- TestACL/main.go --
+package main
+func main() {}
diff --git a/src/cmd/go/testdata/script/build_arm.txt b/src/cmd/go/testdata/script/build_arm.txt
new file mode 100644
index 0000000..ff2a364
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_arm.txt
@@ -0,0 +1,13 @@
+[short] skip 'skipping cross-compile in short mode'
+
+env GOARCH=arm
+env GOOS=linux
+env GOARM=5
+
+go build hello.go
+! stderr 'unable to find math.a'
+
+-- hello.go --
+package main
+
+func main() {} \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/build_buildvcs_auto.txt b/src/cmd/go/testdata/script/build_buildvcs_auto.txt
new file mode 100644
index 0000000..cfd5d82
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_buildvcs_auto.txt
@@ -0,0 +1,91 @@
+# Regression test for https://go.dev/issue/51748: by default, 'go build' should
+# not attempt to stamp VCS information when the VCS tool is not present.
+
+[short] skip
+[!git] skip
+
+cd sub
+exec git init .
+exec git config user.name 'Nameless Gopher'
+exec git config user.email 'nobody@golang.org'
+exec git add sub.go
+exec git commit -m 'initial state'
+cd ..
+
+exec git init
+exec git config user.name 'Nameless Gopher'
+exec git config user.email 'nobody@golang.org'
+exec git submodule add ./sub
+exec git add go.mod example.go
+exec git commit -m 'initial state'
+
+
+# Control case: with a git binary in $PATH,
+# 'go build' on a package in the same git repo
+# succeeds and stamps VCS metadata by default.
+
+go build -o example.exe .
+go version -m example.exe
+stdout '^\tbuild\tvcs=git$'
+stdout '^\tbuild\tvcs.modified=false$'
+
+
+# Building a binary from a different (nested) VCS repo should not stamp VCS
+# info. It should be an error if VCS stamps are requested explicitly with
+# '-buildvcs' (since we know the VCS metadata exists), but not an error
+# with '-buildvcs=auto'.
+
+go build -o sub.exe ./sub
+go version -m sub.exe
+! stdout '^\tbuild\tvcs'
+
+! go build -buildvcs -o sub.exe ./sub
+stderr '\Aerror obtaining VCS status: main package is in repository ".*" but current directory is in repository ".*"\n\tUse -buildvcs=false to disable VCS stamping.\n\z'
+
+cd ./sub
+go build -o sub.exe .
+go version -m sub.exe
+! stdout '^\tbuild\tvcs'
+
+! go build -buildvcs -o sub.exe .
+stderr '\Aerror obtaining VCS status: main module is in repository ".*" but current directory is in repository ".*"\n\tUse -buildvcs=false to disable VCS stamping.\n\z'
+cd ..
+
+
+# After removing 'git' from $PATH, 'go build -buildvcs' should fail...
+
+env PATH=
+env path=
+! go build -buildvcs -o example.exe .
+stderr 'go: missing Git command\. See https://golang\.org/s/gogetcmd$'
+
+# ...but by default we should omit VCS metadata when the tool is missing.
+
+go build -o example.exe .
+go version -m example.exe
+! stdout '^\tbuild\tvcs'
+
+# The default behavior can be explicitly set with '-buildvcs=auto'.
+
+go build -buildvcs=auto -o example.exe .
+go version -m example.exe
+! stdout '^\tbuild\tvcs'
+
+# Other flag values should be rejected with a useful error message.
+
+! go build -buildvcs=hg -o example.exe .
+stderr '\Ainvalid boolean value "hg" for -buildvcs: value is neither ''auto'' nor a valid bool\nusage: go build .*\nRun ''go help build'' for details.\n\z'
+
+
+-- go.mod --
+module example
+
+go 1.18
+-- example.go --
+package main
+
+func main() {}
+-- sub/sub.go --
+package main
+
+func main() {}
diff --git a/src/cmd/go/testdata/script/build_cache_arch_mode.txt b/src/cmd/go/testdata/script/build_cache_arch_mode.txt
new file mode 100644
index 0000000..931827f
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_cache_arch_mode.txt
@@ -0,0 +1,21 @@
+# Issue 9737: verify that GOARM affects the computed build ID
+
+[short] skip
+
+# arm
+env GOOS=linux
+env GOARCH=arm
+env GOARM=5
+go install mycmd
+env GOARM=7
+stale mycmd
+
+
+-- go.mod --
+module mycmd
+
+go 1.16
+-- x.go --
+package main
+
+func main() {}
diff --git a/src/cmd/go/testdata/script/build_cache_compile.txt b/src/cmd/go/testdata/script/build_cache_compile.txt
new file mode 100644
index 0000000..64b391f
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_cache_compile.txt
@@ -0,0 +1,21 @@
+env GO111MODULE=off
+[short] skip
+
+# Set up fresh GOCACHE.
+env GOCACHE=$WORK/gocache
+mkdir $GOCACHE
+
+# Building trivial non-main package should run compiler the first time.
+go build -x lib.go
+stderr '(compile|gccgo)( |\.exe).*lib\.go'
+
+# ... but not again ...
+go build -x lib.go
+! stderr '(compile|gccgo)( |\.exe).*lib\.go'
+
+# ... unless we use -a.
+go build -a -x lib.go
+stderr '(compile|gccgo)( |\.exe)'
+
+-- lib.go --
+package lib
diff --git a/src/cmd/go/testdata/script/build_cache_disabled.txt b/src/cmd/go/testdata/script/build_cache_disabled.txt
new file mode 100644
index 0000000..cb1a755
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_cache_disabled.txt
@@ -0,0 +1,50 @@
+# The build cache is required to build anything. It also may be needed to
+# initialize the build system, which is needed for commands like 'go env'.
+# However, there are lots of commands the cache is not needed for, and we
+# shouldn't require it when it won't be used.
+#
+# TODO(golang.org/issue/39882): commands below should work, too.
+# * go clean -modcache
+# * go env
+# * go fix
+# * go fmt
+# * go generate
+# * go get
+# * go list (without -export or -compiled)
+
+env GOCACHE=off
+
+# Commands that don't completely load packages should work.
+go doc fmt
+stdout Printf
+
+! go tool compile -h
+stderr usage:
+
+go version
+stdout '^go version'
+
+
+# Module commands that don't load packages should work.
+go mod init m
+exists go.mod
+
+go mod edit -require rsc.io/quote@v1.5.2
+
+go mod download rsc.io/quote
+
+go mod graph
+stdout rsc.io/quote
+
+go mod verify
+
+
+# Commands that load but don't build packages should work.
+go fmt .
+
+go doc .
+
+-- main.go --
+package main
+
+func main() {}
diff --git a/src/cmd/go/testdata/script/build_cache_gomips.txt b/src/cmd/go/testdata/script/build_cache_gomips.txt
new file mode 100644
index 0000000..0cbf16a
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_cache_gomips.txt
@@ -0,0 +1,40 @@
+env GO111MODULE=off
+[short] skip # rebuilds std for mips
+
+# Set up fresh GOCACHE.
+env GOCACHE=$WORK/gocache
+mkdir $GOCACHE
+
+# Building for mipsle without setting GOMIPS will use floating point registers.
+env GOARCH=mipsle
+env GOOS=linux
+go build -gcflags=-S f.go
+stderr ADDD.F[0-9]+,.F[0-9]+,.F[0-9]+
+
+# Clean cache
+go clean -cache
+
+# Building with GOMIPS=softfloat will not use floating point registers
+env GOMIPS=softfloat
+go build -gcflags=-S f.go
+! stderr ADDD.F[0-9]+,.F[0-9]+,.F[0-9]+
+
+# Clean cache
+go clean -cache
+
+# Build without setting GOMIPS
+env GOMIPS=
+go build -gcflags=-S f.go
+stderr ADDD.F[0-9]+,.F[0-9]+,.F[0-9]+
+
+# Building with GOMIPS should still not use floating point registers.
+env GOMIPS=softfloat
+go build -gcflags=-S f.go
+! stderr ADDD.F[0-9]+,.F[0-9]+,.F[0-9]+
+
+-- f.go --
+package f
+
+func F(x float64) float64 {
+ return x + x
+}
diff --git a/src/cmd/go/testdata/script/build_cache_link.txt b/src/cmd/go/testdata/script/build_cache_link.txt
new file mode 100644
index 0000000..b9c740a
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_cache_link.txt
@@ -0,0 +1,26 @@
+env GO111MODULE=off
+[short] skip
+
+# Set up fresh GOCACHE.
+env GOCACHE=$WORK/gocache
+mkdir $GOCACHE
+
+# Building a main package should run the compiler and linker ...
+go build -o $devnull -x main.go
+stderr '(compile|gccgo)( |\.exe).*main\.go'
+stderr '(link|gccgo)( |\.exe)'
+
+# ... and then the linker again ...
+go build -o $devnull -x main.go
+! stderr '(compile|gccgo)( |\.exe).*main\.go'
+stderr '(link|gccgo)( |\.exe)'
+
+# ... but the output binary can serve as a cache.
+go build -o main$GOEXE -x main.go
+stderr '(link|gccgo)( |\.exe)'
+go build -o main$GOEXE -x main.go
+! stderr '(link|gccgo)( |\.exe)'
+
+-- main.go --
+package main
+func main() {}
diff --git a/src/cmd/go/testdata/script/build_cache_output.txt b/src/cmd/go/testdata/script/build_cache_output.txt
new file mode 100644
index 0000000..fc040b4
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_cache_output.txt
@@ -0,0 +1,67 @@
+env GO111MODULE=off
+env GODEBUG=gocachetest=1
+
+[!compiler:gc] skip
+[short] skip # clears cache, rebuilds too much
+
+# Set up fresh GOCACHE.
+env GOCACHE=$WORK/gocache
+mkdir $GOCACHE
+
+# Building a trivial non-main package should run compiler the first time.
+go build -x -gcflags=-m lib.go
+stderr 'compile( |\.exe"?)'
+stderr 'lib.go:2.* can inline f'
+
+# ... but not the second, even though it still prints the compiler output.
+go build -x -gcflags=-m lib.go
+! stderr 'compile( |\.exe"?)'
+stderr 'lib.go:2.* can inline f'
+
+# Building a trivial main package should run the compiler and linker the first time.
+go build -x -gcflags=-m -ldflags='-v -w' main.go
+stderr 'compile( |\.exe"?)'
+stderr 'main.go:2.* can inline main' # from compiler
+stderr 'link(\.exe"?)? -'
+stderr '\d+ symbols' # from linker
+
+# ... but not the second, even though it still prints the compiler and linker output.
+go build -x -gcflags=-m -ldflags='-v -w' main.go
+! stderr 'compile( |\.exe"?)'
+stderr 'main.go:2.* can inline main' # from compiler
+! stderr 'link(\.exe"?)? -'
+stderr '\d+ symbols' # from linker
+
+# Running a test should run the compiler, linker, and the test the first time.
+go test -v -x -gcflags=-m -ldflags=-v p
+stderr 'compile( |\.exe"?)'
+stderr 'p_test.go:.*can inline Test' # from compile of p_test
+stderr 'testmain\.go:.*inlin' # from compile of testmain
+stderr 'link(\.exe"?)? -'
+stderr '\d+ symbols' # from linker
+stderr 'p\.test( |\.exe"?)'
+stdout 'TEST' # from test
+
+# ... but not the second, even though it still prints the compiler, linker, and test output.
+go test -v -x -gcflags=-m -ldflags=-v p
+! stderr 'compile( |\.exe"?)'
+stderr 'p_test.go:.*can inline Test' # from compile of p_test
+stderr 'testmain\.go:.*inlin' # from compile of testmain
+! stderr 'link(\.exe"?)? -'
+stderr '\d+ symbols' # from linker
+! stderr 'p\.test( |\.exe"?)'
+stdout 'TEST' # from test
+
+
+-- lib.go --
+package p
+func f(x *int) *int { return x }
+
+-- main.go --
+package main
+func main() {}
+
+-- p/p_test.go --
+package p
+import "testing"
+func Test(t *testing.T) {println("TEST")}
diff --git a/src/cmd/go/testdata/script/build_cache_trimpath.txt b/src/cmd/go/testdata/script/build_cache_trimpath.txt
new file mode 100644
index 0000000..7ee3c3b
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_cache_trimpath.txt
@@ -0,0 +1,47 @@
+[short] skip
+env GO111MODULE=on
+
+# Set up fresh GOCACHE.
+env GOCACHE=$WORK/gocache
+mkdir $GOCACHE
+
+cd $WORK
+go build -o a.out
+
+# Varying -trimpath should cause a rebuild.
+go build -x -o a.out -trimpath
+stderr '(compile|gccgo)( |\.exe)'
+stderr 'link( |\.exe)'
+
+# Two distinct versions of the same module with identical content should
+# still be cached separately.
+# Verifies golang.org/issue/35412.
+go get example.com/stack@v1.0.0
+go run -trimpath printstack.go
+stdout '^example.com/stack@v1.0.0/stack.go$'
+go get example.com/stack@v1.0.1
+go run -trimpath printstack.go
+stdout '^example.com/stack@v1.0.1/stack.go$'
+
+-- $WORK/hello.go --
+package main
+func main() { println("hello") }
+
+-- $WORK/printstack.go --
+// +build ignore
+
+package main
+
+import (
+ "fmt"
+
+ "example.com/stack"
+)
+
+func main() {
+ fmt.Println(stack.TopFile())
+}
+-- $WORK/go.mod --
+module m
+
+go 1.14
diff --git a/src/cmd/go/testdata/script/build_cc_cache_issue64423.txt b/src/cmd/go/testdata/script/build_cc_cache_issue64423.txt
new file mode 100644
index 0000000..f1bc2c3
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_cc_cache_issue64423.txt
@@ -0,0 +1,121 @@
+# Regression test for https://go.dev/issue/64423:
+#
+# When we parse the version for a Clang binary, we should accept
+# an arbitrary vendor prefix, which (as of 2023) may be injected
+# by defining CLANG_VENDOR when building clang itself.
+#
+# Since we don't want to actually rebuild the Clang toolchain in
+# this test, we instead simulate it by injecting a fake "clang"
+# binary that runs the real one as a subprocess.
+
+[!cgo] skip
+[short] skip 'builds and links a fake clang binary'
+[!cc:clang] skip 'test is specific to clang version parsing'
+
+# Save the location of the real clang command for our fake one to use.
+go run ./which clang
+cp stdout $WORK/.realclang
+
+# Build a fake clang and ensure that it is the one in $PATH.
+mkdir $WORK/bin
+go build -o $WORK/bin/clang$GOEXE ./fakeclang
+[!GOOS:plan9] env PATH=$WORK${/}bin
+[GOOS:plan9] env path=$WORK${/}bin
+
+# Force CGO_ENABLED=1 so that the following commands should error
+# out if the fake clang doesn't work.
+env CGO_ENABLED=1
+
+# The bug in https://go.dev/issue/64423 resulted in cache keys that
+# didn't contain any information about the C compiler.
+# Since the bug was in cache key computation, isolate the cache:
+# if we change the way caching works, we want the test to fail
+# instead of accidentally reusing the cached information from a
+# previous test run.
+env GOCACHE=$WORK${/}.cache
+mkdir $GOCACHE
+
+go build -x runtime/cgo
+
+ # Tell our fake clang to stop working.
+ # Previously, 'go build -x runtime/cgo' would continue to
+ # succeed because both the broken clang and the non-broken one
+ # resulted in a cache key with no clang version information.
+env GO_BREAK_CLANG=1
+! go build -x runtime/cgo
+stderr '# runtime/cgo\nGO_BREAK_CLANG is set'
+
+-- go.mod --
+module example/issue64423
+go 1.20
+-- which/main.go --
+package main
+
+import (
+ "os"
+ "os/exec"
+)
+
+func main() {
+ path, err := exec.LookPath(os.Args[1])
+ if err != nil {
+ panic(err)
+ }
+ os.Stdout.WriteString(path)
+}
+-- fakeclang/main.go --
+package main
+
+import (
+ "bufio"
+ "bytes"
+ "log"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+)
+
+func main() {
+ if os.Getenv("GO_BREAK_CLANG") != "" {
+ os.Stderr.WriteString("GO_BREAK_CLANG is set\n")
+ os.Exit(1)
+ }
+
+ b, err := os.ReadFile(filepath.Join(os.Getenv("WORK"), ".realclang"))
+ if err != nil {
+ log.Fatal(err)
+ }
+ clang := string(bytes.TrimSpace(b))
+ cmd := exec.Command(clang, os.Args[1:]...)
+ cmd.Stdout = os.Stdout
+ stderr, err := cmd.StderrPipe()
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ if err := cmd.Start(); err != nil {
+ log.Fatal(err)
+ }
+
+ r := bufio.NewReader(stderr)
+ for {
+ line, err := r.ReadString('\n')
+ if line != "" {
+ if strings.Contains(line, "clang version") {
+ // Simulate a clang version string with an arbitrary vendor prefix.
+ const vendorString = "Gopher Solutions Unlimited "
+ os.Stderr.WriteString(vendorString)
+ }
+ os.Stderr.WriteString(line)
+ }
+ if err != nil {
+ break
+ }
+ }
+ os.Stderr.Close()
+
+ if err := cmd.Wait(); err != nil {
+ os.Exit(1)
+ }
+}
diff --git a/src/cmd/go/testdata/script/build_cd_gopath_different.txt b/src/cmd/go/testdata/script/build_cd_gopath_different.txt
new file mode 100644
index 0000000..64d7d74
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_cd_gopath_different.txt
@@ -0,0 +1,73 @@
+[compiler:gccgo] skip 'gccgo does not support -ldflags -X'
+env GO111MODULE=off
+go build run_go.go
+
+# Apply identity function to GOPATH
+exec ./run_go$GOEXE $GOPATH/src/my.pkg/main $GOPATH IDENTITY build -o $WORK/tmp/a.exe -ldflags -X=my.pkg.Text=linkXworked
+exec $WORK/tmp/a.exe
+stderr 'linkXworked'
+rm $WORK/tmp/a.exe
+
+[!GOOS:windows] stop 'rest of the tests only apply to Windows'
+
+# Replace '\' with '/' in GOPATH
+exec ./run_go$GOEXE $GOPATH/src/my.pkg/main $GOPATH REPLACE_SLASH build -o $WORK/tmp/a.exe -ldflags -X=my.pkg.Text=linkXworked
+exec $WORK/tmp/a.exe
+stderr 'linkXworked'
+rm $WORK/tmp/a.exe
+
+# Apply identity function to GOPATH
+exec ./run_go$GOEXE $GOPATH/src/my.pkg/main $GOPATH UPPER build -o $WORK/tmp/a.exe -ldflags -X=my.pkg.Text=linkXworked
+exec $WORK/tmp/a.exe
+stderr 'linkXworked'
+rm $WORK/tmp/a.exe
+
+# Apply identity function to GOPATH
+exec ./run_go$GOEXE $GOPATH/src/my.pkg/main $GOPATH LOWER build -o $WORK/tmp/a.exe -ldflags -X=my.pkg.Text=linkXworked
+exec $WORK/tmp/a.exe
+stderr 'linkXworked'
+rm $WORK/tmp/a.exe
+
+-- run_go.go --
+package main
+
+import (
+ "fmt"
+ "os"
+ "os/exec"
+ "strings"
+)
+
+func main() {
+ dir := os.Args[1]
+ gopath := os.Args[2]
+ switch os.Args[3] {
+ case "IDENTITY":
+ case "REPLACE_SLASH": gopath = strings.ReplaceAll(gopath, `\`, `/`)
+ case "UPPER": gopath = strings.ToUpper(gopath)
+ case "LOWER": gopath = strings.ToLower(gopath)
+ default: fmt.Fprintln(os.Stderr, "bad op"); os.Exit(1)
+ }
+ cmd := exec.Command("go", os.Args[4:]...)
+ cmd.Dir = dir
+ cmd.Env = append(os.Environ(), "GOPATH="+gopath)
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ if err := cmd.Run(); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+}
+
+-- my.pkg/main/main.go --
+package main
+
+import "my.pkg"
+
+func main() {
+ println(pkg.Text)
+}
+-- my.pkg/pkg.go --
+package pkg
+
+var Text = "unset"
diff --git a/src/cmd/go/testdata/script/build_cgo_consistent_results.txt b/src/cmd/go/testdata/script/build_cgo_consistent_results.txt
new file mode 100644
index 0000000..f22994f
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_cgo_consistent_results.txt
@@ -0,0 +1,23 @@
+[short] skip
+[!cgo] skip
+
+[GOOS:solaris] skip "skipping on Solaris; see golang.org/issue/13247"
+[GOOS:illumos] skip "skipping on Solaris; see golang.org/issue/13247"
+
+go build -o $WORK/exe1$GOEXE cgotest
+go build -x -o $WORK/exe2$GOEXE cgotest
+
+# TODO(matloob): skip if stderr does not contain '-fdebug-prefix-map=\$WORK'
+
+cmp $WORK/exe1$GOEXE $WORK/exe2$GOEXE
+
+-- go.mod --
+module cgotest
+
+go 1.16
+-- m.go --
+package cgotest
+
+import "C"
+
+var _ C.int
diff --git a/src/cmd/go/testdata/script/build_cgo_error.txt b/src/cmd/go/testdata/script/build_cgo_error.txt
new file mode 100644
index 0000000..c11ab46
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_cgo_error.txt
@@ -0,0 +1,17 @@
+[short] skip
+[!cgo] skip
+
+! go build .
+stderr '# foo\nfoo.c:'
+! stderr 'EXTRA string'
+
+-- go.mod --
+module foo
+
+go 1.20
+-- foo.go --
+package foo
+
+import "C"
+-- foo.c --
+#include "doesnotexist.h" \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/build_concurrent_backend.txt b/src/cmd/go/testdata/script/build_concurrent_backend.txt
new file mode 100644
index 0000000..9cac635
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_concurrent_backend.txt
@@ -0,0 +1,10 @@
+# Tests golang.org/issue/48490
+# cmd/go should enable concurrent compilation by default
+
+# Reset all experiments, since one of them can disable
+# concurrent compilation, e.g: fieldtrack.
+env GOEXPERIMENT=none
+
+env GOMAXPROCS=4
+go build -n -x -a fmt
+stderr ' -c=4 '
diff --git a/src/cmd/go/testdata/script/build_cwd_newline.txt b/src/cmd/go/testdata/script/build_cwd_newline.txt
new file mode 100644
index 0000000..91cb57f
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_cwd_newline.txt
@@ -0,0 +1,138 @@
+[GOOS:windows] skip 'filesystem normalizes / to \'
+[GOOS:plan9] skip 'filesystem disallows \n in paths'
+
+# If the directory path containing a package to be built includes a newline,
+# the go command should refuse to even try to build the package.
+
+env DIR=$WORK${/}${newline}'package main'${newline}'func main() { panic("uh-oh")'${newline}'/*'
+
+mkdir $DIR
+cd $DIR
+exec pwd
+cp $WORK/go.mod ./go.mod
+cp $WORK/main.go ./main.go
+cp $WORK/main_nocgo.go ./main_nocgo.go
+cp $WORK/main_test.go ./main_test.go
+
+! go build -o $devnull .
+stderr 'package example: invalid package directory .*uh-oh'
+
+[cgo] ! go build -o $devnull main.go
+[!cgo] ! go build -o $devnull main_nocgo.go
+stderr 'package command-line-arguments: invalid package directory .*uh-oh'
+
+! go run .
+stderr 'package example: invalid package directory .*uh-oh'
+
+[cgo] ! go run main.go
+[!cgo] ! go run main_nocgo.go
+stderr 'package command-line-arguments: invalid package directory .*uh-oh'
+
+! go test .
+stderr 'package example: invalid package directory .*uh-oh'
+
+[cgo] ! go test -v main.go main_test.go
+[!cgo] ! go test -v main_nocgo.go main_test.go
+stderr 'package command-line-arguments: invalid package directory .*uh-oh'
+
+go list -compiled -e -f '{{with .CompiledGoFiles}}{{.}}{{end}}' .
+! stdout .
+! stderr .
+! exists obj_
+
+
+# The cgo tool should only accept the source file if the working directory
+# is not written in line directives in the resulting files.
+
+[cgo] ! go tool cgo main.go
+[cgo] stderr 'cgo: input path contains newline character: .*uh-oh'
+[cgo] ! exists _obj
+
+[cgo] go tool cgo -trimpath=$PWD main.go
+[cgo] grep '//line main\.go:1:1' _obj/main.cgo1.go
+[cgo] ! grep 'uh-oh' _obj/main.cgo1.go
+[cgo] rm _obj
+
+
+# Since we do preserve $PWD (or set it appropriately) for commands, and we do
+# not resolve symlinks unnecessarily, referring to the contents of the unsafe
+# directory via a safe symlink should be ok, and should not inject the data from
+# the symlink target path.
+
+[!symlink] stop 'remainder of test checks symlink behavior'
+[short] stop 'links and runs binaries'
+
+symlink $WORK${/}link -> $DIR
+
+[cgo] go run $WORK${/}link${/}main.go
+[!cgo] go run $WORK${/}link${/}main_nocgo.go
+! stdout panic
+! stderr panic
+stderr '^ok$'
+
+[cgo] go test -v $WORK${/}link${/}main.go $WORK${/}link${/}main_test.go
+[!cgo] go test -v $WORK${/}link${/}main_nocgo.go $WORK${/}link${/}main_test.go
+! stdout panic
+! stderr panic
+stdout '^ok$' # 'go test' combines the test's stdout into stderr
+
+cd $WORK/link
+
+[cgo] ! go run $DIR${/}main.go
+[!cgo] ! go run $DIR${/}main_nocgo.go
+stderr 'package command-line-arguments: invalid package directory .*uh-oh'
+
+go run .
+! stdout panic
+! stderr panic
+stderr '^ok$'
+
+[cgo] go run main.go
+[!cgo] go run main_nocgo.go
+! stdout panic
+! stderr panic
+stderr '^ok$'
+
+go test -v
+! stdout panic
+! stderr panic
+stdout '^ok$' # 'go test' combines the test's stdout into stderr
+
+go test -v .
+! stdout panic
+! stderr panic
+stdout '^ok$' # 'go test' combines the test's stdout into stderr
+
+[cgo] go tool cgo main.go
+[cgo] grep '//line .*'${/}'link'${/}'main\.go:1:1' _obj/main.cgo1.go
+[cgo] ! grep 'uh-oh' _obj/main.cgo1.go
+
+-- $WORK/go.mod --
+module example
+go 1.19
+-- $WORK/main.go --
+package main
+
+import "C"
+
+func main() {
+ /* nothing here */
+ println("ok")
+}
+-- $WORK/main_nocgo.go --
+//go:build !cgo
+
+package main
+
+func main() {
+ /* nothing here */
+ println("ok")
+}
+-- $WORK/main_test.go --
+package main
+
+import "testing"
+
+func TestMain(*testing.M) {
+ main()
+}
diff --git a/src/cmd/go/testdata/script/build_darwin_cc_arch.txt b/src/cmd/go/testdata/script/build_darwin_cc_arch.txt
new file mode 100644
index 0000000..df3fa5b
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_darwin_cc_arch.txt
@@ -0,0 +1,24 @@
+# Test that we pass -arch flag to C compiler on Darwin (issue 43692).
+
+[!GOOS:darwin] skip
+[!cgo] skip
+
+# clear CC, in case user sets it
+env CC=
+
+env CGO_ENABLED=1
+
+env GOARCH=amd64
+go build -n -x c.go
+stderr 'clang.*-arch x86_64'
+
+env GOARCH=arm64
+go build -n -x c.go
+stderr 'clang.*-arch arm64'
+
+-- c.go --
+package main
+
+import "C"
+
+func main() {}
diff --git a/src/cmd/go/testdata/script/build_dash_n_cgo.txt b/src/cmd/go/testdata/script/build_dash_n_cgo.txt
new file mode 100644
index 0000000..3f49ef6
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_dash_n_cgo.txt
@@ -0,0 +1,18 @@
+# Tests golang.org/issue/14944
+
+[!cgo] skip
+
+go build -n foo.go
+! stderr 'os.Stat .* no such file or directory' # there shouldn't be a stat of the archive file
+
+-- foo.go --
+package main
+
+/*
+#include <limits.h>
+*/
+import "C"
+
+func main() {
+ println(C.INT_MAX)
+} \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/build_dash_o_dev_null.txt b/src/cmd/go/testdata/script/build_dash_o_dev_null.txt
new file mode 100644
index 0000000..e415fc2
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_dash_o_dev_null.txt
@@ -0,0 +1,13 @@
+# Issue #25579
+
+[short] skip
+
+go build -o $devnull hello.go
+! exists 'hello'$GOEXE
+
+-- hello.go --
+package main
+
+func main() {
+ println("hello, world")
+}
diff --git a/src/cmd/go/testdata/script/build_dash_x.txt b/src/cmd/go/testdata/script/build_dash_x.txt
new file mode 100644
index 0000000..e5580a2
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_dash_x.txt
@@ -0,0 +1,48 @@
+[short] skip
+[!cgo] skip
+
+[!exec:/usr/bin/env] skip
+[!exec:bash] skip
+
+mkdir $WORK/tmp/cache
+env GOCACHE=$WORK/tmp/cache
+
+# Before building our test main.go, ensure that an up-to-date copy of
+# runtime/cgo is present in the cache. If it isn't, the 'go build' step below
+# will fail with "can't open import". See golang.org/issue/29004.
+#
+# (The fix in golang.org/issue/29004 didn't completely fix the underlying issue:
+# cmd/go/internal/load adds a bunch of implicit dependencies
+# based on various heuristics, and, due to a bug described in
+# https://golang.org/issue/31544#issuecomment-490607180,
+# those implicit dependencies are not added early enough during
+# loading to properly affect the import graph.)
+go build runtime/cgo
+
+go build -x -o main main.go
+cp stderr commands.txt
+cat header.txt commands.txt
+cp stdout test.sh
+
+exec ./main
+cmp stderr hello.txt
+rm ./main
+
+exec /usr/bin/env bash -x test.sh
+exec ./main
+cmp stderr hello.txt
+
+grep '^WORK=(.*)\n' commands.txt
+
+-- main.go --
+package main
+
+import "C"
+
+func main() {
+ print("hello\n")
+}
+-- header.txt --
+set -e
+-- hello.txt --
+hello
diff --git a/src/cmd/go/testdata/script/build_exe.txt b/src/cmd/go/testdata/script/build_exe.txt
new file mode 100644
index 0000000..a994d17
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_exe.txt
@@ -0,0 +1,25 @@
+# go build with -o and -buildmode=exe should report an error on a non-main package.
+
+! go build -buildmode=exe -o out$GOEXE ./not_main
+stderr '-buildmode=exe requires exactly one main package'
+! exists out$GOEXE
+! go build -buildmode=exe -o out$GOEXE ./main_one ./main_two
+stderr '-buildmode=exe requires exactly one main package'
+! exists out$GOEXE
+
+-- go.mod --
+module m
+
+go 1.16
+-- not_main/not_main.go --
+package not_main
+
+func F() {}
+-- main_one/main_one.go --
+package main
+
+func main() {}
+-- main_two/main_two.go --
+package main
+
+func main() {}
diff --git a/src/cmd/go/testdata/script/build_gcflags.txt b/src/cmd/go/testdata/script/build_gcflags.txt
new file mode 100644
index 0000000..9603e0b
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_gcflags.txt
@@ -0,0 +1,22 @@
+env GO111MODULE=off
+
+# Test that the user can override default code generation flags.
+
+[compiler:gccgo] skip # gccgo does not use -gcflags
+[!cgo] skip
+[!GOOS:linux] skip # test only works if c-archive implies -shared
+[short] skip
+
+env GOCACHE=$WORK/gocache # Looking for compile commands, so need a clean cache.
+go build -x -n -buildmode=c-archive -gcflags=all=-shared=false ./override.go
+stderr '^.*/compile (.* )?-shared (.* )?-shared=false'
+
+-- override.go --
+package main
+
+import "C"
+
+//export GoFunc
+func GoFunc() {}
+
+func main() {}
diff --git a/src/cmd/go/testdata/script/build_gcflags_order.txt b/src/cmd/go/testdata/script/build_gcflags_order.txt
new file mode 100644
index 0000000..3725c89
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_gcflags_order.txt
@@ -0,0 +1,22 @@
+# Tests golang.org/issue/47682
+# Flags specified with -gcflags should appear after other flags generated by cmd/go.
+
+cd m
+go build -n -gcflags=-lang=go1.17
+stderr ' -lang=go1.16.* -lang=go1.17'
+! go build -gcflags='-c 0'
+stderr 'compile: -c must be at least 1, got 0'
+
+-- m/go.mod --
+module example.com
+
+go 1.16
+
+-- m/main.go --
+package main
+
+func main() {
+ var s = []int{1, 2, 3}
+ var pa = (*[2]int)(s[1:])
+ println(pa[1])
+}
diff --git a/src/cmd/go/testdata/script/build_gopath_order.txt b/src/cmd/go/testdata/script/build_gopath_order.txt
new file mode 100644
index 0000000..caf2502
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_gopath_order.txt
@@ -0,0 +1,36 @@
+# golang.org/issue/14176#issuecomment-179895769
+# golang.org/issue/14192
+# -I arguments to compiler could end up not in GOPATH order,
+# leading to unexpected import resolution in the compiler.
+
+env GO111MODULE=off
+env GOPATH=$WORK/p1${:}$WORK/p2
+mkdir $WORK/p1/src/foo $WORK/p2/src/baz
+mkdir $WORK/p2/pkg/${GOOS}_${GOARCH} $WORK/p1/src/bar
+cp foo.go $WORK/p1/src/foo/foo.go
+cp baz.go $WORK/p2/src/baz/baz.go
+cp foo.a $WORK/p2/pkg/${GOOS}_${GOARCH}/foo.a
+cp bar.go $WORK/p1/src/bar/bar.go
+
+go install -x bar
+
+# add in baz.a to the mix
+mkdir $WORK/p1/pkg/${GOOS}_${GOARCH}
+cp baz.a $WORK/p1/pkg/${GOOS}_${GOARCH}/baz.a
+env GOPATH=$WORK/p1${:}$WORK/p2
+go install -x bar
+env GOPATH=$WORK/p2${:}$WORK/p1
+go install -x bar
+
+-- foo.go --
+package foo
+-- baz.go --
+package baz
+-- foo.a --
+bad
+-- baz.a --
+bad
+-- bar.go --
+package bar
+import _ "baz"
+import _ "foo"
diff --git a/src/cmd/go/testdata/script/build_ignore_leading_bom.txt b/src/cmd/go/testdata/script/build_ignore_leading_bom.txt
new file mode 100644
index 0000000..37141f3
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_ignore_leading_bom.txt
@@ -0,0 +1,27 @@
+# Per https://golang.org/ref/spec#Source_code_representation:
+# a compiler may ignore a UTF-8-encoded byte order mark (U+FEFF)
+# if it is the first Unicode code point in the source text.
+
+go list -f 'Imports: {{.Imports}} EmbedFiles: {{.EmbedFiles}}' .
+stdout '^Imports: \[embed m/hello\] EmbedFiles: \[.*file\]$'
+
+-- go.mod --
+module m
+
+go 1.16
+-- m.go --
+package main
+
+import (
+ _ "embed"
+
+ "m/hello"
+)
+
+//go:embed file
+var s string
+
+-- hello/hello.go --
+package hello
+
+-- file --
diff --git a/src/cmd/go/testdata/script/build_import_comment.txt b/src/cmd/go/testdata/script/build_import_comment.txt
new file mode 100644
index 0000000..b500340
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_import_comment.txt
@@ -0,0 +1,68 @@
+# Test in GOPATH mode first.
+env GO111MODULE=off
+cd m
+
+# Import comment matches
+go build -n works.go
+
+# Import comment mismatch
+! go build -n wrongplace.go
+stderr 'wrongplace expects import "my/x"'
+
+# Import comment syntax error
+! go build -n bad.go
+stderr 'cannot parse import comment'
+
+# Import comment conflict
+! go build -n conflict.go
+stderr 'found import comments'
+
+
+# Test in module mode.
+# We ignore import comments, so these commands should succeed.
+env GO111MODULE=on
+
+# Import comment matches
+go build -n works.go
+
+# Import comment mismatch
+go build -n wrongplace.go
+
+# Import comment syntax error
+go build -n bad.go
+
+# Import comment conflict
+go build -n conflict.go
+
+-- m/go.mod --
+module m
+
+go 1.16
+-- m/bad.go --
+package p
+
+import "m/bad"
+-- m/conflict.go --
+package p
+
+import "m/conflict"
+-- m/works.go --
+package p
+
+import _ "m/works/x"
+-- m/wrongplace.go --
+package p
+
+import "m/wrongplace"
+-- m/bad/bad.go --
+package bad // import
+-- m/conflict/a.go --
+package conflict // import "a"
+-- m/conflict/b.go --
+package conflict /* import "b" */
+-- m/works/x/x.go --
+package x // import "m/works/x"
+-- m/works/x/x1.go --
+package x // important! not an import comment
+-- m/wrongplace/x.go --
+package x // import "my/x"
diff --git a/src/cmd/go/testdata/script/build_import_cycle.txt b/src/cmd/go/testdata/script/build_import_cycle.txt
new file mode 100644
index 0000000..16e4e87
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_import_cycle.txt
@@ -0,0 +1,13 @@
+# mod_import_cycle covers this error in module mode.
+env GO111MODULE=off
+
+! go build selfimport
+stderr -count=1 'import cycle not allowed'
+
+go list -e -f '{{.Error}}' selfimport # Don't hang forever
+stdout -count=1 'import cycle not allowed'
+
+-- selfimport/selfimport.go --
+package selfimport
+
+import "selfimport"
diff --git a/src/cmd/go/testdata/script/build_internal.txt b/src/cmd/go/testdata/script/build_internal.txt
new file mode 100644
index 0000000..0a37d65
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_internal.txt
@@ -0,0 +1,65 @@
+# Test internal package errors are handled
+cd testinternal3
+go list .
+stdout 'testinternal3'
+
+# Test internal cache
+cd ../testinternal4
+! go build testinternal4/p
+stderr 'internal'
+
+# Test internal packages outside GOROOT are respected
+cd ../testinternal2
+env GO111MODULE=off
+! go build -v .
+stderr 'p\.go:3:8: use of internal package .*internal/w not allowed'
+env GO111MODULE=''
+
+[compiler:gccgo] skip # gccgo does not have GOROOT
+cd ../testinternal
+! go build -v .
+stderr 'p\.go:3:8: use of internal package net/http/internal not allowed'
+
+-- testinternal/go.mod --
+module testinternal
+
+go 1.16
+-- testinternal/p.go --
+package p
+
+import _ "net/http/internal"
+-- testinternal2/go.mod --
+module testinternal2
+
+go 1.16
+-- testinternal2/p.go --
+package p
+
+import _ "./x/y/z/internal/w"
+-- testinternal2/x/y/z/internal/w/w.go --
+package w
+-- testinternal3/go.mod --
+module testinternal3
+
+go 1.16
+-- testinternal3/t.go --
+package t
+
+import _ "internal/does-not-exist"
+-- testinternal4/go.mod --
+module testinternal4
+
+go 1.16
+-- testinternal4/p/p.go --
+package p
+
+import (
+ _ "testinternal4/q/internal/x"
+ _ "testinternal4/q/j"
+)
+-- testinternal4/q/internal/x/x.go --
+package x
+-- testinternal4/q/j/j.go --
+package j
+
+import _ "testinternal4/q/internal/x"
diff --git a/src/cmd/go/testdata/script/build_issue48319.txt b/src/cmd/go/testdata/script/build_issue48319.txt
new file mode 100644
index 0000000..4543303
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_issue48319.txt
@@ -0,0 +1,46 @@
+# Regression test for https://go.dev/issue/48319:
+# cgo builds should not include debug information from a stale GOROOT_FINAL.
+
+[short] skip
+[!cgo] skip
+
+# This test is sensitive to cache invalidation,
+# so use a separate build cache that we can control.
+env GOCACHE=$WORK/gocache
+mkdir $GOCACHE
+
+# Build a binary using a specific value of GOROOT_FINAL.
+env GOROOT_FINAL=$WORK${/}goroot1
+go build -o main.exe
+mv main.exe main1.exe
+
+# Now clean the cache and build using a different GOROOT_FINAL.
+# The resulting binaries should differ in their debug metadata.
+go clean -cache
+env GOROOT_FINAL=$WORK${/}goroot2
+go build -o main.exe
+mv main.exe main2.exe
+! cmp -q main2.exe main1.exe
+
+# Set GOROOT_FINAL back to the first value.
+# If the build is properly reproducible, the two binaries should match.
+env GOROOT_FINAL=$WORK${/}goroot1
+go build -o main.exe
+cmp -q main.exe main1.exe
+
+-- go.mod --
+module main
+
+go 1.18
+-- main.go --
+package main
+
+import "C"
+
+import "runtime"
+
+var _ C.int
+
+func main() {
+ println(runtime.GOROOT())
+}
diff --git a/src/cmd/go/testdata/script/build_issue59571.txt b/src/cmd/go/testdata/script/build_issue59571.txt
new file mode 100644
index 0000000..2cf3259
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_issue59571.txt
@@ -0,0 +1,40 @@
+# Regression test for https://go.dev/issue/59571
+# Build should be reproducible, even with aliased generic types.
+
+go build -a -o 1.a
+go build -a -o 2.a
+cmp -q 1.a 2.a
+
+-- go.mod --
+module m
+
+go 1.20
+-- m.go --
+package m
+
+type (
+ SliceFlag[T any] struct{}
+
+ Alias1 = SliceFlag[[1]int]
+ Alias2 = SliceFlag[[2]int]
+ Alias3 = SliceFlag[[3]int]
+ Alias4 = SliceFlag[[4]int]
+ Alias5 = SliceFlag[[5]int]
+ Alias6 = SliceFlag[[6]int]
+ Alias7 = SliceFlag[[7]int]
+ Alias8 = SliceFlag[[8]int]
+ Alias9 = SliceFlag[[9]int]
+ Alias10 = SliceFlag[[10]int]
+ Alias11 = SliceFlag[[11]int]
+ Alias12 = SliceFlag[[12]int]
+ Alias13 = SliceFlag[[13]int]
+ Alias14 = SliceFlag[[14]int]
+ Alias15 = SliceFlag[[15]int]
+ Alias16 = SliceFlag[[16]int]
+ Alias17 = SliceFlag[[17]int]
+ Alias18 = SliceFlag[[18]int]
+ Alias19 = SliceFlag[[19]int]
+ Alias20 = SliceFlag[[20]int]
+)
+
+func (x *SliceFlag[T]) String() string { return "zzz" }
diff --git a/src/cmd/go/testdata/script/build_issue62156.txt b/src/cmd/go/testdata/script/build_issue62156.txt
new file mode 100644
index 0000000..d241570
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_issue62156.txt
@@ -0,0 +1,27 @@
+# Regression test for https://go.dev/issue/62156:
+# DWARF generation for inlined functions may require more runtime type
+# descriptors to be written.
+
+go build
+
+-- go.mod --
+module m
+
+go 1.20
+-- main.go --
+package main
+
+import "m/sub"
+
+func main() { sub.F() }
+-- sub/sub.go --
+package sub
+
+type iface interface{ m() }
+
+func F() {
+ f := func(rt []iface) []iface {
+ return append([]iface{}, rt...)
+ }
+ f(nil)
+}
diff --git a/src/cmd/go/testdata/script/build_issue6480.txt b/src/cmd/go/testdata/script/build_issue6480.txt
new file mode 100644
index 0000000..991112f
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_issue6480.txt
@@ -0,0 +1,128 @@
+# "go test -c -test.bench=XXX errors" should not hang.
+# "go test -c" should also produce reproducible binaries.
+# "go test -c" should also appear to write a new binary every time,
+# even if it's really just updating the mtime on an existing up-to-date binary.
+
+[compiler:gccgo] skip
+[short] skip
+
+# Install some commands to compare mtimes
+env GOBIN=$WORK/tmp/bin
+go install m/now m/mtime m/before
+
+# Initial builds
+go test -c -test.bench=XXX errors
+go test -c -o errors2.test errors
+cmp errors.test$GOEXE errors2.test # // errors2.test has no exeSuffix because -o above doesn't have it
+
+# Check errors.test mtime is updated
+exec $GOBIN/now
+cp stdout start_time.txt
+go test -x -c -test.bench=XXX errors
+! stderr '[\\/]link|gccgo' # make sure up-to-date test binary is not relinked
+exec $GOBIN/mtime errors.test$GOEXE
+cp stdout errors1_mod_time.txt
+exec $GOBIN/before start_time.txt errors1_mod_time.txt
+rm start_time.txt errors1_mod_time.txt
+
+# Check errors2.test mtime is updated
+exec $GOBIN/now
+cp stdout start_time.txt
+go test -x -c -o errors2.test errors
+! stderr '[\\/]link|gccgo' # make sure up-to-date test binary is not relinked
+exec $GOBIN/mtime errors2.test
+cp stdout errors2_mod_time.txt
+exec $GOBIN/before start_time.txt errors2_mod_time.txt
+
+-- go.mod --
+module m
+
+go 1.16
+-- now/now.go --
+// Writes time.Now() to a file
+package main
+
+import (
+ "encoding/json"
+ "fmt"
+ "os"
+ "time"
+)
+
+func main() {
+ if err := json.NewEncoder(os.Stdout).Encode(time.Now()); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+}
+-- mtime/mtime.go --
+package main
+
+import (
+ "encoding/json"
+ "fmt"
+ "os"
+)
+
+func main() {
+ info, err := os.Stat(os.Args[1])
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ if err := json.NewEncoder(os.Stdout).Encode(info.ModTime()); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+}
+-- before/before.go --
+package main
+
+import (
+ "encoding/json"
+ "fmt"
+ "os"
+ "time"
+)
+
+func truncateLike(t, p time.Time) time.Time {
+ nano := p.UnixNano()
+ d := 1 * time.Nanosecond
+ for nano%int64(d) == 0 && d < 1*time.Second {
+ d *= 10
+ }
+ for nano%int64(d) == 0 && d < 2*time.Second {
+ d *= 2
+ }
+ return t.Truncate(d)
+}
+
+func main() {
+ var t1 time.Time
+ b1, err := os.ReadFile(os.Args[1])
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ if err := json.Unmarshal(b1, &t1); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+
+ var t2 time.Time
+ b2, err := os.ReadFile(os.Args[2])
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ if err := json.Unmarshal(b2, &t2); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+
+ t1 = truncateLike(t1, t2)
+ if !t1.Before(t2) {
+ fmt.Fprintf(os.Stderr, "time in %v (%v) is not before time in %v (%v)", os.Args[1], t1, os.Args[2], t2)
+ os.Exit(1)
+ }
+}
diff --git a/src/cmd/go/testdata/script/build_issue_65528.txt b/src/cmd/go/testdata/script/build_issue_65528.txt
new file mode 100644
index 0000000..ab4d62b
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_issue_65528.txt
@@ -0,0 +1,9 @@
+go build
+
+-- go.mod --
+module test
+
+go 1.0
+
+-- p.go --
+package p
diff --git a/src/cmd/go/testdata/script/build_link_x_import_path_escape.txt b/src/cmd/go/testdata/script/build_link_x_import_path_escape.txt
new file mode 100644
index 0000000..d47c482
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_link_x_import_path_escape.txt
@@ -0,0 +1,22 @@
+[compiler:gccgo] skip 'gccgo does not support -ldflags -X'
+
+go build -o linkx$GOEXE -ldflags -X=my.pkg.Text=linkXworked my.pkg/main
+exec ./linkx$GOEXE
+stderr '^linkXworked$'
+
+-- go.mod --
+module my.pkg
+
+go 1.16
+-- main/main.go --
+package main
+
+import "my.pkg"
+
+func main() {
+ println(pkg.Text)
+}
+-- pkg.go --
+package pkg
+
+var Text = "unset"
diff --git a/src/cmd/go/testdata/script/build_multi_main.txt b/src/cmd/go/testdata/script/build_multi_main.txt
new file mode 100644
index 0000000..8afd8b8
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_multi_main.txt
@@ -0,0 +1,43 @@
+# Verify build -o can output multiple executables to a directory.
+
+mkdir $WORK/bin
+go build -o $WORK/bin ./cmd/c1 ./cmd/c2
+! stderr 'multiple packages'
+
+! go build -o $WORK/bin ./pkg1 ./pkg1
+stderr 'no main packages'
+
+! go build ./cmd/c1
+stderr 'already exists and is a directory'
+
+# Verify build -o output correctly local packages
+mkdir $WORK/local
+go build -o $WORK/local ./exec.go
+exists $WORK/local/exec$GOEXE
+
+-- go.mod --
+module exmod
+
+-- cmd/c1/main.go --
+package main
+
+func main() {}
+
+-- cmd/c2/main.go --
+package main
+
+func main() {}
+
+-- pkg1/pkg1.go --
+package pkg1
+
+-- pkg2/pkg2.go --
+package pkg2
+
+-- exec.go --
+package main
+
+func main() {}
+
+-- c1$GOEXE/keep.txt --
+Create c1 directory.
diff --git a/src/cmd/go/testdata/script/build_n_cgo.txt b/src/cmd/go/testdata/script/build_n_cgo.txt
new file mode 100644
index 0000000..fa01927
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_n_cgo.txt
@@ -0,0 +1,18 @@
+[!cgo] skip
+
+# Test that nothing is prepended to $WORK path prefix.
+# See issue golang.org/issue/37012.
+go build -n
+! stderr '[/\\]\$WORK'
+stderr '[ =]\$WORK'
+
+-- go.mod --
+module m
+
+go 1.16
+-- main.go --
+package main
+
+import "C"
+
+var _ C.int
diff --git a/src/cmd/go/testdata/script/build_negative_p.txt b/src/cmd/go/testdata/script/build_negative_p.txt
new file mode 100644
index 0000000..9123907
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_negative_p.txt
@@ -0,0 +1,5 @@
+! go build -p=-1 example.go
+stderr 'go: -p must be a positive integer: -1'
+
+-- example.go --
+package example \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/build_no_go.txt b/src/cmd/go/testdata/script/build_no_go.txt
new file mode 100644
index 0000000..b61d752
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_no_go.txt
@@ -0,0 +1,41 @@
+! go build ./empty/test
+stderr 'no non-test Go files in '
+
+! go build ./empty/xtest
+stderr 'no non-test Go files in '
+
+! go build ./empty/testxtest
+stderr 'no non-test Go files in '
+
+! go build ./exclude
+stderr 'build constraints exclude all Go files in '
+
+! go build ./exclude/ignore
+stderr 'no Go files in '
+
+! go build ./exclude/empty
+stderr 'no Go files in '
+
+-- go.mod --
+module m
+
+go 1.16
+-- empty/test/test_test.go --
+package p
+-- empty/testxtest/test_test.go --
+package p
+-- empty/testxtest/xtest_test.go --
+package p_test
+-- empty/xtest/xtest_test.go --
+package p_test
+-- exclude/empty/x.txt --
+-- exclude/ignore/_x.go --
+package x
+-- exclude/x.go --
+// +build linux,!linux
+
+package x
+-- exclude/x_linux.go --
+// +build windows
+
+package x
diff --git a/src/cmd/go/testdata/script/build_nocache.txt b/src/cmd/go/testdata/script/build_nocache.txt
new file mode 100644
index 0000000..b21e755
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_nocache.txt
@@ -0,0 +1,40 @@
+env GO111MODULE=off
+
+# As of Go 1.12, the module cache is required.
+
+# If none of the variables we use to locate GOCACHE are set, the cache is off
+# and we cannot build.
+env GOCACHE=
+env XDG_CACHE_HOME=
+env HOME=
+[GOOS:plan9] env home=
+[GOOS:windows] env LocalAppData=
+! go build -o triv triv.go
+stderr 'build cache is required, but could not be located: GOCACHE is not defined and .*'
+
+# If GOCACHE is set but is not an absolute path, and we cannot build.
+env GOCACHE=test
+! go build -o triv triv.go
+stderr 'build cache is required, but could not be located: GOCACHE is not an absolute path'
+
+# An explicit GOCACHE=off also disables builds.
+env GOCACHE=off
+! go build -o triv triv.go
+stderr 'build cache is disabled by GOCACHE=off'
+
+# If GOCACHE is set to an unwritable directory, we should diagnose it as such.
+[GOOS:windows] stop # Does not support unwritable directories.
+[root] skip # Can write to unwritable directories.
+
+mkdir $WORK/unwritable/home
+chmod 0555 $WORK/unwritable/home
+[!GOOS:plan9] env HOME=$WORK/unwritable/home
+[GOOS:plan9] env home=$WORK/unwritable/home
+
+env GOCACHE=$WORK/unwritable/home
+! go build -o triv triv.go
+stderr 'failed to initialize build cache.* permission denied'
+
+-- triv.go --
+package main
+func main() {}
diff --git a/src/cmd/go/testdata/script/build_output.txt b/src/cmd/go/testdata/script/build_output.txt
new file mode 100644
index 0000000..457960f
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_output.txt
@@ -0,0 +1,117 @@
+[compiler:gccgo] skip 'gccgo has no standard packages'
+[short] skip
+
+[!GOOS:windows] env NONEXE='.exe'
+[GOOS:windows] env NONEXE=''
+
+env GOBIN=$WORK/tmp/bin
+go install m/isarchive &
+
+go build x.go
+exists -exec x$GOEXE
+rm x$GOEXE
+! exists x$NONEXE
+
+go build -o myprog x.go
+! exists x
+! exists x.exe
+exists -exec myprog
+! exists myprogr.exe
+
+! exists bin
+go build -o bin/x x.go
+exists -exec bin/x
+rm bin
+
+! exists bin
+go build -o bin/ x.go
+exists -exec bin/x$GOEXE
+rm bin
+
+[GOOS:windows] ! exists bin
+[GOOS:windows] go build -o bin\x x.go
+[GOOS:windows] exists -exec bin\x
+[GOOS:windows] rm bin
+
+[GOOS:windows] ! exists bin
+[GOOS:windows] go build -o bin\ x.go
+[GOOS:windows] exists -exec bin\x.exe
+[GOOS:windows] rm bin
+
+! exists bin
+mkdir bin
+go build -o bin x.go
+exists -exec bin/x$GOEXE
+rm bin
+
+go build p.go
+! exists p
+! exists p.a
+! exists p.o
+! exists p.exe
+
+wait # for isarchive
+
+go build -o p.a p.go
+exists p.a
+exec $GOBIN/isarchive p.a
+
+go build cmd/gofmt
+exists -exec gofmt$GOEXE
+rm gofmt$GOEXE
+! exists gofmt$NONEXE
+
+go build -o mygofmt cmd/gofmt
+exists -exec mygofmt
+! exists mygofmt.exe
+! exists gofmt
+! exists gofmt.exe
+
+go build sync/atomic
+! exists atomic
+! exists atomic.exe
+
+go build -o myatomic.a sync/atomic
+exists myatomic.a
+exec $GOBIN/isarchive myatomic.a
+! exists atomic
+! exists atomic.a
+! exists atomic.exe
+
+! go build -o whatever cmd/gofmt sync/atomic
+stderr 'multiple packages'
+
+-- go.mod --
+module m
+
+go 1.16
+-- x.go --
+package main
+
+func main() {}
+-- p.go --
+package p
+-- isarchive/isarchive.go --
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "os"
+)
+
+func main() {
+ f, err := os.Open(os.Args[1])
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ buf := make([]byte, 100)
+ io.ReadFull(f, buf)
+ f.Close()
+ if !bytes.HasPrefix(buf, []byte("!<arch>\n")) {
+ fmt.Fprintf(os.Stderr, "file %s exists but is not an archive\n", os.Args[1])
+ os.Exit(1)
+ }
+}
diff --git a/src/cmd/go/testdata/script/build_overlay.txt b/src/cmd/go/testdata/script/build_overlay.txt
new file mode 100644
index 0000000..b64bc02
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_overlay.txt
@@ -0,0 +1,313 @@
+[short] skip
+
+# Test building in overlays.
+# TODO(#39958): add a test case where the destination file in the replace map
+# isn't a go file. Either completely exclude that case in fs.IsDirWithGoFiles
+# if the compiler doesn't allow it, or test that it works all the way.
+# TODO(#39958): add a test that both gc and gccgo assembly files can include .h
+# files.
+
+# The main package (m) is contained in an overlay. It imports m/dir2 which has one
+# file in an overlay and one file outside the overlay, which in turn imports m/dir,
+# which only has source files in the overlay.
+
+cd m
+
+! go build .
+go build -overlay overlay.json -o main$GOEXE .
+exec ./main$goexe
+stdout '^hello$'
+
+go build -overlay overlay.json -o print_abspath$GOEXE ./printpath
+exec ./print_abspath$GOEXE
+stdout $WORK[/\\]gopath[/\\]src[/\\]m[/\\]printpath[/\\]main.go
+
+go build -overlay overlay.json -o print_trimpath$GOEXE -trimpath ./printpath
+exec ./print_trimpath$GOEXE
+stdout ^m[/\\]printpath[/\\]main.go
+
+go build -overlay overlay.json -o print_trimpath_two_files$GOEXE printpath/main.go printpath/other.go
+exec ./print_trimpath_two_files$GOEXE
+stdout $WORK[/\\]gopath[/\\]src[/\\]m[/\\]printpath[/\\]main.go
+stdout $WORK[/\\]gopath[/\\]src[/\\]m[/\\]printpath[/\\]other.go
+
+[cgo] go build -overlay overlay.json -o main_cgo_replace$GOEXE ./cgo_hello_replace
+[cgo] exec ./main_cgo_replace$GOEXE
+[cgo] stdout '^hello cgo\r?\n'
+
+[cgo] go build -overlay overlay.json -o main_cgo_quote$GOEXE ./cgo_hello_quote
+[cgo] exec ./main_cgo_quote$GOEXE
+[cgo] stdout '^hello cgo\r?\n'
+
+[cgo] go build -overlay overlay.json -o main_cgo_angle$GOEXE ./cgo_hello_angle
+[cgo] exec ./main_cgo_angle$GOEXE
+[cgo] stdout '^hello cgo\r?\n'
+
+go build -overlay overlay.json -o main_call_asm$GOEXE ./call_asm
+exec ./main_call_asm$GOEXE
+! stdout .
+
+[cgo] go list -compiled -overlay overlay.json -f '{{range .CompiledGoFiles}}{{. | printf "%s\n"}}{{end}}' ./cgo_hello_replace
+[cgo] cp stdout compiled_cgo_sources.txt
+[cgo] go run ../print_line_comments.go compiled_cgo_sources.txt
+[cgo] stdout $GOPATH[/\\]src[/\\]m[/\\]cgo_hello_replace[/\\]cgo_hello_replace.go
+[cgo] ! stdout $GOPATH[/\\]src[/\\]m[/\\]overlay[/\\]hello.c
+
+# Change the contents of a file in the overlay and ensure that makes the target stale
+env OLD_GOCACHE=$GOCACHE
+env GOCACHE=$WORK/cache # use a fresh cache so that multiple runs of the test don't interfere
+go build -x -overlay overlay.json ./test_cache
+stderr '(compile|gccgo)( |\.exe).*test_cache.go'
+go build -x -overlay overlay.json ./test_cache
+! stderr '(compile|gccgo)( |\.exe).*test_cache.go' # cached
+cp overlay/test_cache_different.go overlay/test_cache.go
+go build -x -overlay overlay.json ./test_cache
+stderr '(compile|gccgo)( |\.exe).*test_cache.go' # not cached
+env CACHE=$OLD_GOCACHE
+
+# Run same tests but with gccgo.
+env GO111MODULE=off
+[!exec:gccgo] stop
+[cross] stop # gccgo can't necessarily cross-compile
+
+! go build -compiler=gccgo .
+go build -compiler=gccgo -overlay overlay.json -o main_gccgo$GOEXE .
+exec ./main_gccgo$goexe
+stdout '^hello$'
+
+go build -compiler=gccgo -overlay overlay.json -o print_abspath_gccgo$GOEXE ./printpath
+exec ./print_abspath_gccgo$GOEXE
+stdout $WORK[/\\]gopath[/\\]src[/\\]m[/\\]printpath[/\\]main.go
+
+go build -compiler=gccgo -overlay overlay.json -o print_trimpath_gccgo$GOEXE -trimpath ./printpath
+exec ./print_trimpath_gccgo$GOEXE
+stdout ^\.[/\\]printpath[/\\]main.go
+
+
+go build -compiler=gccgo -overlay overlay.json -o main_cgo_replace_gccgo$GOEXE ./cgo_hello_replace
+exec ./main_cgo_replace_gccgo$GOEXE
+stdout '^hello cgo\r?\n'
+
+go build -compiler=gccgo -overlay overlay.json -o main_cgo_quote_gccgo$GOEXE ./cgo_hello_quote
+exec ./main_cgo_quote_gccgo$GOEXE
+stdout '^hello cgo\r?\n'
+
+go build -compiler=gccgo -overlay overlay.json -o main_cgo_angle_gccgo$GOEXE ./cgo_hello_angle
+exec ./main_cgo_angle_gccgo$GOEXE
+stdout '^hello cgo\r?\n'
+
+go build -compiler=gccgo -overlay overlay.json -o main_call_asm_gccgo$GOEXE ./call_asm
+exec ./main_call_asm_gccgo$GOEXE
+! stdout .
+
+
+-- m/go.mod --
+// TODO(matloob): how do overlays work with go.mod (especially if mod=readonly)
+module m
+
+go 1.16
+
+-- m/dir2/h.go --
+package dir2
+
+func PrintMessage() {
+ printMessage()
+}
+-- m/dir/foo.txt --
+The build action code currently expects the package directory
+to exist, so it can run the compiler in that directory.
+TODO(matloob): Remove this requirement.
+-- m/printpath/about.txt --
+the actual code is in the overlay
+-- m/overlay.json --
+{
+ "Replace": {
+ "f.go": "overlay/f.go",
+ "dir/g.go": "overlay/dir_g.go",
+ "dir2/i.go": "overlay/dir2_i.go",
+ "printpath/main.go": "overlay/printpath.go",
+ "printpath/other.go": "overlay2/printpath2.go",
+ "call_asm/asm_gc.s": "overlay/asm_gc.s",
+ "call_asm/asm_gccgo.s": "overlay/asm_gccgo.s",
+ "test_cache/main.go": "overlay/test_cache.go",
+ "cgo_hello_replace/cgo_header.h": "overlay/cgo_head.h",
+ "cgo_hello_replace/hello.c": "overlay/hello.c",
+ "cgo_hello_quote/cgo_hello.go": "overlay/cgo_hello_quote.go",
+ "cgo_hello_quote/cgo_header.h": "overlay/cgo_head.h",
+ "cgo_hello_angle/cgo_hello.go": "overlay/cgo_hello_angle.go",
+ "cgo_hello_angle/cgo_header.h": "overlay/cgo_head.h"
+ }
+}
+-- m/cgo_hello_replace/cgo_hello_replace.go --
+package main
+
+// #include "cgo_header.h"
+import "C"
+
+func main() {
+ C.say_hello()
+}
+-- m/cgo_hello_replace/cgo_header.h --
+ // Test that this header is replaced with one that has the proper declaration.
+void say_goodbye();
+
+-- m/cgo_hello_replace/hello.c --
+#include <stdio.h>
+
+void say_goodbye() { puts("goodbye cgo\n"); fflush(stdout); }
+
+-- m/overlay/f.go --
+package main
+
+import "m/dir2"
+
+func main() {
+ dir2.PrintMessage()
+}
+-- m/call_asm/main.go --
+package main
+
+func foo() // There will be a "missing function body" error if the assembly file isn't found.
+
+func main() {
+ foo()
+}
+-- m/overlay/dir_g.go --
+package dir
+
+import "fmt"
+
+func PrintMessage() {
+ fmt.Println("hello")
+}
+-- m/overlay/printpath.go --
+package main
+
+import (
+ "fmt"
+ "path/filepath"
+ "runtime"
+)
+
+func main() {
+ _, file, _, _ := runtime.Caller(0)
+
+ // Since https://golang.org/cl/214286, the runtime's debug paths are
+ // slash-separated regardless of platform, so normalize them to system file
+ // paths.
+ fmt.Println(filepath.FromSlash(file))
+}
+-- m/overlay2/printpath2.go --
+package main
+
+import (
+ "fmt"
+ "path/filepath"
+ "runtime"
+)
+
+func init() {
+ _, file, _, _ := runtime.Caller(0)
+ fmt.Println(filepath.FromSlash(file))
+}
+-- m/overlay/dir2_i.go --
+package dir2
+
+import "m/dir"
+
+func printMessage() {
+ dir.PrintMessage()
+}
+-- m/overlay/cgo_hello_quote.go --
+package main
+
+// #include "cgo_header.h"
+import "C"
+
+func main() {
+ C.say_hello()
+}
+-- m/overlay/cgo_hello_angle.go --
+package main
+
+// #include <cgo_header.h>
+import "C"
+
+func main() {
+ C.say_hello()
+}
+-- m/overlay/cgo_head.h --
+void say_hello();
+-- m/overlay/hello.c --
+#include <stdio.h>
+
+void say_hello() { puts("hello cgo\n"); fflush(stdout); }
+-- m/overlay/asm_gc.s --
+// +build gc
+
+TEXT ·foo(SB),0,$0
+ RET
+
+-- m/overlay/asm_gccgo.s --
+// +build gccgo
+
+.globl main.foo
+.text
+main.foo:
+ ret
+
+-- m/overlay/test_cache.go --
+package foo
+
+import "fmt"
+
+func bar() {
+ fmt.Println("something")
+}
+-- m/overlay/test_cache_different.go --
+package foo
+
+import "fmt"
+
+func bar() {
+ fmt.Println("different")
+}
+-- m/cgo_hello_quote/hello.c --
+#include <stdio.h>
+
+void say_hello() { puts("hello cgo\n"); fflush(stdout); }
+-- m/cgo_hello_angle/hello.c --
+#include <stdio.h>
+
+void say_hello() { puts("hello cgo\n"); fflush(stdout); }
+
+-- print_line_comments.go --
+package main
+
+import (
+ "fmt"
+ "io/ioutil"
+ "log"
+ "os"
+ "strings"
+)
+
+func main() {
+ compiledGoFilesArg := os.Args[1]
+ b, err := ioutil.ReadFile(compiledGoFilesArg)
+ if err != nil {
+ log.Fatal(err)
+ }
+ compiledGoFiles := strings.Split(strings.TrimSpace(string(b)), "\n")
+ for _, f := range compiledGoFiles {
+ b, err := ioutil.ReadFile(f)
+ if err != nil {
+ log.Fatal(err)
+ }
+ for _, line := range strings.Split(string(b), "\n") {
+ if strings.HasPrefix(line, "#line") || strings.HasPrefix(line, "//line") {
+ fmt.Println(line)
+ }
+ }
+ }
+}
diff --git a/src/cmd/go/testdata/script/build_patterns_outside_gopath.txt b/src/cmd/go/testdata/script/build_patterns_outside_gopath.txt
new file mode 100644
index 0000000..6a600cf
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_patterns_outside_gopath.txt
@@ -0,0 +1,36 @@
+# Tests issue #18778
+[short] skip
+
+cd pkgs
+
+env GO111MODULE=off
+go build ./...
+! stdout .
+go test ./...
+stdout '^ok'
+go list ./...
+stdout 'pkgs$'
+stdout 'pkgs/a'
+
+-- pkgs/go.mod --
+module pkgs
+
+go 1.16
+-- pkgs/a.go --
+package x
+-- pkgs/a_test.go --
+package x_test
+
+import "testing"
+
+func TestX(t *testing.T) {
+}
+-- pkgs/a/a.go --
+package a
+-- pkgs/a/a_test.go --
+package a_test
+
+import "testing"
+
+func TestA(t *testing.T) {
+}
diff --git a/src/cmd/go/testdata/script/build_pgo.txt b/src/cmd/go/testdata/script/build_pgo.txt
new file mode 100644
index 0000000..3b0804b
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_pgo.txt
@@ -0,0 +1,74 @@
+# Test go build -pgo flag.
+# Specifically, the build cache handles profile content correctly.
+
+[short] skip 'compiles and links executables'
+
+# build without PGO
+go build triv.go
+
+# build with PGO, should trigger rebuild
+# starting with an empty profile (the compiler accepts it)
+go build -x -pgo=prof -o triv.exe triv.go
+stderr 'compile.*-pgoprofile=.*prof.*triv.go'
+
+# check that PGO appears in build info
+# N.B. we can't start the stdout check with -pgo because the script assumes that
+# if the first arg starts with - it is a grep flag.
+go version -m triv.exe
+stdout 'build\s+-pgo=.*'${/}'prof'
+
+# store the build ID
+go list -export -json=BuildID -pgo=prof triv.go
+stdout '"BuildID":' # check that output actually contains a build ID
+cp stdout list.out
+
+# build again with the same profile, should be cached
+go build -x -pgo=prof -o triv.exe triv.go
+! stderr 'compile.*triv.go'
+
+# check that the build ID is the same
+go list -export -json=BuildID -pgo=prof triv.go
+cmp stdout list.out
+
+# overwrite the prof
+go run overwrite.go
+
+# build again, profile content changed, should trigger rebuild
+go build -n -pgo=prof triv.go
+stderr 'compile.*-pgoprofile=.*prof.*p.go'
+
+# check that the build ID is different
+go list -export -json=BuildID -pgo=prof triv.go
+! cmp stdout list.out
+
+# build with trimpath, buildinfo path should be trimmed
+go build -x -pgo=prof -trimpath -o triv.exe triv.go
+
+# check that path is trimmed
+go version -m triv.exe
+stdout 'build\s+-pgo=prof'
+
+-- prof --
+-- triv.go --
+package main
+func main() {}
+-- overwrite.go --
+package main
+
+import (
+ "os"
+ "runtime/pprof"
+)
+
+func main() {
+ f, err := os.Create("prof")
+ if err != nil {
+ panic(err)
+ }
+ err = pprof.StartCPUProfile(f)
+ if err != nil {
+ panic(err)
+ }
+ pprof.StopCPUProfile()
+ f.Close()
+}
diff --git a/src/cmd/go/testdata/script/build_pgo_auto.txt b/src/cmd/go/testdata/script/build_pgo_auto.txt
new file mode 100644
index 0000000..509be0d
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_pgo_auto.txt
@@ -0,0 +1,97 @@
+# Test go build -pgo=auto flag.
+
+[short] skip 'compiles and links executables'
+
+# use default.pgo for a single main package
+go build -n -pgo=auto -o a1.exe ./a/a1
+stderr 'compile.*-pgoprofile=.*default\.pgo.*a1.go'
+
+# check that pgo applied to dependencies
+stderr 'compile.*-p test/dep.*-pgoprofile=.*default\.pgo'
+
+# check that pgo appears in build info
+# N.B. we can't start the stdout check with -pgo because the script assumes that
+# if the first arg starts with - it is a grep flag.
+stderr 'build\\t-pgo=.*default\.pgo'
+
+# check also that -pgo appears with the other flags, before non-flag settings
+! stderr 'build\\t[A-Za-z].*build\\t-pgo'
+
+# use default.pgo for ... with a single main package
+go build -n -pgo=auto ./a/...
+stderr 'compile.*-pgoprofile=.*default\.pgo.*a1.go'
+
+# check that pgo appears in build info
+stderr 'build\\t-pgo=.*default\.pgo'
+
+# build succeeds without PGO when default.pgo file is absent
+go build -n -pgo=auto -o nopgo.exe ./nopgo
+stderr 'compile.*nopgo.go'
+! stderr 'compile.*-pgoprofile'
+
+# check that pgo doesn't appear in build info
+! stderr 'build\\t-pgo='
+
+# other build-related commands
+go install -a -n -pgo=auto ./a/a1
+stderr 'compile.*-pgoprofile=.*default\.pgo.*a1.go'
+
+go run -a -n -pgo=auto ./a/a1
+stderr 'compile.*-pgoprofile=.*default\.pgo.*a1.go'
+
+go test -a -n -pgo=auto ./a/a1
+stderr 'compile.*-pgoprofile=.*default\.pgo.*a1.go.*a1_test.go'
+stderr 'compile.*-pgoprofile=.*default\.pgo.*external_test.go'
+
+# go list commands should succeed as usual
+go list -pgo=auto ./a/a1
+
+go list -test -pgo=auto ./a/a1
+
+go list -deps -pgo=auto ./a/a1
+
+# -pgo=auto is the default. Commands without explicit -pgo=auto
+# should work as -pgo=auto.
+go build -a -n -o a1.exe ./a/a1
+stderr 'compile.*-pgoprofile=.*default\.pgo.*a1.go'
+stderr 'compile.*-p test/dep.*-pgoprofile=.*default\.pgo'
+
+# check that pgo appears in build info
+stderr 'build\\t-pgo=.*default\.pgo'
+
+go build -a -n -o nopgo.exe ./nopgo
+stderr 'compile.*nopgo.go'
+! stderr 'compile.*-pgoprofile'
+
+# check that pgo doesn't appear in build info
+! stderr 'build\\t-pgo='
+
+# -pgo=off should turn off PGO.
+go build -a -n -pgo=off -o a1.exe ./a/a1
+stderr 'compile.*a1.go'
+! stderr 'compile.*-pgoprofile'
+
+# check that pgo doesn't appear in build info
+! stderr 'build\\t-pgo='
+
+-- go.mod --
+module test
+go 1.20
+-- a/a1/a1.go --
+package main
+import _ "test/dep"
+func main() {}
+-- a/a1/a1_test.go --
+package main
+import "testing"
+func TestA(*testing.T) {}
+-- a/a1/external_test.go --
+package main_test
+import "testing"
+func TestExternal(*testing.T) {}
+-- a/a1/default.pgo --
+-- nopgo/nopgo.go --
+package main
+func main() {}
+-- dep/dep.go --
+package dep
diff --git a/src/cmd/go/testdata/script/build_pgo_auto_multi.txt b/src/cmd/go/testdata/script/build_pgo_auto_multi.txt
new file mode 100644
index 0000000..991b72c
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_pgo_auto_multi.txt
@@ -0,0 +1,109 @@
+# Test go build -pgo=auto flag with multiple main packages.
+
+go install -a -n -pgo=auto ./a ./b ./nopgo
+
+# a/default.pgo applies to package a and (transitive)
+# dependencies.
+stderr 'compile.*-pgoprofile=.*a(/|\\\\)default\.pgo.*a(/|\\\\)a\.go'
+stderr 'compile.*-pgoprofile=.*a(/|\\\\)default\.pgo.*dep(/|\\\\)dep\.go'
+stderr 'compile.*-pgoprofile=.*a(/|\\\\)default\.pgo.*dep2(/|\\\\)dep2\.go'
+stderr -count=1 'compile.*-pgoprofile=.*a(/|\\\\)default\.pgo.*dep3(/|\\\\)dep3\.go'
+
+# b/default.pgo applies to package b and (transitive)
+# dependencies.
+stderr 'compile.*-pgoprofile=.*b(/|\\\\)default\.pgo.*b(/|\\\\)b\.go'
+stderr 'compile.*-pgoprofile=.*b(/|\\\\)default\.pgo.*dep(/|\\\\)dep\.go'
+stderr 'compile.*-pgoprofile=.*b(/|\\\\)default\.pgo.*dep2(/|\\\\)dep2\.go'
+stderr -count=1 'compile.*-pgoprofile=.*b(/|\\\\)default\.pgo.*dep3(/|\\\\)dep3\.go'
+
+# nopgo should be built without PGO.
+! stderr 'compile.*-pgoprofile=.*nopgo(/|\\\\)nopgo\.go'
+
+# Dependencies should also be built without PGO.
+# Here we want to match a compile action without -pgoprofile,
+# by matching 3 occurrences of "compile dep.go", among which
+# 2 of them have -pgoprofile (therefore one without).
+stderr -count=3 'compile.*dep(/|\\\\)dep.go'
+stderr -count=2 'compile.*-pgoprofile=.*dep(/|\\\\)dep\.go'
+
+stderr -count=3 'compile.*dep2(/|\\\\)dep2.go'
+stderr -count=2 'compile.*-pgoprofile=.*dep2(/|\\\\)dep2\.go'
+
+stderr -count=3 'compile.*dep3(/|\\\\)dep3.go'
+stderr -count=2 'compile.*-pgoprofile=.*dep3(/|\\\\)dep3\.go'
+
+# check that pgo appears or not in build info as expected
+stderr 'path\\ttest/a\\n.*build\\t-pgo=.*a(/|\\\\)default\.pgo'
+stderr 'path\\ttest/b\\n.*build\\t-pgo=.*b(/|\\\\)default\.pgo'
+! stderr 'path\\ttest/nopgo\\n.*build\\t-pgo='
+
+# go test works the same way
+go test -a -n -pgo=auto ./a ./b ./nopgo
+stderr 'compile.*-pgoprofile=.*a(/|\\\\)default\.pgo.*a(/|\\\\)a_test\.go'
+stderr 'compile.*-pgoprofile=.*a(/|\\\\)default\.pgo.*dep(/|\\\\)dep\.go'
+stderr 'compile.*-pgoprofile=.*b(/|\\\\)default\.pgo.*b(/|\\\\)b_test\.go'
+stderr 'compile.*-pgoprofile=.*b(/|\\\\)default\.pgo.*dep(/|\\\\)dep\.go'
+! stderr 'compile.*-pgoprofile=.*nopgo(/|\\\\)nopgo_test\.go'
+
+# test-only dependencies also have profiles attached
+stderr 'compile.*-pgoprofile=.*a(/|\\\\)default\.pgo.*testdep(/|\\\\)testdep\.go'
+stderr 'compile.*-pgoprofile=.*b(/|\\\\)default\.pgo.*testdep(/|\\\\)testdep\.go'
+stderr 'compile.*-pgoprofile=.*a(/|\\\\)default\.pgo.*testdep2(/|\\\\)testdep2\.go'
+stderr 'compile.*-pgoprofile=.*b(/|\\\\)default\.pgo.*testdep2(/|\\\\)testdep2\.go'
+
+# go list -deps prints packages built multiple times.
+go list -pgo=auto -deps ./a ./b ./nopgo
+stdout 'test/dep \[test/a\]'
+stdout 'test/dep \[test/b\]'
+stdout 'test/dep$'
+
+# Here we have 3 main packages, a, b, and nopgo, where a and b each has
+# its own default.pgo profile, and nopgo has none.
+# All 3 main packages import dep and dep2, both of which then import dep3
+# (a diamond-shape import graph).
+-- go.mod --
+module test
+go 1.20
+-- a/a.go --
+package main
+import _ "test/dep"
+import _ "test/dep2"
+func main() {}
+-- a/a_test.go --
+package main
+import "testing"
+import _ "test/testdep"
+func TestA(*testing.T) {}
+-- a/default.pgo --
+-- b/b.go --
+package main
+import _ "test/dep"
+import _ "test/dep2"
+func main() {}
+-- b/b_test.go --
+package main
+import "testing"
+import _ "test/testdep"
+func TestB(*testing.T) {}
+-- b/default.pgo --
+-- nopgo/nopgo.go --
+package main
+import _ "test/dep"
+import _ "test/dep2"
+func main() {}
+-- nopgo/nopgo_test.go --
+package main
+import "testing"
+func TestNopgo(*testing.T) {}
+-- dep/dep.go --
+package dep
+import _ "test/dep3"
+-- dep2/dep2.go --
+package dep2
+-- dep3/dep3.go --
+package dep3
+-- testdep/testdep.go --
+package testdep
+import _ "test/testdep2"
+-- testdep2/testdep2.go --
+package testdep2
diff --git a/src/cmd/go/testdata/script/build_pie_race.txt b/src/cmd/go/testdata/script/build_pie_race.txt
new file mode 100644
index 0000000..39bea05
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_pie_race.txt
@@ -0,0 +1,30 @@
+# go build -buildmode=pie -race main.go on Darwin should work without errors
+
+[!race] skip 'test requires race detector support'
+
+[!GOOS:darwin] ! go build -buildmode=pie -race
+[!GOOS:darwin] stderr '^-buildmode=pie not supported when -race is enabled on '$GOOS'/'$GOARCH'$'
+[!GOOS:darwin] stop 'not testing -buildmode=pie -race on platform that does not support it'
+
+go build -buildmode=pie -race bytes
+! stderr .
+
+[short] stop 'not linking a binary in -short mode'
+
+go build -buildmode=pie -race main.go
+! stderr .
+exec ./main
+stdout 'Hello, 世界'
+
+-- go.mod --
+module m
+
+go 1.21
+-- main.go --
+package main
+
+import "fmt"
+
+func main() {
+ fmt.Println("Hello, 世界")
+}
diff --git a/src/cmd/go/testdata/script/build_plugin_non_main.txt b/src/cmd/go/testdata/script/build_plugin_non_main.txt
new file mode 100644
index 0000000..e0bbbef
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_plugin_non_main.txt
@@ -0,0 +1,13 @@
+# Plugins are not supported on all platforms.
+[!buildmode:plugin] skip
+
+go build -n testdep
+! go build -buildmode=plugin testdep
+stderr '-buildmode=plugin requires exactly one main package'
+
+-- go.mod --
+module testdep
+
+go 1.16
+-- testdep.go --
+package p
diff --git a/src/cmd/go/testdata/script/build_plugin_reproducible.txt b/src/cmd/go/testdata/script/build_plugin_reproducible.txt
new file mode 100644
index 0000000..5369954
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_plugin_reproducible.txt
@@ -0,0 +1,11 @@
+[!buildmode:plugin] skip
+[short] skip
+
+go build -trimpath -buildvcs=false -buildmode=plugin -o a.so main.go
+go build -trimpath -buildvcs=false -buildmode=plugin -o b.so main.go
+cmp -q a.so b.so
+
+-- main.go --
+package main
+
+func main() {} \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/build_relative_pkgdir.txt b/src/cmd/go/testdata/script/build_relative_pkgdir.txt
new file mode 100644
index 0000000..57f18ee
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_relative_pkgdir.txt
@@ -0,0 +1,9 @@
+env GO111MODULE=off
+
+# Regression test for golang.org/issue/21309: accept relative -pkgdir argument.
+
+[short] skip
+
+mkdir $WORK/gocache
+env GOCACHE=$WORK/gocache
+go build -pkgdir=. runtime
diff --git a/src/cmd/go/testdata/script/build_relative_tmpdir.txt b/src/cmd/go/testdata/script/build_relative_tmpdir.txt
new file mode 100644
index 0000000..ea7412e
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_relative_tmpdir.txt
@@ -0,0 +1,18 @@
+env GO111MODULE=off
+
+# If GOTMPDIR is relative, 'go build' should derive an absolute $WORK directory.
+cd $WORK
+mkdir tmp
+env GOTMPDIR=tmp
+go build -work a
+stderr 'WORK='$WORK
+
+# Similarly if TMP/TMPDIR is relative.
+env GOTMPDIR=
+env TMP=tmp # Windows
+env TMPDIR=tmp # Unix
+go build -work a
+stderr 'WORK='$WORK
+
+-- a/a.go --
+package a
diff --git a/src/cmd/go/testdata/script/build_runtime_gcflags.txt b/src/cmd/go/testdata/script/build_runtime_gcflags.txt
new file mode 100644
index 0000000..c87e480
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_runtime_gcflags.txt
@@ -0,0 +1,11 @@
+env GO111MODULE=off
+[short] skip # rebuilds all of std
+
+# Set up fresh GOCACHE.
+env GOCACHE=$WORK/gocache
+mkdir $GOCACHE
+
+# Verify the standard library (specifically runtime/internal/atomic) can be
+# built with -gcflags when -n is given. See golang.org/issue/29346.
+go build -n -gcflags=all='-l' std
+stderr 'compile.* runtime/internal/atomic .* -l'
diff --git a/src/cmd/go/testdata/script/build_shorten_pkg.txt b/src/cmd/go/testdata/script/build_shorten_pkg.txt
new file mode 100644
index 0000000..38672b6
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_shorten_pkg.txt
@@ -0,0 +1,81 @@
+[short] skip
+
+# This test may go away when the loopvar experiment goes away.
+# Accurate reporting of notable loops in the presence of inlining
+# can create warnings in sibling directories, and it's nice if those
+# can be trimmed like subdirectory paths are.
+
+env GOEXPERIMENT=loopvar
+go build -gcflags=inlines/a=-d=loopvar=2 .
+stderr ^\.[\\/]b[\\/]b\.go:12:6:.*loop.inlined.into.a[\\/]a\.go
+stderr ^\.[\\/]b[\\/]b\.go:12:9:.*loop.inlined.into.a[\\/]a\.go
+
+-- go.mod --
+module inlines
+
+go 1.21
+-- a/a.go --
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+import "inlines/b"
+
+func F() []*int {
+ var s []*int
+ for i := 0; i < 10; i++ {
+ s = append(s, &i)
+ }
+ return s
+}
+
+func Fb() []*int {
+ bf, _ := b.F()
+ return bf
+}
+-- b/b.go --
+package b
+
+var slice = []int{1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024}
+
+func F() ([]*int, []*int) {
+ return g()
+}
+
+func g() ([]*int, []*int) {
+ var s []*int
+ var t []*int
+ for i, j := range slice {
+ s = append(s, &i)
+ t = append(t, &j)
+ }
+ return s[:len(s)-1], t
+}
+-- main.go --
+package main
+
+import (
+ "fmt"
+ "inlines/a"
+ "inlines/b"
+)
+
+func sum(s []*int) int {
+ sum := 0
+ for _, pi := range s {
+ sum += *pi
+ }
+ return sum
+}
+
+func main() {
+ af := a.F()
+ bf, _ := b.F()
+ abf := a.Fb()
+
+ saf, sbf, sabf := sum(af), sum(bf), sum(abf)
+
+ fmt.Printf("af, bf, abf sums = %d, %d, %d\n", saf, sbf, sabf)
+}
diff --git a/src/cmd/go/testdata/script/build_single_error.txt b/src/cmd/go/testdata/script/build_single_error.txt
new file mode 100644
index 0000000..241cdb9
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_single_error.txt
@@ -0,0 +1,18 @@
+# go test ./... with a bad package should report the error once (#44624).
+! go test ./...
+stderr -count=1 undefined
+
+-- go.mod --
+module example.com
+
+go 1.18
+-- a/a.go --
+package a
+
+import "example.com/b"
+-- b/b.go --
+package b
+
+var X = Y
+-- b/b_test.go --
+package b
diff --git a/src/cmd/go/testdata/script/build_static.txt b/src/cmd/go/testdata/script/build_static.txt
new file mode 100644
index 0000000..7db90a1
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_static.txt
@@ -0,0 +1,44 @@
+[short] skip 'links and runs binaries'
+
+# This test requires external linking. Assume that if cgo is supported
+# then external linking works.
+[!cgo] skip 'requires a C linker'
+
+# Only run on Unix systems.
+[GOOS:windows] skip
+[GOOS:plan9] skip
+
+# Ordinary build should work.
+go build
+exec ./hello
+stdout Hello
+
+# Building with -linkmode=external should not say anything about
+# runtime/cgo (issue #31544).
+go build -ldflags=-linkmode=external
+! stderr runtime/cgo
+exec ./hello
+stdout Hello
+
+# Some targets don't support -static
+[GOOS:darwin] skip 'no static linking on Darwin'
+[GOOS:solaris] skip 'no static linking on Solaris'
+
+# Building with -linkmode=external -extldflags=-static should work.
+go build -ldflags='-linkmode=external -extldflags=-static'
+! stderr runtime/cgo
+exec ./hello
+stdout Hello
+
+-- go.mod --
+module hello
+
+go 1.20
+-- hello.go --
+package main
+
+import "fmt"
+
+func main() {
+ fmt.Println("Hello, world")
+}
diff --git a/src/cmd/go/testdata/script/build_tag_goexperiment.txt b/src/cmd/go/testdata/script/build_tag_goexperiment.txt
new file mode 100644
index 0000000..bee218f
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_tag_goexperiment.txt
@@ -0,0 +1,31 @@
+[short] skip
+# Reset all experiments so fieldtrack is definitely off.
+env GOEXPERIMENT=none
+go run m
+stderr 'fieldtrack off'
+# Turn fieldtrack on.
+env GOEXPERIMENT=none,fieldtrack
+go run m
+stderr 'fieldtrack on'
+
+-- ft_off.go --
+// +build !goexperiment.fieldtrack
+
+package main
+
+func main() {
+ println("fieldtrack off")
+}
+
+-- ft_on.go --
+// +build goexperiment.fieldtrack
+
+package main
+
+func main() {
+ println("fieldtrack on")
+}
+
+-- go.mod --
+module m
+go 1.14
diff --git a/src/cmd/go/testdata/script/build_tags_no_comma.txt b/src/cmd/go/testdata/script/build_tags_no_comma.txt
new file mode 100644
index 0000000..a14a200
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_tags_no_comma.txt
@@ -0,0 +1,4 @@
+[compiler:gccgo] skip 'gccgo has no standard packages'
+go build -tags 'tag1 tag2' math
+! go build -tags 'tag1,tag2 tag3' math
+stderr 'space-separated list contains comma' \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/build_test_only.txt b/src/cmd/go/testdata/script/build_test_only.txt
new file mode 100644
index 0000000..8693a80
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_test_only.txt
@@ -0,0 +1,19 @@
+# Named explicitly, test-only packages should be reported as
+# unbuildable/uninstallable, even if there is a wildcard also matching.
+! go build m/testonly m/testonly...
+stderr 'no non-test Go files in'
+! go install ./testonly
+stderr 'no non-test Go files in'
+
+# Named through a wildcard, the test-only packages should be silently ignored.
+go build m/testonly...
+go install ./testonly...
+
+-- go.mod --
+module m
+
+go 1.16
+-- testonly/t_test.go --
+package testonly
+-- testonly2/t.go --
+package testonly2
diff --git a/src/cmd/go/testdata/script/build_trimpath.txt b/src/cmd/go/testdata/script/build_trimpath.txt
new file mode 100644
index 0000000..2a2aa20
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_trimpath.txt
@@ -0,0 +1,164 @@
+[short] skip
+
+# If GOROOT_FINAL is set, 'go build -trimpath' bakes that into the resulting
+# binary instead of GOROOT. Explicitly unset it here.
+env GOROOT_FINAL=
+
+# Set up two identical directories that can be used as GOPATH.
+env GO111MODULE=on
+mkdir $WORK/a/src/paths $WORK/b/src/paths
+cp paths.go $WORK/a/src/paths
+cp paths.go $WORK/b/src/paths
+cp overlay.json $WORK/a/src/paths
+cp overlay.json $WORK/b/src/paths
+cp go.mod $WORK/a/src/paths/
+cp go.mod $WORK/b/src/paths/
+
+
+# A binary built without -trimpath should contain the module root dir
+# and GOROOT for debugging and stack traces.
+cd $WORK/a/src/paths
+go build -o $WORK/paths-dbg.exe .
+exec $WORK/paths-dbg.exe $WORK/paths-dbg.exe
+stdout 'binary contains module root: true'
+stdout 'binary contains GOROOT: true'
+
+# A binary built with -trimpath should not contain the current workspace
+# or GOROOT.
+go build -trimpath -o $WORK/paths-a.exe .
+exec $WORK/paths-a.exe $WORK/paths-a.exe
+stdout 'binary contains module root: false'
+stdout 'binary contains GOROOT: false'
+
+# A binary from an external module built with -trimpath should not contain
+# the current workspace or GOROOT.
+go get rsc.io/fortune
+go install -trimpath rsc.io/fortune
+exec $WORK/paths-a.exe $GOPATH/bin/fortune$GOEXE
+stdout 'binary contains module root: false'
+stdout 'binary contains GOROOT: false'
+go mod edit -droprequire rsc.io/fortune
+
+# Two binaries built from identical packages in different directories
+# should be identical.
+cd $WORK/b/src/paths
+go build -trimpath -o $WORK/paths-b.exe
+cmp -q $WORK/paths-a.exe $WORK/paths-b.exe
+
+
+# Same sequence of tests but with overlays.
+# A binary built without -trimpath should contain the module root dir
+# and GOROOT for debugging and stack traces.
+cd $WORK/a/src/paths
+go build -overlay overlay.json -o $WORK/paths-dbg.exe ./overlaydir
+exec $WORK/paths-dbg.exe $WORK/paths-dbg.exe
+stdout 'binary contains module root: true'
+stdout 'binary contains GOROOT: true'
+
+# A binary built with -trimpath should not contain the current workspace
+# or GOROOT.
+go build -overlay overlay.json -trimpath -o $WORK/paths-a.exe ./overlaydir
+exec $WORK/paths-a.exe $WORK/paths-a.exe
+stdout 'binary contains module root: false'
+stdout 'binary contains GOROOT: false'
+
+# Two binaries built from identical packages in different directories
+# should be identical.
+cd $WORK/b/src/paths
+go build -overlay overlay.json -trimpath -o $WORK/paths-b.exe ./overlaydir
+cmp -q $WORK/paths-a.exe $WORK/paths-b.exe
+
+
+# Same sequence of tests but in GOPATH mode.
+# A binary built without -trimpath should contain GOPATH and GOROOT.
+env GO111MODULE=off
+cd $WORK
+env GOPATH=$WORK/a
+go build -o paths-dbg.exe paths
+exec ./paths-dbg.exe paths-dbg.exe
+stdout 'binary contains GOPATH: true'
+stdout 'binary contains GOROOT: true'
+
+# A binary built with -trimpath should not contain GOPATH or GOROOT.
+go build -trimpath -o paths-a.exe paths
+exec ./paths-a.exe paths-a.exe
+stdout 'binary contains GOPATH: false'
+stdout 'binary contains GOROOT: false'
+
+# Two binaries built from identical packages in different GOPATH roots
+# should be identical.
+env GOPATH=$WORK/b
+go build -trimpath -o paths-b.exe paths
+cmp -q paths-a.exe paths-b.exe
+
+
+# Same sequence of tests but with gccgo.
+# gccgo does not support builds in module mode.
+[!exec:gccgo] stop
+[cross] stop # gccgo can't necessarily cross-compile
+env GOPATH=$WORK/a
+
+# A binary built with gccgo without -trimpath should contain the current
+# GOPATH and GOROOT.
+go build -compiler=gccgo -o paths-dbg.exe paths
+exec ./paths-dbg.exe paths-dbg.exe
+stdout 'binary contains GOPATH: true'
+stdout 'binary contains GOROOT: false' # gccgo doesn't load std from GOROOT.
+
+# A binary built with gccgo with -trimpath should not contain GOPATH or GOROOT.
+go build -compiler=gccgo -trimpath -o paths-a.exe paths
+exec ./paths-a.exe paths-a.exe
+stdout 'binary contains GOPATH: false'
+stdout 'binary contains GOROOT: false'
+
+# Two binaries built from identical packages in different directories
+# should be identical.
+env GOPATH=$WORK/b
+go build -compiler=gccgo -trimpath -o paths-b.exe paths
+cmp -q paths-a.exe paths-b.exe
+
+-- paths.go --
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+)
+
+func main() {
+ exe := os.Args[1]
+ data, err := ioutil.ReadFile(exe)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ if os.Getenv("GO111MODULE") == "on" {
+ out, err := exec.Command("go", "env", "GOMOD").Output()
+ if err != nil {
+ log.Fatal(err)
+ }
+ modRoot := filepath.Dir(strings.TrimSpace(string(out)))
+ check(data, "module root", modRoot)
+ } else {
+ check(data, "GOPATH", os.Getenv("GOPATH"))
+ }
+ check(data, "GOROOT", os.Getenv("GOROOT"))
+}
+
+func check(data []byte, desc, dir string) {
+ containsDir := bytes.Contains(data, []byte(dir))
+ containsSlashDir := bytes.Contains(data, []byte(filepath.ToSlash(dir)))
+ fmt.Printf("binary contains %s: %v\n", desc, containsDir || containsSlashDir)
+}
+-- overlay.json --
+{ "Replace": { "overlaydir/paths.go": "paths.go" } }
+-- go.mod --
+module paths
+
+go 1.14
diff --git a/src/cmd/go/testdata/script/build_trimpath_cgo.txt b/src/cmd/go/testdata/script/build_trimpath_cgo.txt
new file mode 100644
index 0000000..5289824
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_trimpath_cgo.txt
@@ -0,0 +1,184 @@
+# This test builds a cgo binary and verifies the source directory path
+# does not appear in the binary, either literally or in compressed DWARF.
+# TODO(golang.org/issue/36072): ideally we should build a binary from identical
+# sources in different directories and verify the binary and all intermediate
+# files are identical.
+
+[short] skip
+[!cgo] skip
+
+# Check that the source path appears when -trimpath is not used.
+go build -o hello.exe .
+grep -q gopath[/\\]src hello.exe
+go run ./list-dwarf hello.exe
+stdout gopath[/\\]src
+
+# Check that the source path does not appear when -trimpath is used.
+[GOOS:aix] stop # can't inspect XCOFF binaries
+go build -trimpath -o hello.exe .
+! grep -q gopath[/\\]src hello.exe
+go run ./list-dwarf hello.exe
+! stdout gopath/src
+
+
+# Do the above, with the cgo (but not .c) sources in an overlay
+# Check that the source path appears when -trimpath is not used.
+mkdir $WORK/overlay
+cp hello.go $WORK/overlay/hello.go
+mkdir hello_overlay
+cp hello.c hello_overlay/hello.c
+go build -overlay overlay.json -o hello_overlay.exe ./hello_overlay
+grep -q gopath[/\\]src hello_overlay.exe
+! grep -q $WORK[/\\]overlay hello_overlay.exe
+go run ./list-dwarf hello_overlay.exe
+stdout gopath[/\\]src
+! stdout $WORK[/\\]overlay
+
+# Check that the source path does not appear when -trimpath is used.
+go build -overlay overlay.json -trimpath -o hello_overlay.exe ./hello_overlay
+! grep -q gopath[/\\]src hello_overlay.exe
+! grep -q $WORK[/\\]overlay hello_overlay.exe
+go run ./list-dwarf hello_overlay.exe
+! stdout gopath/src
+! stdout $WORK[/\\]overlay
+
+-- go.mod --
+module m
+
+go 1.14
+-- overlay.json --
+{
+ "Replace": {
+ "hello_overlay/hello.go": "../../overlay/hello.go"
+ }
+}
+-- hello.c --
+#include <stdio.h>
+
+void say_hello() { puts("Hello, world!\n"); }
+
+-- hello.go --
+package main
+
+// void say_hello();
+import "C"
+
+func main() {
+ C.say_hello()
+}
+
+-- list-dwarf/list-dwarf.go --
+package main
+
+import (
+ "debug/dwarf"
+ "fmt"
+ "io"
+ "log"
+ "os"
+ "sort"
+)
+
+func main() {
+ files, err := run(os.Args[1])
+ if err != nil {
+ log.Fatal(err)
+ }
+ for _, file := range files {
+ fmt.Println(file)
+ }
+}
+
+func run(exePath string) ([]string, error) {
+ dwarfData, err := readDWARF(exePath)
+ if err != nil {
+ return nil, err
+ }
+
+ dwarfReader := dwarfData.Reader()
+ files := make(map[string]bool)
+ for {
+ e, err := dwarfReader.Next()
+ if err != nil {
+ return nil, err
+ }
+ if e == nil {
+ break
+ }
+ lr, err := dwarfData.LineReader(e)
+ if err != nil {
+ return nil, err
+ }
+ if lr == nil {
+ continue
+ }
+
+ var le dwarf.LineEntry
+ for {
+ if err := lr.Next(&le); err != nil {
+ if err == io.EOF {
+ break
+ }
+ return nil, err
+ }
+ files[le.File.Name] = true
+ }
+ }
+
+ sortedFiles := make([]string, 0, len(files))
+ for file := range files {
+ sortedFiles = append(sortedFiles, file)
+ }
+ sort.Strings(sortedFiles)
+ return sortedFiles, nil
+}
+-- list-dwarf/read_darwin.go --
+package main
+
+import (
+ "debug/dwarf"
+ "debug/macho"
+)
+
+func readDWARF(exePath string) (*dwarf.Data, error) {
+ machoFile, err := macho.Open(exePath)
+ if err != nil {
+ return nil, err
+ }
+ defer machoFile.Close()
+ return machoFile.DWARF()
+}
+-- list-dwarf/read_elf.go --
+// +build android dragonfly freebsd illumos linux netbsd openbsd solaris
+
+package main
+
+import (
+ "debug/dwarf"
+ "debug/elf"
+)
+
+func readDWARF(exePath string) (*dwarf.Data, error) {
+ elfFile, err := elf.Open(exePath)
+ if err != nil {
+ return nil, err
+ }
+ defer elfFile.Close()
+ return elfFile.DWARF()
+}
+-- list-dwarf/read_windows.go --
+package main
+
+import (
+ "debug/dwarf"
+ "debug/pe"
+)
+
+func readDWARF(exePath string) (*dwarf.Data, error) {
+ peFile, err := pe.Open(exePath)
+ if err != nil {
+ return nil, err
+ }
+ defer peFile.Close()
+ return peFile.DWARF()
+}
diff --git a/src/cmd/go/testdata/script/build_trimpath_goroot.txt b/src/cmd/go/testdata/script/build_trimpath_goroot.txt
new file mode 100644
index 0000000..a26cfd2
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_trimpath_goroot.txt
@@ -0,0 +1,103 @@
+# Regression test for https://go.dev/issue/51461 and https://go.dev/issue/51483.
+#
+# When built with -trimpath, runtime.GOROOT() returned the bogus string "go"
+# if GOROOT was not set explicitly in the environment.
+# It should instead return the empty string, since we know that we don't
+# have a valid path to return.
+#
+# TODO(#51483): when runtime.GOROOT() returns the empty string,
+# go/build should default to 'go env GOROOT' instead.
+
+env GOROOT_FINAL=
+
+[trimpath] env GOROOT=
+[trimpath] ! go env GOROOT
+[trimpath] stderr '^go: cannot find GOROOT directory: ''go'' binary is trimmed and GOROOT is not set$'
+[trimpath] env GOROOT=$TESTGO_GOROOT
+
+[short] stop
+
+# With GOROOT still set but GOROOT_FINAL unset, 'go build' and 'go test -c'
+# should cause runtime.GOROOT() to report either the correct GOROOT
+# (without -trimpath) or no GOROOT at all (with -trimpath).
+
+go build -o example.exe .
+go build -trimpath -o example-trimpath.exe .
+go test -c -o example.test.exe .
+go test -trimpath -c -o example.test-trimpath.exe .
+
+env GOROOT=
+
+exec ./example.exe
+stdout '^GOROOT '$TESTGO_GOROOT'$'
+stdout '^runtime '$TESTGO_GOROOT${/}src${/}runtime'$'
+
+! exec ./example-trimpath.exe
+stdout '^GOROOT $'
+stderr 'cannot find package "runtime" in any of:\n\t\(\$GOROOT not set\)\n\t'$WORK${/}gopath${/}src${/}runtime' \(from \$GOPATH\)\n\z'
+
+exec ./example.test.exe -test.v
+stdout '^GOROOT '$TESTGO_GOROOT'$'
+stdout '^runtime '$TESTGO_GOROOT${/}src${/}runtime'$'
+
+! exec ./example.test-trimpath.exe -test.v
+stdout '^GOROOT $'
+stderr 'cannot find package "runtime" in any of:\n\t\(\$GOROOT not set\)\n\t'$WORK${/}gopath${/}src${/}runtime' \(from \$GOPATH\)$'
+
+# If a correct GOROOT is baked in to the 'go' command itself, 'go run' and
+# 'go test' should not implicitly set GOROOT in the process environment
+# (because that could mask an unexpected production dependency on the GOROOT
+# environment variable), but 'go generate' should (because the generator may
+# reasonably expect to be able to locate the GOROOT for which it is generating
+# code).
+
+[trimpath] stop
+[mismatched-goroot] stop
+
+! go run -trimpath .
+stdout '^GOROOT $'
+stderr 'cannot find package "runtime" in any of:\n\t\(\$GOROOT not set\)\n\t'$WORK${/}gopath${/}src${/}runtime' \(from \$GOPATH\)\nexit status 1\n\z'
+
+! go test -trimpath -v .
+stdout '^GOROOT $'
+stdout 'cannot find package "runtime" in any of:\n\t\(\$GOROOT not set\)\n\t'$WORK${/}gopath${/}src${/}runtime' \(from \$GOPATH\)$'
+
+env GOFLAGS=-trimpath
+go generate .
+stdout '^GOROOT '$TESTGO_GOROOT'$'
+stdout '^runtime '$TESTGO_GOROOT${/}src${/}runtime'$'
+
+-- go.mod --
+module example
+
+go 1.19
+-- main.go --
+package main
+
+//go:generate go run .
+
+import (
+ "fmt"
+ "go/build"
+ "os"
+ "runtime"
+)
+
+func main() {
+ fmt.Println("GOROOT", runtime.GOROOT())
+
+ p, err := build.Default.Import("runtime", "", build.FindOnly)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ fmt.Println("runtime", p.Dir)
+}
+-- main_test.go --
+package main
+
+import "testing"
+
+func TestMain(*testing.M) {
+ main()
+}
diff --git a/src/cmd/go/testdata/script/build_unsupported_goos.txt b/src/cmd/go/testdata/script/build_unsupported_goos.txt
new file mode 100644
index 0000000..c94d6d2
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_unsupported_goos.txt
@@ -0,0 +1,6 @@
+[compiler:gccgo] skip # gccgo assumes cross-compilation is always possible
+
+env GOOS=windwos # intentional misspelling of windows
+
+! go build -n exclude
+stderr 'unsupported GOOS/GOARCH pair'
diff --git a/src/cmd/go/testdata/script/build_vendor.txt b/src/cmd/go/testdata/script/build_vendor.txt
new file mode 100644
index 0000000..f430ff2
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_vendor.txt
@@ -0,0 +1,42 @@
+# Build
+env GO111MODULE=off
+go build vend/x
+! stdout .
+! stderr .
+
+-- vend/dir1/dir1.go --
+package dir1
+-- vend/subdir/bad.go --
+package subdir
+
+import _ "r"
+-- vend/subdir/good.go --
+package subdir
+
+import _ "p"
+-- vend/vendor/p/p.go --
+package p
+-- vend/vendor/q/q.go --
+package q
+-- vend/vendor/vend/dir1/dir2/dir2.go --
+package dir2
+-- vend/x/invalid/invalid.go --
+package invalid
+
+import "vend/x/invalid/vendor/foo"
+-- vend/x/vendor/p/p/p.go --
+package p
+
+import _ "notfound"
+-- vend/x/vendor/p/p.go --
+package p
+-- vend/x/vendor/r/r.go --
+package r
+-- vend/x/x.go --
+package x
+
+import _ "p"
+import _ "q"
+import _ "r"
+import _ "vend/dir1" // not vendored
+import _ "vend/dir1/dir2" // vendored
diff --git a/src/cmd/go/testdata/script/cache_unix.txt b/src/cmd/go/testdata/script/cache_unix.txt
new file mode 100644
index 0000000..e11804d
--- /dev/null
+++ b/src/cmd/go/testdata/script/cache_unix.txt
@@ -0,0 +1,37 @@
+env GO111MODULE=off
+
+# Integration test for cache directory calculation (cmd/go/internal/cache).
+
+[GOOS:windows] skip 'windows does not use XDG_CACHE_HOME'
+[GOOS:darwin] skip 'darwin does not use XDG_CACHE_HOME'
+[GOOS:ios] skip 'ios does not use XDG_CACHE_HOME'
+[GOOS:plan9] skip 'plan9 does not use XDG_CACHE_HOME'
+
+mkdir $WORK/gocache
+mkdir $WORK/xdg
+mkdir $WORK/home
+
+# Set GOCACHE, XDG_CACHE_HOME, and HOME.
+env GOCACHE=$WORK/gocache
+env XDG_CACHE_HOME=$WORK/xdg
+env HOME=$WORK/home
+
+# With all three set, we should prefer GOCACHE.
+go env GOCACHE
+stdout $WORK'/gocache$'
+
+# Without GOCACHE, we should prefer XDG_CACHE_HOME over HOME.
+env GOCACHE=
+go env GOCACHE
+stdout $WORK'/xdg/go-build$$'
+
+# With only HOME set, we should use $HOME/.cache.
+env XDG_CACHE_HOME=
+go env GOCACHE
+stdout $WORK'/home/.cache/go-build$'
+
+# With no guidance from the environment, we must disable the cache, but that
+# should not cause commands that do not write to the cache to fail.
+env HOME=
+go env GOCACHE
+stdout 'off'
diff --git a/src/cmd/go/testdata/script/cache_vet.txt b/src/cmd/go/testdata/script/cache_vet.txt
new file mode 100644
index 0000000..6689048
--- /dev/null
+++ b/src/cmd/go/testdata/script/cache_vet.txt
@@ -0,0 +1,22 @@
+env GO111MODULE=off
+
+[short] skip
+[GODEBUG:gocacheverify=1] skip
+[compiler:gccgo] skip # gccgo has no standard packages
+
+# Start with a clean build cache:
+# test failures may be masked if the cache has just the right entries already.
+env GOCACHE=$WORK/cache
+
+# Run 'go vet os/user' once to warm up the cache.
+go vet os/user
+
+# Check that second vet reuses cgo-derived inputs.
+# The first command could be build instead of vet,
+# except that if the cache is empty and there's a net.a
+# in GOROOT/pkg, the build will not bother to regenerate
+# and cache the cgo outputs, whereas vet always will.
+
+go vet -x os/user
+! stderr '^(clang|gcc)' # should not have run compiler
+! stderr '[\\/]cgo ' # should not have run cgo
diff --git a/src/cmd/go/testdata/script/cgo_asm_error.txt b/src/cmd/go/testdata/script/cgo_asm_error.txt
new file mode 100644
index 0000000..7aaa713
--- /dev/null
+++ b/src/cmd/go/testdata/script/cgo_asm_error.txt
@@ -0,0 +1,25 @@
+[!cgo] skip
+
+# Test that cgo package can't contain a go assembly file.
+
+# Ensure the build fails and reports that the package has a Go assembly file.
+! go build cgoasm
+stderr 'package using cgo has Go assembly file'
+
+-- go.mod --
+module cgoasm
+
+go 1.16
+-- p.go --
+package p
+
+/*
+// hi
+*/
+import "C"
+
+func F() {}
+-- p.s --
+TEXT asm(SB),$0
+ RET
+
diff --git a/src/cmd/go/testdata/script/cgo_bad_directives.txt b/src/cmd/go/testdata/script/cgo_bad_directives.txt
new file mode 100644
index 0000000..7d28171
--- /dev/null
+++ b/src/cmd/go/testdata/script/cgo_bad_directives.txt
@@ -0,0 +1,129 @@
+[!cgo] skip
+[short] skip
+
+cp x.go.txt x.go
+
+# Only allow //go:cgo_ldflag .* in cgo-generated code
+[compiler:gc] cp x_gc.go.txt x.go
+[compiler:gc] ! go build x
+[compiler:gc] stderr '//go:cgo_ldflag .* only allowed in cgo-generated code'
+
+# Ignore _* files
+rm x.go
+! go build .
+stderr 'no Go files'
+cp cgo_yy.go.txt _cgo_yy.go
+! go build .
+stderr 'no Go files' #_* files are ignored...
+
+[compiler:gc] ! go build _cgo_yy.go # ... but if forced, the comment is rejected
+# Actually, today there is a separate issue that _ files named
+# on the command line are ignored. Once that is fixed,
+# we want to see the cgo_ldflag error.
+[compiler:gc] stderr '//go:cgo_ldflag only allowed in cgo-generated code|no Go files'
+
+rm _cgo_yy.go
+
+# Reject #cgo CFLAGS: -fplugin=foo.so
+cp x.go.txt x.go
+cp y_fplugin.go.txt y.go
+! go build x
+stderr 'invalid flag in #cgo CFLAGS: -fplugin=foo.so'
+
+# Reject #cgo CFLAGS: -lbar -fplugin=foo.so
+cp y_lbar_fplugin.go.txt y.go
+! go build x
+stderr 'invalid flag in #cgo CFLAGS: -fplugin=foo.so'
+
+# Reject #cgo pkg-config: -foo
+cp y_pkgconfig_dash_foo.txt y.go
+! go build x
+stderr 'invalid pkg-config package name: -foo'
+
+# Reject #cgo pkg-config: @foo
+cp y_pkgconfig_at_foo.txt y.go
+! go build x
+stderr 'invalid pkg-config package name: @foo'
+
+# Reject #cgo CFLAGS: @foo
+cp y_cflags_at_foo.txt y.go
+! go build x
+stderr 'invalid flag in #cgo CFLAGS: @foo'
+
+# Reject #cgo CFLAGS: -D
+cp y_cflags_dash_d.txt y.go
+! go build x
+stderr 'invalid flag in #cgo CFLAGS: -D without argument'
+
+# Note that -I @foo is allowed because we rewrite it into -I /path/to/src/@foo
+# before the check is applied. There's no such rewrite for -D.
+
+# Reject #cgo CFLAGS: -D @foo
+cp y_cflags_dash_d_space_at_foo.txt y.go
+! go build x
+stderr 'invalid flag in #cgo CFLAGS: -D @foo'
+
+# Reject #cgo CFLAGS -D@foo
+cp y_cflags_dash_d_at_foo.txt y.go
+! go build x
+stderr 'invalid flag in #cgo CFLAGS: -D@foo'
+
+# Check for CFLAGS in commands
+env CGO_CFLAGS=-D@foo
+cp y_no_cflags.txt y.go
+go build -n x
+stderr '-D@foo'
+
+-- go.mod --
+module x
+
+go 1.16
+-- x_gc.go.txt --
+package x
+
+//go:cgo_ldflag "-fplugin=foo.so"
+
+import "C"
+-- cgo_yy.go.txt --
+package x
+
+//go:cgo_ldflag "-fplugin=foo.so"
+
+import "C"
+-- x.go.txt --
+package x
+-- y_fplugin.go.txt --
+package x
+// #cgo CFLAGS: -fplugin=foo.so
+import "C"
+-- y_lbar_fplugin.go.txt --
+package x
+// #cgo CFLAGS: -Ibar -fplugin=foo.so
+import "C"
+-- y_pkgconfig_dash_foo.txt --
+package x
+// #cgo pkg-config: -foo
+import "C"
+-- y_pkgconfig_at_foo.txt --
+package x
+// #cgo pkg-config: @foo
+import "C"
+-- y_cflags_at_foo.txt --
+package x
+// #cgo CFLAGS: @foo
+import "C"
+-- y_cflags_dash_d.txt --
+package x
+// #cgo CFLAGS: -D
+import "C"
+-- y_cflags_dash_d_space_at_foo.txt --
+package x
+// #cgo CFLAGS: -D @foo
+import "C"
+-- y_cflags_dash_d_at_foo.txt --
+package x
+// #cgo CFLAGS: -D@foo
+import "C"
+-- y_no_cflags.txt --
+package x
+import "C"
diff --git a/src/cmd/go/testdata/script/cgo_badmethod_issue57926.txt b/src/cmd/go/testdata/script/cgo_badmethod_issue57926.txt
new file mode 100644
index 0000000..81ef850
--- /dev/null
+++ b/src/cmd/go/testdata/script/cgo_badmethod_issue57926.txt
@@ -0,0 +1,31 @@
+[short] skip
+[!cgo] skip
+
+# Test that cgo rejects attempts to declare methods
+# on the types C.T or *C.T; see issue #57926.
+
+! go build
+stderr 'cannot define new methods on non-local type C.T'
+stderr 'cannot define new methods on non-local type \*C.T'
+! stderr 'Alias'
+
+-- go.mod --
+module example.com
+go 1.12
+
+-- a.go --
+package a
+
+/*
+typedef int T;
+*/
+import "C"
+
+func (C.T) f() {}
+func (recv *C.T) g() {}
+
+// The check is more education than enforcement,
+// and is easily defeated using a type alias.
+type Alias = C.T
+func (Alias) h() {}
+func (*Alias) i() {}
diff --git a/src/cmd/go/testdata/script/cgo_depends_on_syscall.txt b/src/cmd/go/testdata/script/cgo_depends_on_syscall.txt
new file mode 100644
index 0000000..bd4777c
--- /dev/null
+++ b/src/cmd/go/testdata/script/cgo_depends_on_syscall.txt
@@ -0,0 +1,15 @@
+[!cgo] skip
+[!race] skip
+
+go list -race -deps foo
+stdout syscall
+
+-- go.mod --
+module foo
+
+go 1.16
+-- foo.go --
+package foo
+
+// #include <stdio.h>
+import "C"
diff --git a/src/cmd/go/testdata/script/cgo_flag_contains_space.txt b/src/cmd/go/testdata/script/cgo_flag_contains_space.txt
new file mode 100644
index 0000000..a3372bb
--- /dev/null
+++ b/src/cmd/go/testdata/script/cgo_flag_contains_space.txt
@@ -0,0 +1,16 @@
+[short] skip
+[!cgo] skip
+
+env GOCACHE=$WORK/gocache # Looking for compile flags, so need a clean cache.
+go build -x -n main.go
+stderr '"-I[^"]+c flags"' # find quoted c flags
+! stderr '"-I[^"]+c flags".*"-I[^"]+c flags"' # don't find too many quoted c flags per line
+stderr '"-L[^"]+ld flags"' # find quoted ld flags
+! stderr '"-L[^"]+c flags".*"-L[^"]+c flags"' # don't find too many quoted ld flags per line
+
+-- main.go --
+package main
+// #cgo CFLAGS: -I"c flags"
+// #cgo LDFLAGS: -L"ld flags"
+import "C"
+func main() {}
diff --git a/src/cmd/go/testdata/script/cgo_path.txt b/src/cmd/go/testdata/script/cgo_path.txt
new file mode 100644
index 0000000..be23893
--- /dev/null
+++ b/src/cmd/go/testdata/script/cgo_path.txt
@@ -0,0 +1,41 @@
+[!cgo] skip
+
+# Require that CC is something that requires a PATH lookup.
+# Normally, the default is gcc or clang, but if CC was set during make.bash,
+# that becomes the default.
+[!cc:clang] [!cc:gcc] skip 'C compiler is not gcc or clang'
+
+env GOCACHE=$WORK/gocache # Looking for compile flags, so need a clean cache.
+[!GOOS:windows] env PATH=.:$PATH
+[!GOOS:windows] chmod 0755 p/gcc p/clang
+[!GOOS:windows] exists -exec p/gcc p/clang
+[GOOS:windows] exists -exec p/gcc.bat p/clang.bat
+! exists p/bug.txt
+! go build -x
+stderr '^cgo: C compiler "(clang|gcc)" not found: exec: "(clang|gcc)": cannot run executable found relative to current directory'
+! exists p/bug.txt
+
+-- go.mod --
+module m
+
+-- m.go --
+package m
+
+import _ "m/p"
+
+-- p/p.go --
+package p
+
+// #define X 1
+import "C"
+
+-- p/gcc --
+#!/bin/sh
+echo ran gcc >bug.txt
+-- p/clang --
+#!/bin/sh
+echo ran clang >bug.txt
+-- p/gcc.bat --
+echo ran gcc >bug.txt
+-- p/clang.bat --
+echo ran clang >bug.txt
diff --git a/src/cmd/go/testdata/script/cgo_path_space.txt b/src/cmd/go/testdata/script/cgo_path_space.txt
new file mode 100644
index 0000000..1a78902
--- /dev/null
+++ b/src/cmd/go/testdata/script/cgo_path_space.txt
@@ -0,0 +1,56 @@
+# Check that if the PATH directory containing the C compiler has a space,
+# we can still use that compiler with cgo.
+# Verifies #43808.
+[!cgo] skip
+
+# Set CC explicitly to something that requires a PATH lookup.
+# Normally, the default is gcc or clang, but if CC was set during make.bash,
+# that becomes the default.
+[exec:clang] env CC=clang
+[exec:gcc] env CC=gcc
+[!exec:clang] [!exec:gcc] skip 'Unknown C compiler'
+
+[!GOOS:windows] chmod 0755 $WORK/'program files'/clang
+[!GOOS:windows] chmod 0755 $WORK/'program files'/gcc
+[!GOOS:windows] exists -exec $WORK/'program files'/clang
+[!GOOS:windows] exists -exec $WORK/'program files'/gcc
+[!GOOS:windows] env PATH=$WORK/'program files':$PATH
+[GOOS:windows] exists -exec $WORK/'program files'/gcc.bat
+[GOOS:windows] exists -exec $WORK/'program files'/clang.bat
+[GOOS:windows] env PATH=$WORK\'program files';%PATH%
+
+! exists $WORK/log.txt
+? go build -x
+exists $WORK/log.txt
+rm $WORK/log.txt
+
+# TODO(#41400, #43078): when CC is set explicitly, it should be allowed to
+# contain spaces separating arguments, and it should be possible to quote
+# arguments with spaces (including the path), as in CGO_CFLAGS and other
+# variables. For now, this doesn't work.
+[!GOOS:windows] env CC=$WORK/'program files'/gcc
+[GOOS:windows] env CC=$WORK\'program files'\gcc.bat
+! go build -x
+! exists $WORK/log.txt
+
+-- go.mod --
+module m
+
+-- m.go --
+package m
+
+// #define X 1
+import "C"
+
+-- $WORK/program files/gcc --
+#!/bin/sh
+
+echo ok >$WORK/log.txt
+-- $WORK/program files/clang --
+#!/bin/sh
+
+echo ok >$WORK/log.txt
+-- $WORK/program files/gcc.bat --
+echo ok >%WORK%\log.txt
+-- $WORK/program files/clang.bat --
+echo ok >%WORK%\log.txt
diff --git a/src/cmd/go/testdata/script/cgo_path_space_quote.txt b/src/cmd/go/testdata/script/cgo_path_space_quote.txt
new file mode 100644
index 0000000..9556101
--- /dev/null
+++ b/src/cmd/go/testdata/script/cgo_path_space_quote.txt
@@ -0,0 +1,58 @@
+# This test checks that the CC environment variable may contain quotes and
+# spaces. Arguments are normally split on spaces, tabs, newlines. If an
+# argument contains these characters, the entire argument may be quoted
+# with single or double quotes. This is the same as -gcflags and similar
+# options.
+
+[short] skip
+[!exec:clang] [!exec:gcc] skip
+[!cgo] skip
+
+env GOENV=$WORK/go.env
+mkdir 'program files'
+go build -o 'program files' './which cc/which cc.go'
+[exec:clang] env CC='"'$PWD${/}program' 'files${/}which' 'cc"' 'clang
+[!exec:clang] env CC='"'$PWD${/}program' 'files${/}which' 'cc"' 'gcc
+go env CC
+stdout 'program files[/\\]which cc" (clang|gcc)$'
+go env -w CC=$CC
+env CC=
+go env CC
+stdout 'program files[/\\]which cc" (clang|gcc)$'
+
+go run .
+stdout 1
+
+-- go.mod --
+module test
+
+go 1.17
+-- which cc/which cc.go --
+package main
+
+import (
+ "fmt"
+ "os"
+ "os/exec"
+)
+
+func main() {
+ args := append([]string{"-DWRAPPER_WAS_USED=1"}, os.Args[2:]...)
+ cmd := exec.Command(os.Args[1], args...)
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ if err := cmd.Run(); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+}
+-- hello.go --
+package main
+
+// int x = WRAPPER_WAS_USED;
+import "C"
+import "fmt"
+
+func main() {
+ fmt.Println(C.x)
+}
diff --git a/src/cmd/go/testdata/script/cgo_stale.txt b/src/cmd/go/testdata/script/cgo_stale.txt
new file mode 100644
index 0000000..0d30aea
--- /dev/null
+++ b/src/cmd/go/testdata/script/cgo_stale.txt
@@ -0,0 +1,39 @@
+# golang.org/issue/46347: a stale runtime/cgo should only force a single rebuild
+
+[!cgo] skip
+[short] skip
+
+
+# If we set a unique CGO_CFLAGS, the installed copy of runtime/cgo
+# should be reported as stale.
+
+env CGO_CFLAGS=-DTestScript_cgo_stale=true
+stale runtime/cgo
+
+
+# If we then build a package that uses cgo, runtime/cgo should be rebuilt and
+# cached with the new flag, but not installed to GOROOT.
+# It has no install target, and thus is never stale.
+
+env GOCACHE=$WORK/cache # Use a fresh cache to avoid interference between runs.
+
+go build -x .
+stderr '[/\\]cgo'$GOEXE'["]? .* -importpath runtime/cgo'
+! stale runtime/cgo
+
+
+# After runtime/cgo has been rebuilt and cached, it should not be rebuilt again.
+
+go build -x .
+! stderr '[/\\]cgo'$GOEXE'["]? .* -importpath runtime/cgo'
+! stale runtime/cgo
+
+
+-- go.mod --
+module example.com/m
+
+go 1.17
+-- m.go --
+package m
+
+import "C"
diff --git a/src/cmd/go/testdata/script/cgo_stale_precompiled.txt b/src/cmd/go/testdata/script/cgo_stale_precompiled.txt
new file mode 100644
index 0000000..b2a0e0c
--- /dev/null
+++ b/src/cmd/go/testdata/script/cgo_stale_precompiled.txt
@@ -0,0 +1,40 @@
+# Regression test for https://go.dev/issue/47215 and https://go.dev/issue/50183:
+# A mismatched $GOROOT_FINAL or missing $CC caused the C dependencies of the net
+# package to appear stale, and it could not be rebuilt due to a missing $CC.
+
+[!cgo] skip
+
+# This test may start with the runtime/cgo package already stale.
+# Explicitly rebuild it to ensure that it is cached.
+# (See https://go.dev/issue/50892.)
+#
+# If running in non-short mode, explicitly vary CGO_CFLAGS
+# as a control case (to ensure that our regexps do catch rebuilds).
+
+[!short] env GOCACHE=$WORK/cache
+[!short] env CGO_CFLAGS=-DTestScript_cgo_stale_precompiled=true
+go build -x runtime/cgo
+[!short] stderr '[/\\]cgo'$GOEXE'["]? .* -importpath runtime/cgo'
+
+# https://go.dev/issue/50183: a mismatched GOROOT_FINAL caused net to be stale.
+env oldGOROOT_FINAL=$GOROOT_FINAL
+env GOROOT_FINAL=$WORK${/}goroot
+go build -x runtime/cgo
+! stderr '[/\\]cgo'$GOEXE'["]? .* -importpath runtime/cgo'
+
+env GOROOT_FINAL=$oldGOROOT_FINAL
+
+# https://go.dev/issue/47215: a missing $(go env CC) caused the precompiled net
+# to be stale. But as of https://go.dev/cl/452457 the precompiled libraries are
+# no longer installed anyway! Since we're requiring a C compiler in order to
+# build and use cgo libraries in the standard library, we should make sure it
+# matches what's in the cache.
+
+[abscc] stop
+
+env CGO_ENABLED=1
+env CC=''
+[!GOOS:plan9] env PATH='' # Guaranteed not to include $(go env CC)!
+[GOOS:plan9] env path=''
+! go build -x runtime/cgo
+stderr 'C compiler .* not found'
diff --git a/src/cmd/go/testdata/script/cgo_suspect_flag_force_external.txt b/src/cmd/go/testdata/script/cgo_suspect_flag_force_external.txt
new file mode 100644
index 0000000..6dc30be
--- /dev/null
+++ b/src/cmd/go/testdata/script/cgo_suspect_flag_force_external.txt
@@ -0,0 +1,201 @@
+# Test case to verify that when we have a package that uses CGO in
+# combination with selected "unusual" flags (involving plugins, LTO)
+# that we force external linking. See related
+# issues 58619, 58620, and 58848.
+
+[compiler:gccgo] skip # only external linking for gccgo
+
+[!cgo] skip 'test verifies behavior that depends on CGO_CFLAGS'
+[mustlinkext] skip 'test expects internal linking for non-cgo programs'
+
+# Here we build three program: one with explicit CGO use, one with no
+# CGO use, and one that uses a stdlib package ("runtime/cgo") that has
+# CGO in it. It used to be that only the explicit use of CGO would
+# trigger external linking, and that the program that only used
+# "runtime/cgo" would always be handled with internal linking. This caused
+# issues when users included odd/unusual flags (ex: -fplugin, -flto)
+# in CGO_CFLAGS, causing the Go linker to have to read and interpret
+# non-standard host objects.
+#
+# As of 1.21 we continue to use internal linking for programs whose
+# CGO use comes only from stdlib packages in the absence of any flag
+# funny business, however if the Go command sees flags that may be suspicious,
+# it signals the Go linker to invoke the external linker.
+
+# The next few tests run builds passing "-n" to the Go command, then
+# checking the output to see if the Go command is trying to pass a
+# "preferlinkext" token to the linker to request external linking.
+
+#-----------------------
+
+# Use a fresh GOCACHE for these next steps, so as to have the real
+# actions for the runtime/cgo package appear in the "-n -x" output.
+env GOCACHE=$WORK/gocache
+mkdir $GOCACHE
+
+# First build: there is no CGO in use, so no token should be present regardless
+# of weird CGO flags.
+go build -x -n -o dummy.exe ./noUseOfCgo
+! stderr preferlinkext
+env CGO_CFLAGS=-flto
+go build -x -n -o dummy.exe ./noUseOfCgo
+! stderr preferlinkext
+env CGO_CFLAGS=
+
+# Second build uses CGO, so we expect to see the token present in the
+# -n output only when strange flags are used.
+go build -x -n -o dummy.exe ./usesInternalCgo
+! stderr preferlinkext
+env CGO_CFLAGS=-flto
+go build -x -n -o dummy.exe ./usesInternalCgo
+stderr preferlinkext
+env CGO_CFLAGS=-fplugin
+go build -x -n -o dummy.exe ./usesInternalCgo
+stderr preferlinkext
+env CGO_CFLAGS=-fprofile-instr-generate
+go build -x -n -o dummy.exe ./usesInternalCgo
+stderr preferlinkext
+
+# The -fdebug-prefix-map=path is permitted for internal linking.
+env CGO_CFLAGS=-fdebug-prefix-map=/some/sandbox/execroot/workspace=/tmp/new
+go build -x -n -o dummy.exe ./usesInternalCgo
+! stderr preferlinkext
+env CGO_CFLAGS=-fdebug-prefix-map=/Users/someone/.cache/bazel/_bazel_someone/3fa7e4650c43657ead684537951f49e2/sandbox/linux-sandbox/10/execroot/rules_go_static=.
+go build -x -n -o dummy.exe ./usesInternalCgo
+! stderr preferlinkext
+# The -ffile-prefix-map=path is permitted for internal linking too.
+env CGO_CFLAGS=-ffile-prefix-map=/Users/someone/.cache/bazel/_bazel_someone/3fa7e4650c43657ead684537951f49e2/sandbox/linux-sandbox/10/execroot/rules_go_static/bazel-out/aarch64-fastbuild-ST-b33d65c724e6/bin/external/io_bazel_rules_go/stdlib_=.
+go build -x -n -o dummy.exe ./usesInternalCgo
+! stderr preferlinkext
+# Verifying that -fdebug-prefix-map=path, -ffile-prefix-map, -no-canonical-prefixes
+# and -fno-canonical-systemd-headers are permitted for internal linking.
+env CGO_CFLAGS=-fdebug-prefix-map=old=/tmp/new
+go build -x -n -o dummy.exe ./usesInternalCgo
+! stderr preferlinkext
+env CGO_CFLAGS=-ffile-prefix-map=/Users/someone/_11233/things=new
+go build -x -n -o dummy.exe ./usesInternalCgo
+! stderr preferlinkext
+env CGO_CFLAGS=-no-canonical-prefixes
+go build -x -n -o dummy.exe ./usesInternalCgo
+! stderr preferlinkext
+env CGO_CFLAGS=-fno-canonical-system-headers
+go build -x -n -o dummy.exe ./usesInternalCgo
+! stderr preferlinkext
+env CGO_CFLAGS=
+
+[short] skip
+
+# In the remaining tests below we do actual builds (without -n) to
+# verify that the Go linker is going the right thing in addition to the
+# Go command. Here the idea is to pass "-tmpdir" to the linker, then
+# check after the link is done for the presence of the file
+# <tmpdir>/go.o, which the Go linker creates prior to kicking off the
+# external linker.
+
+mkdir tmp1
+mkdir tmp2
+mkdir tmp3
+mkdir tmp4
+mkdir tmp5
+
+# First build: no external linking expected
+go build -ldflags=-tmpdir=tmp1 -o $devnull ./noUseOfCgo &
+
+# Second build: using only "runtime/cgo", expect internal linking.
+go build -ldflags=-tmpdir=tmp2 -o $devnull ./usesInternalCgo &
+
+# Third build: program uses only "runtime/cgo", so we would normally
+# expect internal linking, except that cflags contain suspicious entries
+# (in this case, a flag that does not appear on the allow list).
+env CGO_CFLAGS=-fmerge-all-constants
+env CGO_LDFLAGS=-fmerge-all-constants
+go build -ldflags=-tmpdir=tmp3 -o $devnull ./usesInternalCgo &
+env CGO_CFLAGS=
+env CGO_LDFLAGS=
+
+# Fourth build: explicit CGO, expect external linking.
+go build -ldflags=-tmpdir=tmp4 -o $devnull ./usesExplicitCgo &
+
+# Fifth build: explicit CGO, but we specifically asked for internal linking
+# via a flag, so using internal linking it is.
+[cgolinkext] go list ./usesInternalCgo
+[!cgolinkext] go build '-ldflags=-tmpdir=tmp5 -linkmode=internal' -o $devnull ./usesInternalCgo &
+
+# Sixth build: explicit CGO use in a non-main package.
+go build -o p.a ./nonMainPackageUsesExplicitCgo &
+
+wait
+
+# Check first build: no external linking expected
+! exists tmp1/go.o
+
+# Check second build: using only "runtime/cgo", expect internal linking.
+[!cgolinkext] ! exists tmp2/go.o
+[cgolinkext] exists tmp2/go.o
+
+# Check third build: has suspicious flag.
+exists tmp3/go.o
+
+# Fourth build: explicit CGO, expect external linking.
+exists tmp4/go.o
+
+# Fifth build: explicit CGO, -linkmode=internal.
+! exists tmp5/go.o
+
+# Sixth build: make sure that "go tool nm" doesn't get confused
+# by the presence of the "preferlinkext" sentinel.
+go tool nm p.a
+
+-- go.mod --
+
+module cgo.example
+
+go 1.20
+
+-- noUseOfCgo/main.go --
+
+package main
+
+func main() {
+ println("clean as a whistle")
+}
+
+-- usesInternalCgo/main.go --
+
+package main
+
+import (
+ "runtime/cgo"
+)
+
+func main() {
+ q := "hello"
+ h := cgo.NewHandle(q)
+ h.Delete()
+}
+
+-- usesExplicitCgo/main.go --
+
+package main
+
+/*
+int meaningOfLife() { return 42; }
+*/
+import "C"
+
+func main() {
+ println(C.meaningOfLife())
+}
+
+-- nonMainPackageUsesExplicitCgo/main.go --
+
+package p
+
+/*
+int meaningOfLife() { return 42; }
+*/
+import "C"
+
+func PrintIt() {
+ println(C.meaningOfLife())
+}
diff --git a/src/cmd/go/testdata/script/cgo_syso_issue29253.txt b/src/cmd/go/testdata/script/cgo_syso_issue29253.txt
new file mode 100644
index 0000000..18526c6
--- /dev/null
+++ b/src/cmd/go/testdata/script/cgo_syso_issue29253.txt
@@ -0,0 +1,31 @@
+env GO111MODULE=off
+[short] skip
+
+# This test tests that we can link in-package syso files that provides symbols
+# for cgo. See issue 29253.
+[!cgo] stop
+[!compiler:gc] stop
+cc -c -o pkg/o.syso ext.c
+go build main.go
+
+-- ext.c --
+// +build ignore
+
+int f() { return 42; }
+-- pkg/pkg.go --
+package pkg
+
+// extern int f(void);
+import "C"
+
+func init() {
+ if v := C.f(); v != 42 {
+ panic(v)
+ }
+}
+-- main.go --
+package main
+
+import _ "pkg"
+
+func main() {}
diff --git a/src/cmd/go/testdata/script/cgo_trimpath_macro.txt b/src/cmd/go/testdata/script/cgo_trimpath_macro.txt
new file mode 100644
index 0000000..b5cc116
--- /dev/null
+++ b/src/cmd/go/testdata/script/cgo_trimpath_macro.txt
@@ -0,0 +1,71 @@
+# This is a test that -trimpath trims the paths of every directory
+# of Cgo dependencies in the module, and trims file paths included
+# through the __FILE__ macro using --file-prefix-map.
+
+[!cgo] skip
+[short] skip 'links and runs binaries'
+
+# Test in main module.
+go run -trimpath -mod=vendor ./main
+stdout '(\\_\\_|/_)[\\/]m[\\/]c[\\/]bar.h'
+
+# Test in vendored module.
+go run -trimpath -mod=vendor v.com/main
+stdout '(\\_\\_|/_)[\\/]vendor[\\/]v.com[\\/]c[\\/]bar.h'
+
+# Test in GOPATH mode.
+env GO111MODULE=off
+go run -trimpath ./main
+stdout '(\\_\\_|/_)[\\/]GOPATH[\\/]src[\\/]c[\\/]bar.h'
+
+-- go.mod --
+module m
+
+require v.com v1.0.0
+-- go.sum --
+v.com v1.0.0 h1:xxx
+v.com v1.0.0/go.mod h1:xxx
+-- vendor/modules.txt --
+# v.com v1.0.0
+## explicit; go 1.20
+v.com/main
+-- vendor/v.com/main/main.go --
+package main
+
+// #cgo CFLAGS: -I../c
+// #include "stdio.h"
+// void printfile();
+import "C"
+
+func main() {
+ C.printfile()
+ C.fflush(C.stdout)
+}
+-- vendor/v.com/main/foo.c --
+#include "bar.h"
+-- vendor/v.com/c/bar.h --
+#include "stdio.h"
+
+void printfile() {
+ printf("%s\n", __FILE__);
+}
+-- main/main.go --
+package main
+
+// #cgo CFLAGS: -I../c
+// #include "stdio.h"
+// void printfile();
+import "C"
+
+func main() {
+ C.printfile()
+ C.fflush(C.stdout)
+}
+-- main/foo.c --
+#include "bar.h"
+-- c/bar.h --
+#include "stdio.h"
+
+void printfile() {
+ printf("%s\n", __FILE__);
+} \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/cgo_undef.txt b/src/cmd/go/testdata/script/cgo_undef.txt
new file mode 100644
index 0000000..30034fb
--- /dev/null
+++ b/src/cmd/go/testdata/script/cgo_undef.txt
@@ -0,0 +1,68 @@
+# Issue 52863.
+
+# We manually create a .syso and a .a file in package a,
+# such that the .syso file only works when linked against the .a file.
+# Package a has #cgo LDFLAGS to make this happen.
+#
+# Package c imports package a, and uses cgo itself.
+# The generation of the _cgo_import.go for package c will fail,
+# because it won't know that it has to link against a/libb.a
+# (because we don't gather the #cgo LDFLAGS from all transitively
+# imported packages).
+#
+# The _cgo_import.go file is only needed for internal linking.
+# When generating _cgo_import.go for package c fails, an ordinary
+# external link should still work. But an internal link is expected
+# to fail, because the failure to create _cgo_import.go should cause
+# the linker to report an inability to internally link.
+
+[short] skip
+[!cgo] skip
+[!exec:ar] skip
+
+cc -c -o a/b.syso b/b.c
+cc -c -o b/lib.o b/lib.c
+exec ar rc a/libb.a b/lib.o
+go build
+! go build -ldflags=-linkmode=internal
+stderr 'some packages could not be built to support internal linking.*m/c|requires external linking|does not support internal cgo'
+
+-- go.mod --
+module m
+
+-- a/a.go --
+package a
+
+// #cgo LDFLAGS: -L. -lb
+// extern int CFn(int);
+import "C"
+
+func GoFn(v int) int { return int(C.CFn(C.int(v))) }
+
+-- b/b.c --
+extern int LibFn(int);
+int CFn(int i) { return LibFn(i); }
+
+-- b/lib.c --
+int LibFn(int i) { return i; }
+
+-- c/c.go --
+package c
+
+// static int D(int i) { return i; }
+import "C"
+
+import "m/a"
+
+func Fn(i int) (int, int) {
+ return a.GoFn(i), int(C.D(C.int(i)))
+}
+
+-- main.go --
+package main
+
+import "m/c"
+
+func main() {
+ println(c.Fn(0))
+}
diff --git a/src/cmd/go/testdata/script/chdir.txt b/src/cmd/go/testdata/script/chdir.txt
new file mode 100644
index 0000000..a6feed6
--- /dev/null
+++ b/src/cmd/go/testdata/script/chdir.txt
@@ -0,0 +1,35 @@
+env OLD=$PWD
+
+# basic -C functionality
+cd $GOROOT/src/math
+go list -C ../strings
+stdout strings
+! go list -C ../nonexist
+stderr 'chdir.*nonexist'
+
+# check for -C in subcommands with custom flag parsing
+# cmd/go/chdir_test.go handles the normal ones more directly.
+
+# go doc
+go doc -C ../strings HasPrefix
+
+# go env
+go env -C $OLD/custom GOMOD
+stdout 'custom[\\/]go.mod'
+! go env -C ../nonexist
+stderr '^go: chdir ../nonexist: '
+
+# go test
+go test -C ../strings -n
+stderr 'strings\.test'
+
+# go vet
+go vet -C ../strings -n
+stderr strings_test
+
+# -C must be first on command line (as of Go 1.21)
+! go test -n -C ../strings
+stderr '^invalid value "../strings" for flag -C: -C flag must be first flag on command line$'
+
+-- custom/go.mod --
+module m
diff --git a/src/cmd/go/testdata/script/check_goexperiment.txt b/src/cmd/go/testdata/script/check_goexperiment.txt
new file mode 100644
index 0000000..3434cb9
--- /dev/null
+++ b/src/cmd/go/testdata/script/check_goexperiment.txt
@@ -0,0 +1,10 @@
+# Test that [GOEXPERIMENT:x] is accepted.
+# Here fieldtrack is picked arbitrarily.
+
+[GOEXPERIMENT:nofieldtrack] env
+
+[GOEXPERIMENT:fieldtrack] env
+
+#[GOEXPERIMENT:crashme] env
+
+
diff --git a/src/cmd/go/testdata/script/clean_binary.txt b/src/cmd/go/testdata/script/clean_binary.txt
new file mode 100644
index 0000000..7335f8a
--- /dev/null
+++ b/src/cmd/go/testdata/script/clean_binary.txt
@@ -0,0 +1,78 @@
+# Build something to create the executable, including several cases
+[short] skip
+
+# --------------------- clean executables -------------------------
+
+# case1: test file-named executable 'main'
+env GO111MODULE=on
+
+! exists main$GOEXE
+go build main.go
+exists -exec main$GOEXE
+go clean
+! exists main$GOEXE
+
+# case2: test module-named executable 'a.b.c'
+! exists a.b.c$GOEXE
+go build
+exists -exec a.b.c$GOEXE
+go clean
+! exists a.b.c$GOEXE
+
+# case3: directory-named executable 'src'
+env GO111MODULE=off
+
+! exists src$GOEXE
+go build
+exists -exec src$GOEXE
+go clean
+! exists src$GOEXE
+
+# --------------------- clean test files -------------------------
+
+# case1: test file-named test file
+env GO111MODULE=on
+
+! exists main.test$GOEXE
+go test -c main_test.go
+exists -exec main.test$GOEXE
+go clean
+! exists main.test$GOEXE
+
+# case2: test module-named test file
+! exists a.b.c.test$GOEXE
+go test -c
+exists -exec a.b.c.test$GOEXE
+go clean
+! exists a.b.c.test$GOEXE
+
+# case3: test directory-based test file
+env GO111MODULE=off
+
+! exists src.test$GOEXE
+go test -c
+exists -exec src.test$GOEXE
+go clean
+! exists src.test$GOEXE
+
+-- main.go --
+package main
+
+import "fmt"
+
+func main() {
+ fmt.Println("hello!")
+}
+
+-- main_test.go --
+package main
+
+import "testing"
+
+func TestSomething(t *testing.T) {
+}
+
+-- go.mod --
+module example.com/a.b.c/v2
+
+go 1.12 \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/clean_cache_n.txt b/src/cmd/go/testdata/script/clean_cache_n.txt
new file mode 100644
index 0000000..72f9abf
--- /dev/null
+++ b/src/cmd/go/testdata/script/clean_cache_n.txt
@@ -0,0 +1,28 @@
+# We're testing cache behavior, so start with a clean GOCACHE.
+env GOCACHE=$WORK/cache
+
+# Build something so that the cache gets populates
+go build main.go
+
+# Check that cache contains directories before running
+exists $GOCACHE/00
+
+# Run go clean -cache -n and ensure that directories weren't deleted
+go clean -cache -n
+exists $GOCACHE/00
+
+# Re-run go clean cache without the -n flag go ensure that directories were properly removed
+go clean -cache
+! exists $GOCACHE/00
+
+! go clean -cache .
+stderr 'go: clean -cache cannot be used with package arguments'
+
+-- main.go --
+package main
+
+import "fmt"
+
+func main() {
+ fmt.Println("hello!")
+}
diff --git a/src/cmd/go/testdata/script/clean_testcache.txt b/src/cmd/go/testdata/script/clean_testcache.txt
new file mode 100644
index 0000000..3f98602
--- /dev/null
+++ b/src/cmd/go/testdata/script/clean_testcache.txt
@@ -0,0 +1,28 @@
+env GO111MODULE=off
+[short] skip
+
+# go clean -testcache
+# should work (see golang.org/issue/29757).
+cd x
+go test x_test.go
+go clean -testcache
+go test x_test.go
+! stdout 'cached'
+! go clean -testcache ../x
+stderr 'go: clean -testcache cannot be used with package arguments'
+
+# golang.org/issue/29100: 'go clean -testcache' should succeed
+# if the cache directory doesn't exist at all.
+# It should not write a testexpire.txt file, since there are no
+# test results that need to be invalidated in the first place.
+env GOCACHE=$WORK/nonexistent
+go clean -testcache
+! exists $WORK/nonexistent
+
+-- x/x_test.go --
+package x_test
+import (
+ "testing"
+)
+func TestMain(t *testing.T) {
+}
diff --git a/src/cmd/go/testdata/script/cmd_import_error.txt b/src/cmd/go/testdata/script/cmd_import_error.txt
new file mode 100644
index 0000000..89e1dbb
--- /dev/null
+++ b/src/cmd/go/testdata/script/cmd_import_error.txt
@@ -0,0 +1,16 @@
+env GO111MODULE=on
+
+# Regression test for golang.org/issue/31031:
+# Importing or loading a non-existent package in cmd/ should print
+# a clear error in module mode.
+
+! go list cmd/unknown
+stderr '^package cmd/unknown is not in std \('$GOROOT'[/\\]src[/\\]cmd[/\\]unknown\)$'
+
+go list -f '{{range .DepsErrors}}{{.Err}}{{end}}' x.go
+stdout '^package cmd/unknown is not in std \('$GOROOT'[/\\]src[/\\]cmd[/\\]unknown\)$'
+
+-- x.go --
+package x
+
+import _ "cmd/unknown"
diff --git a/src/cmd/go/testdata/script/cover_asm.txt b/src/cmd/go/testdata/script/cover_asm.txt
new file mode 100644
index 0000000..c7b7114
--- /dev/null
+++ b/src/cmd/go/testdata/script/cover_asm.txt
@@ -0,0 +1,33 @@
+[short] skip
+[compiler:gccgo] skip # gccgo has no cover tool
+
+# Test cover for a package that has an assembly function.
+
+go test -outputdir=$WORK -coverprofile=cover.out coverasm
+go tool cover -func=$WORK/cover.out
+stdout '\tg\t*100.0%' # Check g is 100% covered.
+! stdout '\tf\t*[0-9]' # Check for no coverage on the assembly function
+
+-- go.mod --
+module coverasm
+
+go 1.16
+-- p.go --
+package p
+
+func f()
+
+func g() {
+ println("g")
+}
+-- p.s --
+// empty asm file,
+// so go test doesn't complain about declaration of f in p.go.
+-- p_test.go --
+package p
+
+import "testing"
+
+func Test(t *testing.T) {
+ g()
+}
diff --git a/src/cmd/go/testdata/script/cover_atomic_pkgall.txt b/src/cmd/go/testdata/script/cover_atomic_pkgall.txt
new file mode 100644
index 0000000..c3bc67d
--- /dev/null
+++ b/src/cmd/go/testdata/script/cover_atomic_pkgall.txt
@@ -0,0 +1,25 @@
+env GO111MODULE=off
+
+[short] skip
+
+go test -coverpkg=all -covermode=atomic x
+stdout ok[\s\S]+?coverage
+
+[!race] stop
+
+go test -coverpkg=all -race x
+stdout ok[\s\S]+?coverage
+
+-- x/x.go --
+package x
+
+import _ "sync/atomic"
+
+func F() {}
+
+-- x/x_test.go --
+package x
+
+import "testing"
+
+func TestF(t *testing.T) { F() }
diff --git a/src/cmd/go/testdata/script/cover_blank_func_decl.txt b/src/cmd/go/testdata/script/cover_blank_func_decl.txt
new file mode 100644
index 0000000..e7d5250
--- /dev/null
+++ b/src/cmd/go/testdata/script/cover_blank_func_decl.txt
@@ -0,0 +1,35 @@
+[short] skip
+go test -cover coverblank
+stdout 'coverage: 100.0% of statements'
+
+
+-- go.mod --
+module coverblank
+
+go 1.16
+-- a.go --
+package coverblank
+
+func _() {
+ println("unreachable")
+}
+
+type X int
+
+func (x X) Print() {
+ println(x)
+}
+
+func (x X) _() {
+ println("unreachable")
+}
+
+-- a_test.go --
+package coverblank
+
+import "testing"
+
+func TestX(t *testing.T) {
+ var x X
+ x.Print()
+}
diff --git a/src/cmd/go/testdata/script/cover_build_cmdline_pkgs.txt b/src/cmd/go/testdata/script/cover_build_cmdline_pkgs.txt
new file mode 100644
index 0000000..e14a078
--- /dev/null
+++ b/src/cmd/go/testdata/script/cover_build_cmdline_pkgs.txt
@@ -0,0 +1,73 @@
+
+# This test is intended to verify that when a user does "go run -cover ..."
+# or "go build -cover ...", packages named on the command line are
+# always instrumented (but not their dependencies). This rule applies
+# inside and outside the standard library.
+
+[short] skip
+[!GOEXPERIMENT:coverageredesign] skip
+
+# Compile an object.
+go tool compile -p tiny tiny/tiny.go tiny/tiny2.go
+
+# Build a stdlib command with coverage.
+go build -o $WORK/nm.exe -cover cmd/nm
+
+# Save off old GOCOVERDIR setting
+env SAVEGOCOVERDIR=$GOCOVERDIR
+
+# Collect a coverage profile from running 'cmd/nm' on the object.
+mkdir $WORK/covdata
+env GOCOVERDIR=$WORK/covdata
+exec $WORK/nm.exe tiny.o
+
+# Restore previous GOCOVERDIR setting
+env GOCOVERDIR=$SAVEGOCOVERDIR
+
+# Check to make sure we instrumented just the main package, not
+# any dependencies.
+go tool covdata pkglist -i=$WORK/covdata
+stdout cmd/nm
+! stdout cmd/internal/goobj pkglist.txt
+
+# ... now collect a coverage profile from a Go file
+# listed on the command line.
+go build -cover -o $WORK/another.exe testdata/another.go
+mkdir $WORK/covdata2
+env GOCOVERDIR=$WORK/covdata2
+exec $WORK/another.exe
+
+# Restore previous GOCOVERDIR setting
+env GOCOVERDIR=$SAVEGOCOVERDIR
+
+# Check to make sure we instrumented just the main package.
+go tool covdata pkglist -i=$WORK/covdata2
+stdout command-line-arguments
+! stdout fmt
+
+-- go.mod --
+
+module example.prog
+
+-- testdata/another.go --
+
+package main
+
+import "fmt"
+
+func main() {
+ fmt.Println("Hi dad")
+}
+
+-- tiny/tiny.go --
+
+package tiny
+
+var Tvar int
+
+-- tiny/tiny2.go --
+
+package tiny
+
+var Tvar2 bool
+
diff --git a/src/cmd/go/testdata/script/cover_build_pkg_select.txt b/src/cmd/go/testdata/script/cover_build_pkg_select.txt
new file mode 100644
index 0000000..447ca77
--- /dev/null
+++ b/src/cmd/go/testdata/script/cover_build_pkg_select.txt
@@ -0,0 +1,114 @@
+# This test checks more of the "go build -cover" functionality,
+# specifically which packages get selected when building.
+
+[short] skip
+
+# Skip if new coverage is not enabled.
+[!GOEXPERIMENT:coverageredesign] skip
+
+#-------------------------------------------
+
+# Build for coverage.
+go build -mod=mod -o $WORK/modex.exe -cover mod.example/main
+
+# Save off old GOCOVERDIR setting
+env SAVEGOCOVERDIR=$GOCOVERDIR
+
+# Execute.
+mkdir $WORK/covdata
+env GOCOVERDIR=$WORK/covdata
+exec $WORK/modex.exe
+
+# Restore previous GOCOVERDIR setting
+env GOCOVERDIR=$SAVEGOCOVERDIR
+
+# Examine the result.
+go tool covdata percent -i=$WORK/covdata
+stdout 'coverage: 100.0% of statements'
+
+# By default we want to see packages resident in the module covered,
+# but not dependencies.
+go tool covdata textfmt -i=$WORK/covdata -o=$WORK/covdata/out.txt
+grep 'mode: set' $WORK/covdata/out.txt
+grep 'mod.example/main/main.go:' $WORK/covdata/out.txt
+grep 'mod.example/sub/sub.go:' $WORK/covdata/out.txt
+! grep 'rsc.io' $WORK/covdata/out.txt
+
+rm $WORK/covdata
+rm $WORK/modex.exe
+
+#-------------------------------------------
+
+# Repeat the build but with -coverpkg=all
+
+go build -mod=mod -coverpkg=all -o $WORK/modex.exe -cover mod.example/main
+
+# Execute.
+mkdir $WORK/covdata
+env GOCOVERDIR=$WORK/covdata
+exec $WORK/modex.exe
+
+# Restore previous GOCOVERDIR setting
+env GOCOVERDIR=$SAVEGOCOVERDIR
+
+# Examine the result.
+go tool covdata percent -i=$WORK/covdata
+stdout 'coverage:.*[1-9][0-9.]+%'
+
+# The whole enchilada.
+go tool covdata textfmt -i=$WORK/covdata -o=$WORK/covdata/out.txt
+grep 'mode: set' $WORK/covdata/out.txt
+grep 'mod.example/main/main.go:' $WORK/covdata/out.txt
+grep 'mod.example/sub/sub.go:' $WORK/covdata/out.txt
+grep 'rsc.io' $WORK/covdata/out.txt
+grep 'bufio/bufio.go:' $WORK/covdata/out.txt
+
+# Use the covdata tool to select a specific set of module paths
+mkdir $WORK/covdata2
+go tool covdata merge -pkg=rsc.io/quote -i=$WORK/covdata -o=$WORK/covdata2
+
+# Examine the result.
+go tool covdata percent -i=$WORK/covdata2
+stdout 'coverage:.*[1-9][0-9.]+%'
+
+# Check for expected packages + check that we don't see things from stdlib.
+go tool covdata textfmt -i=$WORK/covdata2 -o=$WORK/covdata2/out.txt
+grep 'mode: set' $WORK/covdata2/out.txt
+! grep 'mod.example/main/main.go:' $WORK/covdata2/out.txt
+! grep 'mod.example/sub/sub.go:' $WORK/covdata2/out.txt
+grep 'rsc.io' $WORK/covdata2/out.txt
+! grep 'bufio/bufio.go:' $WORK/covdata2/out.txt
+
+#-------------------------------------------
+# end of test cmds, start of harness and related files.
+
+-- go.mod --
+module mod.example
+
+go 1.20
+
+require rsc.io/quote/v3 v3.0.0
+
+-- main/main.go --
+package main
+
+import (
+ "fmt"
+ "mod.example/sub"
+
+ "rsc.io/quote"
+)
+
+func main() {
+ fmt.Println(quote.Go(), sub.F())
+}
+
+-- sub/sub.go --
+
+package sub
+
+func F() int {
+ return 42
+}
+
+
diff --git a/src/cmd/go/testdata/script/cover_build_simple.txt b/src/cmd/go/testdata/script/cover_build_simple.txt
new file mode 100644
index 0000000..b61e631
--- /dev/null
+++ b/src/cmd/go/testdata/script/cover_build_simple.txt
@@ -0,0 +1,149 @@
+# This test checks basic "go build -cover" functionality.
+
+[short] skip
+
+# Hard-wire new coverage for this test.
+env GOEXPERIMENT=coverageredesign
+
+# Build for coverage.
+go build -gcflags=-m -o example.exe -cover example/main &
+[race] go build -o examplewithrace.exe -race -cover example/main &
+wait
+
+# First execute without GOCOVERDIR set...
+env GOCOVERDIR=
+exec ./example.exe normal
+stderr '^warning: GOCOVERDIR not set, no coverage data emitted'
+
+# ... then with GOCOVERDIR set.
+env GOCOVERDIR=data/normal
+exec ./example.exe normal
+! stderr '^warning: GOCOVERDIR not set, no coverage data emitted'
+go tool covdata percent -i=data/normal
+stdout 'coverage:.*[1-9][0-9.]+%'
+
+# Program makes a direct call to os.Exit(0).
+env GOCOVERDIR=data/goodexit
+exec ./example.exe goodexit
+! stderr '^warning: GOCOVERDIR not set, no coverage data emitted'
+go tool covdata percent -i=data/goodexit
+stdout 'coverage:.*[1-9][0-9.]+%'
+
+# Program makes a direct call to os.Exit(1).
+env GOCOVERDIR=data/badexit
+! exec ./example.exe badexit
+! stderr '^warning: GOCOVERDIR not set, no coverage data emitted'
+go tool covdata percent -i=data/badexit
+stdout 'coverage:.*[1-9][0-9.]+%'
+
+# Program invokes panic.
+env GOCOVERDIR=data/panic
+! exec ./example.exe panic
+! stderr '^warning: GOCOVERDIR not set, no coverage data emitted'
+go tool covdata percent -i=data/panic
+stdout 'coverage:.*[0-9.]+%'
+
+# Skip remainder if no race detector support.
+[!race] skip
+
+env GOCOVERDIR=data2/normal
+exec ./examplewithrace.exe normal
+! stderr '^warning: GOCOVERDIR not set, no coverage data emitted'
+go tool covdata percent -i=data2/normal
+stdout 'coverage:.*[1-9][0-9.]+%'
+
+# Program makes a direct call to os.Exit(0).
+env GOCOVERDIR=data2/goodexit
+exec ./examplewithrace.exe goodexit
+! stderr '^warning: GOCOVERDIR not set, no coverage data emitted'
+go tool covdata percent -i=data2/goodexit
+stdout 'coverage:.*[1-9][0-9.]+%'
+
+# Program makes a direct call to os.Exit(1).
+env GOCOVERDIR=data2/badexit
+! exec ./examplewithrace.exe badexit
+! stderr '^warning: GOCOVERDIR not set, no coverage data emitted'
+go tool covdata percent -i=data2/badexit
+stdout 'coverage:.*[1-9][0-9.]+%'
+
+# Program invokes panic.
+env GOCOVERDIR=data2/panic
+! exec ./examplewithrace.exe panic
+! stderr '^warning: GOCOVERDIR not set, no coverage data emitted'
+go tool covdata percent -i=data2/panic
+stdout 'coverage:.*[0-9.]+%'
+
+# end of test cmds, start of harness and related files.
+
+-- go.mod --
+module example
+
+go 1.18
+
+-- main/example.go --
+package main
+
+import "example/sub"
+
+func main() {
+ sub.S()
+}
+
+-- sub/sub.go --
+
+package sub
+
+import "os"
+
+func S() {
+ switch os.Args[1] {
+ case "normal":
+ println("hi")
+ case "goodexit":
+ os.Exit(0)
+ case "badexit":
+ os.Exit(1)
+ case "panic":
+ panic("something bad happened")
+ }
+}
+
+-- data/README.txt --
+
+Just a location where we can write coverage profiles.
+
+-- data/normal/f.txt --
+
+X
+
+-- data/goodexit/f.txt --
+
+X
+
+-- data/badexit/f.txt --
+
+X
+
+-- data/panic/f.txt --
+
+X
+
+-- data2/README.txt --
+
+Just a location where we can write coverage profiles.
+
+-- data2/normal/f.txt --
+
+X
+
+-- data2/goodexit/f.txt --
+
+X
+
+-- data2/badexit/f.txt --
+
+X
+
+-- data2/panic/f.txt --
+
+X
diff --git a/src/cmd/go/testdata/script/cover_cgo.txt b/src/cmd/go/testdata/script/cover_cgo.txt
new file mode 100644
index 0000000..85754b5
--- /dev/null
+++ b/src/cmd/go/testdata/script/cover_cgo.txt
@@ -0,0 +1,42 @@
+[short] skip
+[!cgo] skip
+[compiler:gccgo] skip # gccgo has no cover tool
+
+# Test coverage on cgo code.
+
+go test -short -cover cgocover
+stdout 'coverage:.*[1-9][0-9.]+%'
+! stderr '[^0-9]0\.0%'
+
+-- go.mod --
+module cgocover
+
+go 1.16
+-- p.go --
+package p
+
+/*
+void
+f(void)
+{
+}
+*/
+import "C"
+
+var b bool
+
+func F() {
+ if b {
+ for {
+ }
+ }
+ C.f()
+}
+-- p_test.go --
+package p
+
+import "testing"
+
+func TestF(t *testing.T) {
+ F()
+}
diff --git a/src/cmd/go/testdata/script/cover_cgo_extra_file.txt b/src/cmd/go/testdata/script/cover_cgo_extra_file.txt
new file mode 100644
index 0000000..afc2178
--- /dev/null
+++ b/src/cmd/go/testdata/script/cover_cgo_extra_file.txt
@@ -0,0 +1,48 @@
+[short] skip
+[!cgo] skip
+[compiler:gccgo] skip # gccgo has no cover tool
+
+# Test coverage on cgo code. This test case includes an
+# extra empty non-cgo file in the package being checked.
+
+go test -short -cover cgocover4
+stdout 'coverage:.*[1-9][0-9.]+%'
+! stderr '[^0-9]0\.0%'
+
+-- go.mod --
+module cgocover4
+
+go 1.16
+-- notcgo.go --
+package p
+-- p.go --
+package p
+
+/*
+void
+f(void)
+{
+}
+*/
+import "C"
+
+var b bool
+
+func F() {
+ if b {
+ for {
+ }
+ }
+ C.f()
+}
+-- x_test.go --
+package p_test
+
+import (
+ . "cgocover4"
+ "testing"
+)
+
+func TestF(t *testing.T) {
+ F()
+}
diff --git a/src/cmd/go/testdata/script/cover_cgo_extra_test.txt b/src/cmd/go/testdata/script/cover_cgo_extra_test.txt
new file mode 100644
index 0000000..ad09bab
--- /dev/null
+++ b/src/cmd/go/testdata/script/cover_cgo_extra_test.txt
@@ -0,0 +1,49 @@
+[short] skip
+[!cgo] skip
+[compiler:gccgo] skip # gccgo has no cover tool
+
+# Test coverage on cgo code. This test case has an external
+# test that tests the code and an in-package test file with
+# no test cases.
+
+go test -short -cover cgocover3
+stdout 'coverage:.*[1-9][0-9.]+%'
+! stderr '[^0-9]0\.0%'
+
+-- go.mod --
+module cgocover3
+
+go 1.16
+-- p.go --
+package p
+
+/*
+void
+f(void)
+{
+}
+*/
+import "C"
+
+var b bool
+
+func F() {
+ if b {
+ for {
+ }
+ }
+ C.f()
+}
+-- p_test.go --
+package p
+-- x_test.go --
+package p_test
+
+import (
+ . "cgocover3"
+ "testing"
+)
+
+func TestF(t *testing.T) {
+ F()
+}
diff --git a/src/cmd/go/testdata/script/cover_cgo_xtest.txt b/src/cmd/go/testdata/script/cover_cgo_xtest.txt
new file mode 100644
index 0000000..0900a48
--- /dev/null
+++ b/src/cmd/go/testdata/script/cover_cgo_xtest.txt
@@ -0,0 +1,45 @@
+[short] skip
+[!cgo] skip
+[compiler:gccgo] skip # gccgo has no cover tool
+
+# Test cgo coverage with an external test.
+
+go test -short -cover cgocover2
+stdout 'coverage:.*[1-9][0-9.]+%'
+! stderr '[^0-9]0\.0%'
+
+-- go.mod --
+module cgocover2
+
+go 1.16
+-- p.go --
+package p
+
+/*
+void
+f(void)
+{
+}
+*/
+import "C"
+
+var b bool
+
+func F() {
+ if b {
+ for {
+ }
+ }
+ C.f()
+}
+-- x_test.go --
+package p_test
+
+import (
+ . "cgocover2"
+ "testing"
+)
+
+func TestF(t *testing.T) {
+ F()
+}
diff --git a/src/cmd/go/testdata/script/cover_coverpkg_partial.txt b/src/cmd/go/testdata/script/cover_coverpkg_partial.txt
new file mode 100644
index 0000000..5240241
--- /dev/null
+++ b/src/cmd/go/testdata/script/cover_coverpkg_partial.txt
@@ -0,0 +1,141 @@
+
+# Testcase related to #58770 and #24570. This is intended to ensure
+# that coverage collection works in situations where we're testing a
+# collection of packages and supplying a -coverpkg pattern that
+# matches some but not all of the collection. In addition, some of the
+# packages have Go code but no tests, and other packages have tests
+# but no Go code. Package breakdown:
+#
+# Package Code? Tests? Stmts Imports
+# a yes yes 2 f
+# b yes yes 1 a, d
+# c yes yes 3 ---
+# d yes no 1 ---
+# e no yes 0 a, b
+# f yes no 3 ---
+#
+
+[short] skip
+[!GOEXPERIMENT:coverageredesign] skip
+
+# Test all packages with -coverpkg=./...
+go test -coverprofile=cov.p -coverpkg=./... ./...
+stdout '^ok\s+M/a\s+\S+\s+coverage: 50.0% of statements in ./...'
+stdout '^ok\s+M/b\s+\S+\s+coverage: 60.0% of statements in ./...'
+stdout '^ok\s+M/c\s+\S+\s+coverage: 30.0% of statements in ./...'
+stdout '^\s*M/d\s+coverage: 0.0% of statements'
+stdout '^\s*M/f\s+coverage: 0.0% of statements'
+
+# Test just the test-only package ./e but with -coverpkg=./...
+# Total number of statements should be 7 (e.g. a/b/d/f but not c)
+# and covered percent should be 6/7 (we hit everything in the
+# coverpkg pattern except the func in "d").
+go test -coverprofile=bar.p -coverpkg=./... ./e
+stdout '^ok\s+M/e\s+\S+\s+coverage: 85.7% of statements in ./...'
+
+# Test b and f with -coverpkg set to a/d/f. Total of 6 statements
+# in a/d/f, again we hit everything except DFunc.
+go test -coverprofile=baz.p -coverpkg=./a,./d,./f ./b ./f
+stdout '^ok\s+M/b\s+\S+\s+coverage: 83.3% of statements in ./a, ./d, ./f'
+stdout '^\s*M/f\s+coverage: 0.0% of statements'
+
+-- a/a.go --
+package a
+
+import "M/f"
+
+var G int
+
+func AFunc() int {
+ G = 1
+ return f.Id()
+}
+-- a/a_test.go --
+package a
+
+import "testing"
+
+func TestA(t *testing.T) {
+ if AFunc() != 42 {
+ t.Fatalf("bad!")
+ }
+}
+-- b/b.go --
+package b
+
+import (
+ "M/a"
+ "M/d"
+)
+
+func BFunc() int {
+ return -d.FortyTwo + a.AFunc()
+}
+-- b/b_test.go --
+package b
+
+import "testing"
+
+func TestB(t *testing.T) {
+ if BFunc() == 1010101 {
+ t.Fatalf("bad!")
+ }
+}
+-- c/c.go --
+package c
+
+var G int
+
+func CFunc(x, y int) int {
+ G += x
+ G -= y
+ return x + y
+}
+-- c/c_test.go --
+package c
+
+import "testing"
+
+func TestC(t *testing.T) {
+ if CFunc(10, 10) == 1010101 {
+ t.Fatalf("bad!")
+ }
+}
+-- d/d.go --
+package d
+
+const FortyTwo = 42
+
+func DFunc() int {
+ return FortyTwo
+}
+
+-- e/e_test.go --
+package e
+
+import (
+ "M/a"
+ "M/b"
+ "testing"
+)
+
+func TestBlah(t *testing.T) {
+ if b.BFunc() == 1010101 {
+ t.Fatalf("bad")
+ }
+ a.AFunc()
+}
+-- f/f.go --
+package f
+
+var F int
+
+func Id() int {
+ F += 9
+ F *= 2
+ return 42
+}
+-- go.mod --
+module M
+
+go 1.21
diff --git a/src/cmd/go/testdata/script/cover_coverpkg_with_init.txt b/src/cmd/go/testdata/script/cover_coverpkg_with_init.txt
new file mode 100644
index 0000000..7a89102
--- /dev/null
+++ b/src/cmd/go/testdata/script/cover_coverpkg_with_init.txt
@@ -0,0 +1,130 @@
+
+# Testcase inspired by issue #58770, intended to verify that we're
+# doing the right thing when running "go test -coverpkg=./... ./..."
+# on a collection of packages where some have init functions and some
+# do not, some have tests and some do not.
+
+[short] skip
+[!GOEXPERIMENT:coverageredesign] skip
+
+# Verify correct statements percentages. We have a total of 10
+# statements in the packages matched by "./..."; package "a" (for
+# example) has two statements so we expect 20.0% stmts covered. Go
+# 1.19 would print 50% here (due to force importing of all ./...
+# packages); prior to the fix for #58770 Go 1.20 would show 100%
+# coverage. For packages "x" and "f" (which have no tests), check for
+# 0% stmts covered (as opposed to "no test files").
+
+go test -count=1 -coverprofile=cov.dat -coverpkg=./... ./...
+stdout '^\s*\?\s+M/n\s+\[no test files\]'
+stdout '^\s*M/x\s+coverage: 0.0% of statements'
+stdout '^\s*M/f\s+coverage: 0.0% of statements'
+stdout '^ok\s+M/a\s+\S+\s+coverage: 30.0% of statements in ./...'
+stdout '^ok\s+M/b\s+\S+\s+coverage: 20.0% of statements in ./...'
+stdout '^ok\s+M/main\s+\S+\s+coverage: 80.0% of statements in ./...'
+
+# Check for selected elements in the collected coverprofile as well.
+
+go tool cover -func=cov.dat
+stdout '^M/x/x.go:3:\s+XFunc\s+0.0%'
+stdout '^M/b/b.go:7:\s+BFunc\s+100.0%'
+stdout '^total:\s+\(statements\)\s+80.0%'
+
+-- go.mod --
+module M
+
+go 1.21
+-- a/a.go --
+package a
+
+import "M/f"
+
+func init() {
+ println("package 'a' init: launch the missiles!")
+}
+
+func AFunc() int {
+ return f.Id()
+}
+-- a/a_test.go --
+package a
+
+import "testing"
+
+func TestA(t *testing.T) {
+ if AFunc() != 42 {
+ t.Fatalf("bad!")
+ }
+}
+-- b/b.go --
+package b
+
+func init() {
+ println("package 'b' init: release the kraken")
+}
+
+func BFunc() int {
+ return -42
+}
+-- b/b_test.go --
+package b
+
+import "testing"
+
+func TestB(t *testing.T) {
+ if BFunc() != -42 {
+ t.Fatalf("bad!")
+ }
+}
+-- f/f.go --
+package f
+
+func Id() int {
+ return 42
+}
+-- main/main.go --
+package main
+
+import (
+ "M/a"
+ "M/b"
+)
+
+func MFunc() string {
+ return "42"
+}
+
+func M2Func() int {
+ return a.AFunc() + b.BFunc()
+}
+
+func init() {
+ println("package 'main' init")
+}
+
+func main() {
+ println(a.AFunc() + b.BFunc())
+}
+-- main/main_test.go --
+package main
+
+import "testing"
+
+func TestMain(t *testing.T) {
+ if MFunc() != "42" {
+ t.Fatalf("bad!")
+ }
+ if M2Func() != 0 {
+ t.Fatalf("also bad!")
+ }
+}
+-- n/n.go --
+package n
+
+type N int
+-- x/x.go --
+package x
+
+func XFunc() int {
+ return 2 * 2
+}
diff --git a/src/cmd/go/testdata/script/cover_coverprofile_multipkg.txt b/src/cmd/go/testdata/script/cover_coverprofile_multipkg.txt
new file mode 100644
index 0000000..543626f
--- /dev/null
+++ b/src/cmd/go/testdata/script/cover_coverprofile_multipkg.txt
@@ -0,0 +1,193 @@
+
+# Testcase for #63356. In this bug we're doing a "go test -coverprofile"
+# run for a collection of packages, mostly independent (hence tests can
+# be done in parallel) and in the original bug, temp coverage profile
+# files were not being properly qualified and were colliding, resulting
+# in a corrupted final profile. Actual content of the packages doesn't
+# especially matter as long as we have a mix of packages with tests and
+# multiple packages without tests.
+
+[short] skip
+
+# Kick off test.
+go test -p=10 -vet=off -count=1 -coverprofile=cov.p ./...
+
+# Make sure resulting profile is digestible.
+go tool cover -func=cov.p
+
+# No extraneous extra files please.
+! exists _cover_.out
+
+-- a/a.go --
+package a
+
+func init() {
+ println("package 'a' init: launch the missiles!")
+}
+
+func AFunc() int {
+ return 42
+}
+-- a/a_test.go --
+package a
+
+import "testing"
+
+func TestA(t *testing.T) {
+ if AFunc() != 42 {
+ t.Fatalf("bad!")
+ }
+}
+-- aa/aa.go --
+package aa
+
+import "M/it"
+
+func AA(y int) int {
+ c := it.Conc{}
+ x := it.Callee(&c)
+ println(x, y)
+ return 0
+}
+-- aa/aa_test.go --
+package aa
+
+import "testing"
+
+func TestMumble(t *testing.T) {
+ AA(3)
+}
+-- b/b.go --
+package b
+
+func init() {
+ println("package 'b' init: release the kraken")
+}
+
+func BFunc() int {
+ return -42
+}
+-- b/b_test.go --
+package b
+
+import "testing"
+
+func TestB(t *testing.T) {
+ if BFunc() != -42 {
+ t.Fatalf("bad!")
+ }
+}
+-- deadstuff/deadstuff.go --
+package deadstuff
+
+func downStreamOfPanic(x int) {
+ panic("bad")
+ if x < 10 {
+ println("foo")
+ }
+}
+-- deadstuff/deadstuff_test.go --
+package deadstuff
+
+import "testing"
+
+func TestMumble(t *testing.T) {
+ defer func() {
+ if x := recover(); x != nil {
+ println("recovered")
+ }
+ }()
+ downStreamOfPanic(10)
+}
+-- go.mod --
+module M
+
+go 1.21
+-- it/it.go --
+package it
+
+type Ctr interface {
+ Count() int
+}
+
+type Conc struct {
+ X int
+}
+
+func (c *Conc) Count() int {
+ return c.X
+}
+
+func DoCall(c *Conc) {
+ c2 := Callee(c)
+ println(c2.Count())
+}
+
+func Callee(ii Ctr) Ctr {
+ q := ii.Count()
+ return &Conc{X: q}
+}
+-- main/main.go --
+package main
+
+import (
+ "M/a"
+ "M/b"
+)
+
+func MFunc() string {
+ return "42"
+}
+
+func M2Func() int {
+ return a.AFunc() + b.BFunc()
+}
+
+func init() {
+ println("package 'main' init")
+}
+
+func main() {
+ println(a.AFunc() + b.BFunc())
+}
+-- main/main_test.go --
+package main
+
+import "testing"
+
+func TestMain(t *testing.T) {
+ if MFunc() != "42" {
+ t.Fatalf("bad!")
+ }
+ if M2Func() != 0 {
+ t.Fatalf("also bad!")
+ }
+}
+-- n/n.go --
+package n
+
+type N int
+-- onlytest/mumble_test.go --
+package onlytest
+
+import "testing"
+
+func TestFoo(t *testing.T) {
+ t.Logf("Whee\n")
+}
+-- x/x.go --
+package x
+
+func XFunc() int {
+ return 2 * 2
+}
+-- xinternal/i.go --
+package i
+
+func I() int { return 32 }
+-- xinternal/q/q.go --
+package q
+
+func Q() int {
+ return 42
+}
diff --git a/src/cmd/go/testdata/script/cover_dash_c.txt b/src/cmd/go/testdata/script/cover_dash_c.txt
new file mode 100644
index 0000000..f28c69e
--- /dev/null
+++ b/src/cmd/go/testdata/script/cover_dash_c.txt
@@ -0,0 +1,31 @@
+[short] skip
+[compiler:gccgo] skip
+
+# Test for issue 24588
+
+go test -c -o $WORK/coverdep -coverprofile=$WORK/no/such/dir/cover.out coverdep
+exists -exec $WORK/coverdep
+
+-- go.mod --
+module coverdep
+
+go 1.16
+-- p.go --
+package p
+
+import _ "coverdep/p1"
+
+func F() {
+}
+-- p1/p1.go --
+package p1
+
+import _ "errors"
+-- p_test.go --
+package p
+
+import "testing"
+
+func Test(t *testing.T) {
+ F()
+}
diff --git a/src/cmd/go/testdata/script/cover_dep_loop.txt b/src/cmd/go/testdata/script/cover_dep_loop.txt
new file mode 100644
index 0000000..46748e1
--- /dev/null
+++ b/src/cmd/go/testdata/script/cover_dep_loop.txt
@@ -0,0 +1,36 @@
+[short] skip
+[compiler:gccgo] skip
+
+# coverdep2/p1's xtest imports coverdep2/p2 which imports coverdep2/p1.
+# Make sure that coverage on coverdep2/p2 recompiles coverdep2/p2.
+
+go test -short -cover coverdep2/p1
+stdout 'coverage: 100.0% of statements' # expect 100.0% coverage
+
+-- go.mod --
+module coverdep2
+
+go 1.16
+-- p1/p.go --
+package p1
+
+func F() int { return 1 }
+-- p1/p_test.go --
+package p1_test
+
+import (
+ "coverdep2/p2"
+ "testing"
+)
+
+func Test(t *testing.T) {
+ p2.F()
+}
+-- p2/p2.go --
+package p2
+
+import "coverdep2/p1"
+
+func F() {
+ p1.F()
+}
diff --git a/src/cmd/go/testdata/script/cover_dot_import.txt b/src/cmd/go/testdata/script/cover_dot_import.txt
new file mode 100644
index 0000000..a336b1c
--- /dev/null
+++ b/src/cmd/go/testdata/script/cover_dot_import.txt
@@ -0,0 +1,29 @@
+[short] skip
+[compiler:gccgo] skip # gccgo has no cover tool
+
+go test -coverpkg=coverdot/a,coverdot/b coverdot/b
+! stderr '[^0-9]0\.0%'
+! stdout '[^0-9]0\.0%'
+
+-- go.mod --
+module coverdot
+
+go 1.16
+-- a/a.go --
+package a
+
+func F() {}
+-- b/b.go --
+package b
+
+import . "coverdot/a"
+
+func G() { F() }
+-- b/b_test.go --
+package b
+
+import "testing"
+
+func TestG(t *testing.T) {
+ G()
+}
diff --git a/src/cmd/go/testdata/script/cover_error.txt b/src/cmd/go/testdata/script/cover_error.txt
new file mode 100644
index 0000000..fa4b58b
--- /dev/null
+++ b/src/cmd/go/testdata/script/cover_error.txt
@@ -0,0 +1,45 @@
+[short] skip
+[compiler:gccgo] skip
+
+# Test line numbers in cover errors.
+
+# Get errors from a go test into stderr.txt
+! go test coverbad
+stderr 'p\.go:4:2' # look for error at coverbad/p.go:4
+[cgo] stderr 'p1\.go:6:2' # look for error at coverbad/p.go:6
+! stderr $WORK # make sure temporary directory isn't in error
+
+cp stderr $WORK/stderr.txt
+
+# Get errors from coverage into stderr2.txt
+! go test -cover coverbad
+cp stderr $WORK/stderr2.txt
+
+wait # for go run above
+
+cmp $WORK/stderr.txt $WORK/stderr2.txt
+
+-- go.mod --
+module coverbad
+
+go 1.16
+-- p.go --
+package p
+
+func f() {
+ g()
+}
+-- p1.go --
+package p
+
+import "C"
+
+func h() {
+ j()
+}
+-- p_test.go --
+package p
+
+import "testing"
+
+func Test(t *testing.T) {}
diff --git a/src/cmd/go/testdata/script/cover_import_main_loop.txt b/src/cmd/go/testdata/script/cover_import_main_loop.txt
new file mode 100644
index 0000000..36a09c2
--- /dev/null
+++ b/src/cmd/go/testdata/script/cover_import_main_loop.txt
@@ -0,0 +1,26 @@
+[compiler:gccgo] skip # gccgo has no cover tool
+
+! go test -n importmain/test
+stderr 'not an importable package' # check that import main was detected
+! go test -n -cover importmain/test
+stderr 'not an importable package' # check that import main was detected
+
+-- go.mod --
+module importmain
+
+go 1.16
+-- ismain/main.go --
+package main
+
+import _ "importmain/test"
+
+func main() {}
+-- test/test.go --
+package test
+-- test/test_test.go --
+package test_test
+
+import "testing"
+import _ "importmain/ismain"
+
+func TestCase(t *testing.T) {}
diff --git a/src/cmd/go/testdata/script/cover_list.txt b/src/cmd/go/testdata/script/cover_list.txt
new file mode 100644
index 0000000..6b8aaf4
--- /dev/null
+++ b/src/cmd/go/testdata/script/cover_list.txt
@@ -0,0 +1,65 @@
+
+# This test is intended to verify that "go list" accepts coverage related
+# build arguments (such as -cover, -covermode). See issue #57785.
+
+[short] skip
+[!GOEXPERIMENT:coverageredesign] skip
+
+env GOBIN=$WORK/bin
+
+# Install a target and then do an ordinary staleness check on it.
+go install m/example
+! stale m/example
+
+# Run a second staleness check with "-cover" as a build flag. The
+# installed target should indeed be stale, since we didn't build it
+# with -cover.
+stale -cover m/example
+
+# Collect build ID from for m/example built with -cover.
+go list -cover -export -f '{{.BuildID}}' m/example
+cp stdout $WORK/listbuildid.txt
+
+# Now build the m/example binary with coverage.
+go build -cover -o $WORK/m.exe m/example
+
+# Ask for the binary build ID by running "go tool buildid".
+go tool buildid $WORK/m.exe
+cp stdout $WORK/rawtoolbuildid.txt
+
+# Make sure that the two build IDs agree with respect to the
+# m/example package. Build IDs from binaries are of the form X/Y/Z/W
+# where Y/Z is the package build ID; running the program below will
+# pick out the parts of the ID that we want.
+env GOCOVERDIR=$WORK
+exec $WORK/m.exe $WORK/rawtoolbuildid.txt
+cp stdout $WORK/toolbuildid.txt
+
+# Build IDs should match here.
+cmp $WORK/toolbuildid.txt $WORK/listbuildid.txt
+
+-- go.mod --
+module m
+
+go 1.20
+-- example/main.go --
+package main
+
+import (
+ "fmt"
+ "os"
+ "strings"
+)
+
+func main() {
+ println(os.Args[1])
+ content, err := os.ReadFile(os.Args[1])
+ if err != nil {
+ os.Exit(1)
+ }
+ fields := strings.Split(strings.TrimSpace(string(content)), "/")
+ if len(fields) != 4 {
+ os.Exit(2)
+ }
+ fmt.Println(fields[1] + "/" + fields[2])
+}
diff --git a/src/cmd/go/testdata/script/cover_main_import_path.txt b/src/cmd/go/testdata/script/cover_main_import_path.txt
new file mode 100644
index 0000000..e8696e2
--- /dev/null
+++ b/src/cmd/go/testdata/script/cover_main_import_path.txt
@@ -0,0 +1,55 @@
+
+# This test is intended to verify that coverage reporting is consistent
+# between "go test -cover" and "go build -cover" with respect to how
+# the "main" package is handled. See issue 57169 for details.
+
+[short] skip
+[!GOEXPERIMENT:coverageredesign] skip
+
+# Build this program with -cover and run to collect a profile.
+
+go build -cover -o $WORK/prog.exe .
+
+# Save off old GOCOVERDIR setting
+env SAVEGOCOVERDIR=$GOCOVERDIR
+
+mkdir $WORK/covdata
+env GOCOVERDIR=$WORK/covdata
+exec $WORK/prog.exe
+
+# Restore previous GOCOVERDIR setting
+env GOCOVERDIR=$SAVEGOCOVERDIR
+
+# Report percent lines covered.
+go tool covdata percent -i=$WORK/covdata
+stdout '\s*mainwithtest\s+coverage:'
+! stdout 'main\s+coverage:'
+
+# Go test -cover should behave the same way.
+go test -cover .
+stdout 'ok\s+mainwithtest\s+\S+\s+coverage:'
+! stdout 'ok\s+main\s+.*'
+
+
+-- go.mod --
+module mainwithtest
+
+go 1.20
+-- mymain.go --
+package main
+
+func main() {
+ println("hi mom")
+}
+
+func Mainer() int {
+ return 42
+}
+-- main_test.go --
+package main
+
+import "testing"
+
+func TestCoverage(t *testing.T) {
+ println(Mainer())
+}
diff --git a/src/cmd/go/testdata/script/cover_mod_empty.txt b/src/cmd/go/testdata/script/cover_mod_empty.txt
new file mode 100644
index 0000000..3c45243
--- /dev/null
+++ b/src/cmd/go/testdata/script/cover_mod_empty.txt
@@ -0,0 +1,9 @@
+go tool cover -func=cover.out
+stdout total.*statements.*0.0%
+
+go mod init golang.org/issue/33855
+
+go tool cover -func=cover.out
+stdout total.*statements.*0.0%
+
+-- cover.out --
diff --git a/src/cmd/go/testdata/script/cover_modes.txt b/src/cmd/go/testdata/script/cover_modes.txt
new file mode 100644
index 0000000..a27296e
--- /dev/null
+++ b/src/cmd/go/testdata/script/cover_modes.txt
@@ -0,0 +1,25 @@
+env GO111MODULE=off
+
+# Coverage analysis should use 'set' mode by default,
+# and should merge coverage profiles correctly.
+
+[short] skip
+[compiler:gccgo] skip # gccgo has no cover tool
+
+go test -short -cover encoding/binary errors -coverprofile=$WORK/cover.out
+! stderr '[^0-9]0\.0%'
+! stdout '[^0-9]0\.0%'
+
+grep -count=1 '^mode: set$' $WORK/cover.out
+grep 'errors\.go' $WORK/cover.out
+grep 'binary\.go' $WORK/cover.out
+
+[!race] stop
+
+go test -short -race -cover encoding/binary errors -coverprofile=$WORK/cover.out
+! stderr '[^0-9]0\.0%'
+! stdout '[^0-9]0\.0%'
+
+grep -count=1 '^mode: atomic$' $WORK/cover.out
+grep 'errors\.go' $WORK/cover.out
+grep 'binary\.go' $WORK/cover.out
diff --git a/src/cmd/go/testdata/script/cover_pattern.txt b/src/cmd/go/testdata/script/cover_pattern.txt
new file mode 100644
index 0000000..6c79c10
--- /dev/null
+++ b/src/cmd/go/testdata/script/cover_pattern.txt
@@ -0,0 +1,41 @@
+[compiler:gccgo] skip
+
+# If coverpkg=m/sleepy... expands by package loading
+# (as opposed to pattern matching on deps)
+# then it will try to load sleepybad, which does not compile,
+# and the test command will fail.
+! go list m/sleepy...
+go test -c -n -coverprofile=$TMPDIR/cover.out -coverpkg=m/sleepy... -run=^$ m/sleepy1
+
+-- go.mod --
+module m
+
+go 1.16
+-- sleepy1/p_test.go --
+package p
+
+import (
+ "testing"
+ "time"
+)
+
+func Test1(t *testing.T) {
+ time.Sleep(200 * time.Millisecond)
+}
+-- sleepy2/p_test.go --
+package p
+
+import (
+ "testing"
+ "time"
+)
+
+func Test1(t *testing.T) {
+ time.Sleep(200 * time.Millisecond)
+}
+-- sleepybad/p.go --
+package p
+
+import ^
+
+var _ = io.DoesNotExist
diff --git a/src/cmd/go/testdata/script/cover_pkgall_imports.txt b/src/cmd/go/testdata/script/cover_pkgall_imports.txt
new file mode 100644
index 0000000..4e51726
--- /dev/null
+++ b/src/cmd/go/testdata/script/cover_pkgall_imports.txt
@@ -0,0 +1,48 @@
+# This test checks that -coverpkg=all can be used
+# when the package pattern includes packages
+# which only have tests.
+# Verifies golang.org/issue/27333, golang.org/issue/43242.
+
+[short] skip
+cd $GOPATH/src/example.com/cov
+
+env GO111MODULE=on
+go test -coverpkg=all ./...
+
+env GO111MODULE=off
+go test -coverpkg=all ./...
+
+-- $GOPATH/src/example.com/cov/go.mod --
+module example.com/cov
+
+-- $GOPATH/src/example.com/cov/notest/notest.go --
+package notest
+
+func Foo() {}
+
+-- $GOPATH/src/example.com/cov/onlytest/onlytest_test.go --
+package onlytest_test
+
+import (
+ "testing"
+
+ "example.com/cov/notest"
+)
+
+func TestFoo(t *testing.T) {
+ notest.Foo()
+}
+
+-- $GOPATH/src/example.com/cov/withtest/withtest.go --
+package withtest
+
+func Bar() {}
+
+-- $GOPATH/src/example.com/cov/withtest/withtest_test.go --
+package withtest
+
+import "testing"
+
+func TestBar(t *testing.T) {
+ Bar()
+}
diff --git a/src/cmd/go/testdata/script/cover_pkgall_multiple_mains.txt b/src/cmd/go/testdata/script/cover_pkgall_multiple_mains.txt
new file mode 100644
index 0000000..f21cd8b
--- /dev/null
+++ b/src/cmd/go/testdata/script/cover_pkgall_multiple_mains.txt
@@ -0,0 +1,46 @@
+# This test checks that multiple main packages can be tested
+# with -coverpkg=all without duplicate symbol errors.
+# Verifies golang.org/issue/30374, golang.org/issue/34114.
+
+[short] skip
+cd $GOPATH/src/example.com/cov
+
+env GO111MODULE=on
+go test -coverpkg=all ./...
+
+env GO111MODULE=off
+go test -coverpkg=all ./...
+
+-- $GOPATH/src/example.com/cov/go.mod --
+module example.com/cov
+
+-- $GOPATH/src/example.com/cov/mainonly/mainonly.go --
+package main
+
+func main() {}
+
+-- $GOPATH/src/example.com/cov/mainwithtest/mainwithtest.go --
+package main
+
+func main() {}
+
+func Foo() {}
+
+-- $GOPATH/src/example.com/cov/mainwithtest/mainwithtest_test.go --
+package main
+
+import "testing"
+
+func TestFoo(t *testing.T) {
+ Foo()
+}
+
+-- $GOPATH/src/example.com/cov/xtest/x.go --
+package x
+
+-- $GOPATH/src/example.com/cov/xtest/x_test.go --
+package x_test
+
+import "testing"
+
+func TestX(t *testing.T) {}
diff --git a/src/cmd/go/testdata/script/cover_pkgall_runtime.txt b/src/cmd/go/testdata/script/cover_pkgall_runtime.txt
new file mode 100644
index 0000000..9927c30
--- /dev/null
+++ b/src/cmd/go/testdata/script/cover_pkgall_runtime.txt
@@ -0,0 +1,23 @@
+env GO111MODULE=off
+
+# Issue 23882
+
+[short] skip
+
+go test -coverpkg=all x
+stdout ok[\s\S]+?coverage
+
+[!race] stop
+
+go test -coverpkg=all -race x
+stdout ok[\s\S]+?coverage
+
+-- x/x.go --
+package x
+import _ "runtime"
+func F() {}
+
+-- x/x_test.go --
+package x
+import "testing"
+func TestF(t *testing.T) { F() }
diff --git a/src/cmd/go/testdata/script/cover_runs.txt b/src/cmd/go/testdata/script/cover_runs.txt
new file mode 100644
index 0000000..6df6096
--- /dev/null
+++ b/src/cmd/go/testdata/script/cover_runs.txt
@@ -0,0 +1,13 @@
+[compiler:gccgo] skip 'gccgo has no cover tool'
+[short] skip
+
+go test -short -coverpkg=strings strings regexp
+! stdout '[^0-9]0\.0%'
+stdout 'strings.*coverage:.*[1-9][0-9.]+%'
+stdout 'regexp.*coverage:.*[1-9][0-9.]+%'
+
+go test -short -cover strings math regexp
+! stdout '[^0-9]0\.0%'
+stdout 'strings.*coverage:.*[1-9][0-9.]+%'
+stdout 'math.*coverage:.*[1-9][0-9.]+%'
+stdout 'regexp.*coverage:.*[1-9][0-9.]+%' \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/cover_statements.txt b/src/cmd/go/testdata/script/cover_statements.txt
new file mode 100644
index 0000000..030177c
--- /dev/null
+++ b/src/cmd/go/testdata/script/cover_statements.txt
@@ -0,0 +1,96 @@
+[short] skip
+
+# Workaround for issue 64014 -- for the portion of this test that
+# verifies that caching works correctly, the cache should theoretically
+# always behave reliably/deterministically, however if other tests are
+# concurrently accessing the cache while this test is running, it can
+# lead to cache lookup failures, which manifest as test failures here.
+# To avoid such flakes, use a separate isolated GOCACHE for this test.
+env GOCACHE=$WORK/cache
+
+# Initial run with simple coverage.
+go test -cover ./pkg1 ./pkg2 ./pkg3 ./pkg4
+[!GOEXPERIMENT:coverageredesign] stdout 'pkg1 \[no test files\]'
+[GOEXPERIMENT:coverageredesign] stdout 'pkg1 coverage: 0.0% of statements'
+stdout 'pkg2 \S+ coverage: 0.0% of statements \[no tests to run\]'
+stdout 'pkg3 \S+ coverage: 100.0% of statements'
+stdout 'pkg4 \S+ coverage: \[no statements\]'
+
+# Second run to make sure that caching works properly.
+go test -x -cover ./pkg1 ./pkg2 ./pkg3 ./pkg4
+[!GOEXPERIMENT:coverageredesign] stdout 'pkg1 \[no test files\]'
+[GOEXPERIMENT:coverageredesign] stdout 'pkg1 coverage: 0.0% of statements'
+stdout 'pkg2 \S+ coverage: 0.0% of statements \[no tests to run\]'
+stdout 'pkg3 \S+ coverage: 100.0% of statements'
+stdout 'pkg4 \S+ coverage: \[no statements\]'
+[GOEXPERIMENT:coverageredesign] ! stderr 'link(\.exe"?)? -'
+! stderr 'compile(\.exe"?)? -'
+! stderr 'cover(\.exe"?)? -'
+[GOEXPERIMENT:coverageredesign] stderr 'covdata(\.exe"?)? percent'
+
+# Now add in -coverprofile.
+go test -cover -coverprofile=cov.dat ./pkg1 ./pkg2 ./pkg3 ./pkg4
+[!GOEXPERIMENT:coverageredesign] stdout 'pkg1 \[no test files\]'
+[GOEXPERIMENT:coverageredesign] stdout 'pkg1 coverage: 0.0% of statements'
+stdout 'pkg2 \S+ coverage: 0.0% of statements \[no tests to run\]'
+stdout 'pkg3 \S+ coverage: 100.0% of statements'
+stdout 'pkg4 \S+ coverage: \[no statements\]'
+
+# Validate
+go tool cover -func=cov.dat
+[GOEXPERIMENT:coverageredesign] stdout 'pkg1/a.go:5:\s+F\s+0.0%'
+
+-- go.mod --
+module m
+
+go 1.16
+-- pkg1/a.go --
+package pkg1
+
+import "fmt"
+
+func F() {
+ fmt.Println("pkg1")
+}
+-- pkg2/a.go --
+package pkg2
+
+import "fmt"
+
+func F() {
+ fmt.Println("pkg2")
+}
+-- pkg2/a_test.go --
+package pkg2
+-- pkg3/a.go --
+package pkg3
+
+import "fmt"
+
+func F() {
+ fmt.Println("pkg3")
+}
+-- pkg3/a_test.go --
+package pkg3
+
+import "testing"
+
+func TestF(t *testing.T) {
+ F()
+}
+-- pkg4/a.go --
+package pkg4
+
+type T struct {
+ X bool
+}
+-- pkg4/a_test.go --
+package pkg4
+
+import (
+ "testing"
+)
+
+func TestT(t *testing.T) {
+ _ = T{}
+}
diff --git a/src/cmd/go/testdata/script/cover_swig.txt b/src/cmd/go/testdata/script/cover_swig.txt
new file mode 100644
index 0000000..decb29a
--- /dev/null
+++ b/src/cmd/go/testdata/script/cover_swig.txt
@@ -0,0 +1,72 @@
+
+# Testcase for issue 64661. This testcase is intended to verify that
+# we don't try to send swig-generated Go files through the cover tool
+# for "go test -cover" runs on packages that have *.swig source files.
+
+[!exec:swig] skip
+[!cgo] skip
+
+go test -v -count=1 -coverprofile=foo.p
+stdout 'coverage: 100.0% of statements'
+
+-- go.mod --
+module simple
+
+go 1.21
+-- main.c --
+/* A global variable */
+double Foo = 3.0;
+
+/* Compute the greatest common divisor of positive integers */
+int gcd(int x, int y) {
+ int g;
+ g = y;
+ while (x > 0) {
+ g = x;
+ x = y % x;
+ y = g;
+ }
+ return g;
+}
+
+
+-- main.go --
+package main
+
+import (
+ "fmt"
+)
+
+func main() {
+ // Call our gcd() function
+ x := 42
+ y := 105
+ g := Gcd(x, y)
+ fmt.Println("The gcd of", x, "and", y, "is", g)
+
+ // Manipulate the Foo global variable
+
+ // Output its current value
+ fmt.Println("Foo =", GetFoo())
+
+ // Change its value
+ SetFoo(3.1415926)
+
+ // See if the change took effect
+ fmt.Println("Foo =", GetFoo())
+}
+-- main.swig --
+%module main
+
+%inline %{
+extern int gcd(int x, int y);
+extern double Foo;
+%}
+-- main_test.go --
+package main
+
+import "testing"
+
+func TestSwigFuncs(t *testing.T) {
+ main()
+}
diff --git a/src/cmd/go/testdata/script/cover_sync_atomic_import.txt b/src/cmd/go/testdata/script/cover_sync_atomic_import.txt
new file mode 100644
index 0000000..283db3e
--- /dev/null
+++ b/src/cmd/go/testdata/script/cover_sync_atomic_import.txt
@@ -0,0 +1,44 @@
+[short] skip
+[compiler:gccgo] skip # gccgo has no cover tool
+[!GOEXPERIMENT:coverageredesign] skip
+
+go test -short -cover -covermode=atomic -coverpkg=coverdep/p1 coverdep
+
+# In addition to the above, test to make sure there is no funny
+# business if we try "go test -cover" in atomic mode targeting
+# sync/atomic itself (see #57445). Just a short test run is needed
+# since we're mainly interested in making sure the test builds and can
+# execute at least one test.
+
+go test -short -covermode=atomic -run=TestStoreInt64 sync/atomic
+go test -short -covermode=atomic -run=TestAnd8 runtime/internal/atomic
+
+# Skip remainder if no race detector support.
+[!race] skip
+
+go test -short -cover -race -run=TestStoreInt64 sync/atomic
+go test -short -cover -race -run=TestAnd8 runtime/internal/atomic
+
+-- go.mod --
+module coverdep
+
+go 1.16
+-- p.go --
+package p
+
+import _ "coverdep/p1"
+
+func F() {
+}
+-- p1/p1.go --
+package p1
+
+import _ "errors"
+-- p_test.go --
+package p
+
+import "testing"
+
+func Test(t *testing.T) {
+ F()
+}
diff --git a/src/cmd/go/testdata/script/cover_test_localpkg_filepath.txt b/src/cmd/go/testdata/script/cover_test_localpkg_filepath.txt
new file mode 100644
index 0000000..17c5808
--- /dev/null
+++ b/src/cmd/go/testdata/script/cover_test_localpkg_filepath.txt
@@ -0,0 +1,40 @@
+
+[short] skip
+
+# collect coverage profile in text format
+go test -coverprofile=blah.prof prog.go prog_test.go
+
+# should not contain cmd-line pseudo-import-path
+grep prog.go blah.prof
+grep $PWD blah.prof
+! grep command-line-arguments blah.prof
+
+-- prog.go --
+package main
+
+func Mumble(x int) int {
+ if x < 0 {
+ return -x
+ }
+ return 42
+}
+
+func Grumble(y int) int {
+ return -y
+}
+
+func main() {
+}
+
+-- prog_test.go --
+package main
+
+import (
+ "testing"
+)
+
+func TestMumble(t *testing.T) {
+ if x := Mumble(10); x != 42 {
+ t.Errorf("Mumble(%d): got %d want %d", 10, x, 42)
+ }
+}
diff --git a/src/cmd/go/testdata/script/cover_test_pkgselect.txt b/src/cmd/go/testdata/script/cover_test_pkgselect.txt
new file mode 100644
index 0000000..97a1d2c
--- /dev/null
+++ b/src/cmd/go/testdata/script/cover_test_pkgselect.txt
@@ -0,0 +1,80 @@
+
+[short] skip
+
+# Hard-wire new coverage for this test.
+env GOEXPERIMENT=coverageredesign
+
+# Baseline run.
+go test -cover example/foo
+stdout 'coverage: 50.0% of statements$'
+
+# Coverage percentage output should mention -coverpkg selection.
+go test -coverpkg=example/foo example/foo
+stdout 'coverage: 50.0% of statements in example/foo'
+
+# Try to ask for coverage of a package that doesn't exist.
+go test -coverpkg nonexistent example/bar
+stderr 'no packages being tested depend on matches for pattern nonexistent'
+stdout 'coverage: \[no statements\]'
+
+# Ask for foo coverage, but test bar.
+go test -coverpkg=example/foo example/bar
+stdout 'coverage: 50.0% of statements in example/foo'
+
+# end of test cmds, start of harness and related files.
+
+-- go.mod --
+module example
+
+go 1.18
+
+-- foo/foo.go --
+package foo
+
+func FooFunc() int {
+ return 42
+}
+func FooFunc2() int {
+ return 42
+}
+
+-- foo/foo_test.go --
+package foo
+
+import "testing"
+
+func TestFoo(t *testing.T) {
+ if FooFunc() != 42 {
+ t.Fatalf("bad")
+ }
+}
+
+-- bar/bar.go --
+package bar
+
+import "example/foo"
+
+func BarFunc() int {
+ return foo.FooFunc2()
+}
+
+-- bar/bar_test.go --
+package bar_test
+
+import (
+ "example/bar"
+ "testing"
+)
+
+func TestBar(t *testing.T) {
+ if bar.BarFunc() != 42 {
+ t.Fatalf("bad")
+ }
+}
+
+-- baz/baz.go --
+package baz
+
+func BazFunc() int {
+ return -42
+}
diff --git a/src/cmd/go/testdata/script/cover_test_race_issue56370.txt b/src/cmd/go/testdata/script/cover_test_race_issue56370.txt
new file mode 100644
index 0000000..2e55f10
--- /dev/null
+++ b/src/cmd/go/testdata/script/cover_test_race_issue56370.txt
@@ -0,0 +1,54 @@
+[short] skip
+[!race] skip
+
+go test -race -cover issue.56370/filter
+
+-- go.mod --
+module issue.56370
+
+go 1.20
+
+-- filter/filter.go --
+
+package filter
+
+func New() func(error) bool {
+ return func(error) bool {
+ return false
+ }
+}
+
+-- filter/filter_test.go --
+
+package filter_test
+
+import (
+ "testing"
+
+ "issue.56370/filter"
+)
+
+func Test1(t *testing.T) {
+ t.Parallel()
+
+ _ = filter.New()
+}
+
+func Test2(t *testing.T) {
+ t.Parallel()
+
+ _ = filter.New()
+}
+
+func Test3(t *testing.T) {
+ t.Parallel()
+
+ _ = filter.New()
+}
+
+func Test4(t *testing.T) {
+ t.Parallel()
+
+ _ = filter.New()
+}
+
diff --git a/src/cmd/go/testdata/script/cover_var_init_order.txt b/src/cmd/go/testdata/script/cover_var_init_order.txt
new file mode 100644
index 0000000..37e07b7
--- /dev/null
+++ b/src/cmd/go/testdata/script/cover_var_init_order.txt
@@ -0,0 +1,55 @@
+# This test verifies that issue 56293 has been fixed, and that the
+# insertion of coverage instrumentation doesn't perturb package
+# initialization order.
+
+[short] skip
+
+# Skip if new coverage is turned off.
+[!GOEXPERIMENT:coverageredesign] skip
+
+go test -cover example
+
+-- go.mod --
+module example
+
+go 1.20
+
+-- m.go --
+
+package main
+
+import (
+ "flag"
+)
+
+var (
+ fooFlag = flag.String("foo", "", "this should be ok")
+ foo = flag.Lookup("foo")
+
+ barFlag = flag.String("bar", "", "this should be also ok, but is "+notOK()+".")
+ bar = flag.Lookup("bar")
+)
+
+func notOK() string {
+ return "not OK"
+}
+
+-- m_test.go --
+
+package main
+
+import (
+ "testing"
+)
+
+func TestFoo(t *testing.T) {
+ if foo == nil {
+ t.Fatal()
+ }
+}
+
+func TestBar(t *testing.T) {
+ if bar == nil {
+ t.Fatal()
+ }
+}
diff --git a/src/cmd/go/testdata/script/cpu_profile_twice.txt b/src/cmd/go/testdata/script/cpu_profile_twice.txt
new file mode 100644
index 0000000..38d6439
--- /dev/null
+++ b/src/cmd/go/testdata/script/cpu_profile_twice.txt
@@ -0,0 +1,22 @@
+env GO111MODULE=off
+
+# Issue 23150
+
+[short] skip
+
+go test -o=$WORK/x.test -cpuprofile=$WORK/cpu_profile_twice.out x
+rm $WORK/cpu_profile_twice.out
+
+go test -o=$WORK/x.test -cpuprofile=$WORK/cpu_profile_twice.out x
+exists $WORK/cpu_profile_twice.out
+
+
+-- x/x_test.go --
+package x_test
+import (
+ "testing"
+ "time"
+)
+func TestSleep(t *testing.T) {
+ time.Sleep(10 * time.Millisecond)
+}
diff --git a/src/cmd/go/testdata/script/devnull.txt b/src/cmd/go/testdata/script/devnull.txt
new file mode 100644
index 0000000..ccb866a
--- /dev/null
+++ b/src/cmd/go/testdata/script/devnull.txt
@@ -0,0 +1,26 @@
+env GO111MODULE=off
+
+# Issue 28035: go test -c -o NUL should work.
+# Issue 28549: go test -c -o /dev/null should not overwrite /dev/null when run as root.
+cd x
+cmp $devnull $WORK/empty.txt
+go test -o=$devnull -c
+! exists x.test$GOEXE
+cmp $devnull $WORK/empty.txt
+
+# Issue 12407: go build -o /dev/null should succeed.
+cd ..
+go build -o $devnull y
+cmp $devnull $WORK/empty.txt
+
+-- x/x_test.go --
+package x_test
+import (
+ "testing"
+)
+func TestNUL(t *testing.T) {
+}
+-- y/y.go --
+package y
+func main() {}
+-- $WORK/empty.txt --
diff --git a/src/cmd/go/testdata/script/dist_list_missing.txt b/src/cmd/go/testdata/script/dist_list_missing.txt
new file mode 100644
index 0000000..affaa00
--- /dev/null
+++ b/src/cmd/go/testdata/script/dist_list_missing.txt
@@ -0,0 +1,57 @@
+# Regression test for #60939: when 'go tool dist' is missing,
+# 'go tool dist list' should inject its output.
+
+
+# Set GOROOT to a directory that definitely does not include
+# a compiled 'dist' tool. 'go tool dist list' should still
+# work, because 'cmd/go' itself can impersonate this command.
+
+mkdir $WORK/goroot/bin
+mkdir $WORK/goroot/pkg/tool/${GOOS}_${GOARCH}
+env GOROOT=$WORK/goroot
+
+! go tool -n dist
+stderr 'go: no such tool "dist"'
+
+go tool dist list
+stdout linux/amd64
+cp stdout tool.txt
+
+go tool dist list -v
+stdout linux/amd64
+cp stdout tool-v.txt
+
+go tool dist list -broken
+stdout $GOOS/$GOARCH
+cp stdout tool-broken.txt
+
+go tool dist list -json
+stdout '"GOOS": "linux",\n\s*"GOARCH": "amd64",\n'
+cp stdout tool-json.txt
+
+go tool dist list -json -broken
+stdout '"GOOS": "'$GOOS'",\n\s*"GOARCH": "'$GOARCH'",\n'
+cp stdout tool-json-broken.txt
+
+[short] stop
+
+
+# Check against the real cmd/dist as the source of truth.
+
+env GOROOT=$TESTGO_GOROOT
+go build -o dist.exe cmd/dist
+
+exec ./dist.exe list
+cmp stdout tool.txt
+
+exec ./dist.exe list -v
+cmp stdout tool-v.txt
+
+exec ./dist.exe list -broken
+cmp stdout tool-broken.txt
+
+exec ./dist.exe list -json
+cmp stdout tool-json.txt
+
+exec ./dist.exe list -json -broken
+cmp stdout tool-json-broken.txt
diff --git a/src/cmd/go/testdata/script/doc.txt b/src/cmd/go/testdata/script/doc.txt
new file mode 100644
index 0000000..3ff1aab
--- /dev/null
+++ b/src/cmd/go/testdata/script/doc.txt
@@ -0,0 +1,75 @@
+# go doc --help
+! go doc --help
+stderr 'go doc'
+stderr 'go doc <pkg>'
+stderr 'go doc <sym>\[\.<methodOrField>\]'
+stderr 'go doc \[<pkg>\.\]<sym>\[\.<methodOrField>\]'
+stderr 'go doc \[<pkg>\.\]\[<sym>\.\]<methodOrField>'
+stderr 'go doc <pkg> <sym>\[\.<methodOrField>\]'
+
+# go help doc
+go help doc
+stdout 'go doc'
+stdout 'go doc <pkg>'
+stdout 'go doc <sym>\[\.<methodOrField>\]'
+stdout 'go doc \[<pkg>\.\]<sym>\[\.<methodOrField>\]'
+stdout 'go doc \[<pkg>\.\]\[<sym>\.\]<methodOrField>'
+stdout 'go doc <pkg> <sym>\[\.<methodOrField>\]'
+
+# go doc <pkg>
+go doc p/v2
+stdout .
+
+# go doc <pkg> <sym>
+go doc p/v2 Symbol
+stdout .
+
+# go doc <pkg> <sym> <method>
+! go doc p/v2 Symbol Method
+stderr .
+
+# go doc <pkg>.<sym>
+go doc p/v2.Symbol
+stdout .
+
+# go doc <pkg>.<sym>.<method>
+go doc p/v2.Symbol.Method
+stdout .
+
+# go doc <sym>
+go doc Symbol
+stdout .
+
+# go doc <sym> <method>
+! go doc Symbol Method
+stderr .
+
+# go doc <sym>.<method>
+go doc Symbol.Method
+stdout .
+
+# go doc <pkg>.<method>
+go doc p/v2.Method
+stdout .
+
+# go doc <pkg> <method>
+go doc p/v2 Method
+stdout .
+
+# go doc <method>
+go doc Method
+stdout .
+
+-- go.mod --
+module p/v2
+
+go 1.13
+
+-- p.go --
+package p
+
+type Symbol struct{}
+
+func (Symbol) Method() error {
+ return nil
+}
diff --git a/src/cmd/go/testdata/script/embed.txt b/src/cmd/go/testdata/script/embed.txt
new file mode 100644
index 0000000..5f7f6ed
--- /dev/null
+++ b/src/cmd/go/testdata/script/embed.txt
@@ -0,0 +1,130 @@
+# go list shows patterns and files
+go list -f '{{.EmbedPatterns}}'
+stdout '\[x\*t\*t\]'
+go list -f '{{.EmbedFiles}}'
+stdout '\[x.txt\]'
+go list -test -f '{{.TestEmbedPatterns}}'
+stdout '\[y\*t\*t\]'
+go list -test -f '{{.TestEmbedFiles}}'
+stdout '\[y.txt\]'
+go list -test -f '{{.XTestEmbedPatterns}}'
+stdout '\[z\*t\*t\]'
+go list -test -f '{{.XTestEmbedFiles}}'
+stdout '\[z.txt\]'
+
+# build embeds x.txt
+go build -x
+stderr 'x.txt'
+
+# build uses cache correctly
+go build -x
+! stderr 'x.txt'
+cp x.txt2 x.txt
+go build -x
+stderr 'x.txt'
+
+# build rejects invalid names
+cp x.go2 x.go
+go build -x
+cp x.txt .git
+! go build -x
+stderr '^x.go:5:12: pattern [*]t: cannot embed file [.]git: invalid name [.]git$'
+rm .git
+
+# build rejects symlinks
+[symlink] symlink x.tzt -> x.txt
+[symlink] ! go build -x
+[symlink] stderr 'pattern [*]t: cannot embed irregular file x.tzt'
+[symlink] rm x.tzt
+
+# build rejects empty directories
+mkdir t
+! go build -x
+stderr '^x.go:5:12: pattern [*]t: cannot embed directory t: contains no embeddable files$'
+
+# build ignores symlinks and invalid names in directories
+cp x.txt t/.git
+! go build -x
+stderr '^x.go:5:12: pattern [*]t: cannot embed directory t: contains no embeddable files$'
+go list -e -f '{{.Incomplete}}'
+stdout 'true'
+[symlink] symlink t/x.link -> ../x.txt
+[symlink] ! go build -x
+[symlink] stderr '^x.go:5:12: pattern [*]t: cannot embed directory t: contains no embeddable files$'
+
+cp x.txt t/x.txt
+go build -x
+
+# build reports errors with positions in imported packages
+rm t/x.txt
+! go build m/use
+stderr '^x.go:5:12: pattern [*]t: cannot embed directory t: contains no embeddable files$'
+
+# all still ignores .git and symlinks
+cp x.go3 x.go
+! go build -x
+stderr '^x.go:5:12: pattern all:t: cannot embed directory t: contains no embeddable files$'
+
+# all finds dot files and underscore files
+cp x.txt t/.x.txt
+go build -x
+rm t/.x.txt
+cp x.txt t/_x.txt
+go build -x
+
+-- x.go --
+package p
+
+import "embed"
+
+//go:embed x*t*t
+var X embed.FS
+
+-- x_test.go --
+package p
+
+import "embed"
+
+//go:embed y*t*t
+var Y string
+
+-- x_x_test.go --
+package p_test
+
+import "embed"
+
+//go:embed z*t*t
+var Z string
+
+-- x.go2 --
+package p
+
+import "embed"
+
+//go:embed *t
+var X embed.FS
+
+-- x.go3 --
+package p
+
+import "embed"
+
+//go:embed all:t
+var X embed.FS
+
+-- x.txt --
+hello
+
+-- y.txt --
+-- z.txt --
+-- x.txt2 --
+not hello
+
+-- use/use.go --
+package use
+
+import _ "m"
+-- go.mod --
+module m
+
+go 1.16
diff --git a/src/cmd/go/testdata/script/embed_brackets.txt b/src/cmd/go/testdata/script/embed_brackets.txt
new file mode 100644
index 0000000..ec17ff3
--- /dev/null
+++ b/src/cmd/go/testdata/script/embed_brackets.txt
@@ -0,0 +1,18 @@
+# issue 53314
+[GOOS:windows] skip
+cd [pkg]
+go build
+
+-- [pkg]/go.mod --
+module m
+
+go 1.19
+-- [pkg]/x.go --
+package p
+
+import _ "embed"
+
+//go:embed t.txt
+var S string
+
+-- [pkg]//t.txt --
diff --git a/src/cmd/go/testdata/script/embed_fmt.txt b/src/cmd/go/testdata/script/embed_fmt.txt
new file mode 100644
index 0000000..8a16afe
--- /dev/null
+++ b/src/cmd/go/testdata/script/embed_fmt.txt
@@ -0,0 +1,22 @@
+# go fmt ignores file not found
+go fmt xnofmt.go
+cmp xnofmt.go xfmt.ref
+! go build xnofmt.go
+stderr 'xnofmt.go:5:12: pattern missing.txt: no matching files found'
+
+-- xnofmt.go --
+package p
+
+import "embed"
+
+//go:embed missing.txt
+var X embed.FS
+-- xfmt.ref --
+package p
+
+import "embed"
+
+//go:embed missing.txt
+var X embed.FS
+-- go.mod --
+module m
diff --git a/src/cmd/go/testdata/script/env_cache.txt b/src/cmd/go/testdata/script/env_cache.txt
new file mode 100644
index 0000000..f2af7ee
--- /dev/null
+++ b/src/cmd/go/testdata/script/env_cache.txt
@@ -0,0 +1,5 @@
+# go env should caches compiler results
+go env
+go env -x
+! stdout '\|\| true'
+
diff --git a/src/cmd/go/testdata/script/env_cross_build.txt b/src/cmd/go/testdata/script/env_cross_build.txt
new file mode 100644
index 0000000..91d1cb9
--- /dev/null
+++ b/src/cmd/go/testdata/script/env_cross_build.txt
@@ -0,0 +1,29 @@
+# Test that the correct default GOEXPERIMENT is used when cross
+# building with GOENV (#46815).
+
+# Unset variables set by the TestScript harness. Users typically won't
+# explicitly configure these, and #46815 doesn't repro if they are.
+env GOOS=
+env GOARCH=
+env GOEXPERIMENT=
+
+env GOENV=windows-amd64
+go build internal/abi
+
+env GOENV=ios-arm64
+go build internal/abi
+
+env GOENV=linux-mips
+go build internal/abi
+
+-- windows-amd64 --
+GOOS=windows
+GOARCH=amd64
+
+-- ios-arm64 --
+GOOS=ios
+GOARCH=arm64
+
+-- linux-mips --
+GOOS=linux
+GOARCH=mips
diff --git a/src/cmd/go/testdata/script/env_exp.txt b/src/cmd/go/testdata/script/env_exp.txt
new file mode 100644
index 0000000..681512d
--- /dev/null
+++ b/src/cmd/go/testdata/script/env_exp.txt
@@ -0,0 +1,17 @@
+# Test GOEXPERIMENT variable
+
+# go env shows default empty GOEXPERIMENT
+go env
+stdout GOEXPERIMENT=
+
+# go env shows valid experiments
+env GOEXPERIMENT=fieldtrack,staticlockranking
+go env GOEXPERIMENT
+stdout '.*fieldtrack.*staticlockranking.*'
+go env
+stdout 'GOEXPERIMENT=.*fieldtrack.*staticlockranking.*'
+
+# go env rejects unknown experiments
+env GOEXPERIMENT=bad
+! go env GOEXPERIMENT
+stderr 'unknown GOEXPERIMENT bad'
diff --git a/src/cmd/go/testdata/script/env_issue46807.txt b/src/cmd/go/testdata/script/env_issue46807.txt
new file mode 100644
index 0000000..e37bc63
--- /dev/null
+++ b/src/cmd/go/testdata/script/env_issue46807.txt
@@ -0,0 +1,12 @@
+! go mod tidy
+stderr '^go: warning: ignoring go.mod in \$GOPATH'
+stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules'''
+
+go env
+stdout 'GOPATH='
+stderr '^go: warning: ignoring go.mod in \$GOPATH'
+
+-- $GOPATH/go.mod --
+module bug
+
+go 1.21 \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/env_sanitize.txt b/src/cmd/go/testdata/script/env_sanitize.txt
new file mode 100644
index 0000000..cc4d23a
--- /dev/null
+++ b/src/cmd/go/testdata/script/env_sanitize.txt
@@ -0,0 +1,5 @@
+env GOFLAGS='$(echo ''cc"''; echo ''OOPS="oops'')'
+go env
+[GOOS:darwin] stdout 'GOFLAGS=''\$\(echo ''\\''''cc"''\\''''; echo ''\\''''OOPS="oops''\\''''\)'''
+[GOOS:linux] stdout 'GOFLAGS=''\$\(echo ''\\''''cc"''\\''''; echo ''\\''''OOPS="oops''\\''''\)'''
+[GOOS:windows] stdout 'set GOFLAGS=\$\(echo ''cc"''; echo ''OOPS="oops''\)'
diff --git a/src/cmd/go/testdata/script/env_unset.txt b/src/cmd/go/testdata/script/env_unset.txt
new file mode 100644
index 0000000..22bc845
--- /dev/null
+++ b/src/cmd/go/testdata/script/env_unset.txt
@@ -0,0 +1,30 @@
+# Test that we can unset variables, even if initially invalid,
+# as long as resulting config is valid.
+
+env GOENV=badenv
+env GOOS=
+env GOARCH=
+env GOEXPERIMENT=
+
+! go env
+stderr '^go(\.exe)?: unknown GOEXPERIMENT badexp$'
+
+go env -u GOEXPERIMENT
+
+! go env
+stderr '^go: unsupported GOOS/GOARCH pair bados/badarch$'
+
+! go env -u GOOS
+stderr '^go: unsupported GOOS/GOARCH pair \w+/badarch$'
+
+! go env -u GOARCH
+stderr '^go: unsupported GOOS/GOARCH pair bados/\w+$'
+
+go env -u GOOS GOARCH
+
+go env
+
+-- badenv --
+GOOS=bados
+GOARCH=badarch
+GOEXPERIMENT=badexp
diff --git a/src/cmd/go/testdata/script/env_write.txt b/src/cmd/go/testdata/script/env_write.txt
new file mode 100644
index 0000000..5d40949
--- /dev/null
+++ b/src/cmd/go/testdata/script/env_write.txt
@@ -0,0 +1,206 @@
+env GO111MODULE=off
+
+# go env should default to the right places
+env AppData=$HOME/windowsappdata
+env home=$HOME/plan9home
+go env GOENV
+[GOOS:aix] stdout $HOME/.config/go/env
+[GOOS:darwin] stdout $HOME'/Library/Application Support/go/env'
+[GOOS:freebsd] stdout $HOME/.config/go/env
+[GOOS:linux] stdout $HOME/.config/go/env
+[GOOS:netbsd] stdout $HOME/.config/go/env
+[GOOS:openbsd] stdout $HOME/.config/go/env
+[GOOS:plan9] stdout $HOME/plan9home/lib/go/env
+[GOOS:windows] stdout $HOME\\windowsappdata\\go\\env
+
+# Now override it to something writable.
+env GOENV=$WORK/envdir/go/env
+go env GOENV
+stdout envdir[\\/]go[\\/]env
+
+# go env shows all variables
+go env
+stdout GOARCH=
+stdout GOOS=
+stdout GOROOT=
+
+# go env ignores invalid flag in GOFLAGS environment variable
+env GOFLAGS='=true'
+go env
+
+# checking errors
+! go env -w
+stderr 'go: no KEY=VALUE arguments given'
+! go env -u
+stderr 'go: ''go env -u'' requires an argument'
+
+# go env -w changes default setting
+env root=
+[GOOS:windows] env root=c:
+env GOPATH=
+go env -w GOPATH=$root/non-exist/gopath
+! stderr .+
+grep GOPATH=$root/non-exist/gopath $WORK/envdir/go/env
+go env GOPATH
+stdout /non-exist/gopath
+
+# go env -w does not override OS environment, and warns about that
+env GOPATH=$root/other
+go env -w GOPATH=$root/non-exist/gopath2
+stderr 'warning: go env -w GOPATH=... does not override conflicting OS environment variable'
+go env GOPATH
+stdout $root/other
+
+# but go env -w does do the update, and unsetting the env var exposes the change
+env GOPATH=
+go env GOPATH
+stdout $root/non-exist/gopath2
+
+# unsetting with go env -u does not warn about OS environment overrides,
+# nor does it warn about variables that haven't been set by go env -w.
+env GOPATH=$root/other
+go env -u GOPATH
+! stderr .+
+go env -u GOPATH
+! stderr .+
+
+# go env -w rejects unknown or bad variables
+! go env -w GODEBUG=gctrace=1
+stderr 'unknown go command variable GODEBUG'
+! go env -w GOEXE=.bat
+stderr 'GOEXE cannot be modified'
+! go env -w GOVERSION=customversion
+stderr 'GOVERSION cannot be modified'
+! go env -w GOENV=/env
+stderr 'GOENV can only be set using the OS environment'
+
+# go env -w can set multiple variables
+env CC=
+go env CC
+! stdout ^xyc$
+go env -w GOOS=$GOOS CC=xyc
+grep CC=xyc $GOENV
+# file is maintained in sorted order
+grep 'CC=xyc\nGOOS=' $GOENV
+go env CC
+stdout ^xyc$
+
+# go env -u unsets effect of go env -w.
+go env -u CC
+go env CC
+! stdout ^xyc$
+
+# go env -w rejects double-set variables
+! go env -w GOOS=$GOOS GOOS=$GOOS
+stderr 'multiple values for key: GOOS'
+
+# go env -w rejects missing variables
+! go env -w GOOS
+stderr 'arguments must be KEY=VALUE: invalid argument: GOOS'
+
+# go env -w rejects invalid GO111MODULE values, as otherwise cmd/go would break
+! go env -w GO111MODULE=badvalue
+stderr 'invalid GO111MODULE value "badvalue"'
+
+# go env -w rejects invalid GOPATH values
+! go env -w GOPATH=~/go
+stderr 'GOPATH entry cannot start with shell metacharacter'
+
+! go env -w GOPATH=./go
+stderr 'GOPATH entry is relative; must be absolute path'
+
+# go env -w rejects invalid GOTMPDIR values
+! go env -w GOTMPDIR=x
+stderr 'go: GOTMPDIR must be an absolute path'
+
+# go env -w should accept absolute GOTMPDIR value
+# and should not create it
+[GOOS:windows] go env -w GOTMPDIR=$WORK\x\y\z
+[!GOOS:windows] go env -w GOTMPDIR=$WORK/x/y/z
+! exists $WORK/x/y/z
+# we should be able to clear an env
+go env -u GOTMPDIR
+go env GOTMPDIR
+stdout ^$
+
+[GOOS:windows] go env -w GOTMPDIR=$WORK\x\y\z
+[!GOOS:windows] go env -w GOTMPDIR=$WORK/x/y/z
+go env -w GOTMPDIR=
+go env GOTMPDIR
+stdout ^$
+
+# go env -w rejects relative CC values
+[!GOOS:windows] go env -w CC=/usr/bin/clang
+go env -w CC=clang
+[!GOOS:windows] ! go env -w CC=./clang
+[!GOOS:windows] ! go env -w CC=bin/clang
+[!GOOS:windows] stderr 'go: CC entry is relative; must be absolute path'
+
+[GOOS:windows] go env -w CC=$WORK\bin\clang
+[GOOS:windows] ! go env -w CC=.\clang
+[GOOS:windows] ! go env -w CC=bin\clang
+[GOOS:windows] stderr 'go: CC entry is relative; must be absolute path'
+
+# go env -w rejects relative CXX values
+[!GOOS:windows] go env -w CC=/usr/bin/cpp
+go env -w CXX=cpp
+[!GOOS:windows] ! go env -w CXX=./cpp
+[!GOOS:windows] ! go env -w CXX=bin/cpp
+[!GOOS:windows] stderr 'go: CXX entry is relative; must be absolute path'
+
+[GOOS:windows] go env -w CXX=$WORK\bin\cpp
+[GOOS:windows] ! go env -w CXX=.\cpp
+[GOOS:windows] ! go env -w CXX=bin\cpp
+[GOOS:windows] stderr 'go: CXX entry is relative; must be absolute path'
+
+# go env -w/-u checks validity of GOOS/ARCH combinations
+env GOOS=
+env GOARCH=
+# check -w doesn't allow invalid GOOS
+! go env -w GOOS=linuxx
+stderr 'unsupported GOOS/GOARCH pair linuxx'
+# check -w doesn't allow invalid GOARCH
+! go env -w GOARCH=amd644
+stderr 'unsupported GOOS/GOARCH.*/amd644$'
+# check -w doesn't allow invalid GOOS with valid GOARCH
+! go env -w GOOS=linuxx GOARCH=amd64
+stderr 'unsupported GOOS/GOARCH pair linuxx'
+# check a valid GOOS and GOARCH values but an incompatible combinations
+! go env -w GOOS=android GOARCH=s390x
+stderr 'unsupported GOOS/GOARCH pair android/s390x'
+# check that -u considers explicit envs
+go env -w GOOS=linux GOARCH=mips
+env GOOS=windows
+! go env -u GOOS
+stderr 'unsupported GOOS/GOARCH.*windows/mips$'
+env GOOS=
+
+# go env -w should reject relative paths in GOMODCACHE environment.
+! go env -w GOMODCACHE=~/test
+stderr 'go: GOMODCACHE entry is relative; must be absolute path: "~/test"'
+! go env -w GOMODCACHE=./test
+stderr 'go: GOMODCACHE entry is relative; must be absolute path: "./test"'
+
+# go env -w checks validity of GOEXPERIMENT
+env GOEXPERIMENT=
+! go env -w GOEXPERIMENT=badexp
+stderr 'unknown GOEXPERIMENT badexp'
+go env -w GOEXPERIMENT=fieldtrack
+
+# go env -w and go env -u work on unknown fields already in the go/env file
+cp bad.env $GOENV
+go env GOENV
+cat $GOENV
+go env
+! stdout UNKNOWN
+go env UNKNOWN
+stdout yes
+go env -w UNKNOWN=maybe
+go env UNKNOWN
+stdout maybe
+go env -u UNKNOWN
+go env UNKNOWN
+! stdout . # gone
+
+-- bad.env --
+UNKNOWN=yes
diff --git a/src/cmd/go/testdata/script/fileline.txt b/src/cmd/go/testdata/script/fileline.txt
new file mode 100644
index 0000000..5cb35f0
--- /dev/null
+++ b/src/cmd/go/testdata/script/fileline.txt
@@ -0,0 +1,8 @@
+env GO111MODULE=off
+
+# look for short, relative file:line in error message
+! go run ../../gopath/x/y/z/err.go
+stderr ^..[\\/]x[\\/]y[\\/]z[\\/]err.go:
+
+-- ../x/y/z/err.go --
+package main; import "bar"
diff --git a/src/cmd/go/testdata/script/fmt_load_errors.txt b/src/cmd/go/testdata/script/fmt_load_errors.txt
new file mode 100644
index 0000000..e3a9034
--- /dev/null
+++ b/src/cmd/go/testdata/script/fmt_load_errors.txt
@@ -0,0 +1,38 @@
+env GO111MODULE=off
+
+! go fmt does-not-exist
+
+go fmt -n exclude
+stdout 'exclude[/\\]x\.go'
+stdout 'exclude[/\\]x_linux\.go'
+
+# Test edge cases with gofmt.
+
+! exec $GOROOT/bin/gofmt does-not-exist
+
+exec $GOROOT/bin/gofmt gofmt-dir/no-extension
+stdout 'package x'
+
+exec $GOROOT/bin/gofmt gofmt-dir
+! stdout 'package x'
+
+! exec $GOROOT/bin/gofmt empty.go nopackage.go
+stderr -count=1 'empty\.go:1:1: expected .package., found .EOF.'
+stderr -count=1 'nopackage\.go:1:1: expected .package., found not'
+
+-- exclude/empty/x.txt --
+-- exclude/ignore/_x.go --
+package x
+-- exclude/x.go --
+// +build linux,!linux
+
+package x
+-- exclude/x_linux.go --
+// +build windows
+
+package x
+-- gofmt-dir/no-extension --
+package x
+-- empty.go --
+-- nopackage.go --
+not the proper start to a Go file
diff --git a/src/cmd/go/testdata/script/fsys_walk.txt b/src/cmd/go/testdata/script/fsys_walk.txt
new file mode 100644
index 0000000..9d1a945
--- /dev/null
+++ b/src/cmd/go/testdata/script/fsys_walk.txt
@@ -0,0 +1,6 @@
+# Test that go list prefix... does not read directories not beginning with prefix.
+env GODEBUG=gofsystrace=1
+go list m...
+stderr mime
+stderr mime[\\/]multipart
+! stderr archive
diff --git a/src/cmd/go/testdata/script/gccgo_link_c.txt b/src/cmd/go/testdata/script/gccgo_link_c.txt
new file mode 100644
index 0000000..d37cb66
--- /dev/null
+++ b/src/cmd/go/testdata/script/gccgo_link_c.txt
@@ -0,0 +1,20 @@
+# Issue #7573
+# cmd/cgo: undefined reference when linking a C-library using gccgo
+
+[!cgo] skip
+[!exec:gccgo] skip
+[cross] skip # gccgo can't necessarily cross-compile, so don't assume it will reach the step where we expect it to fail
+
+! go build -x -compiler gccgo
+stderr 'gccgo.*\-L [^ ]*alibpath \-lalib' # make sure that Go-inline "#cgo LDFLAGS:" ("-L alibpath -lalib") passed to gccgo linking stage
+! stderr 'gccgo.*-lalib.*-lalib' # make sure -lalib is only passed once
+
+-- go.mod --
+module m
+-- cgoref.go --
+package main
+// #cgo LDFLAGS: -L alibpath -lalib
+// void f(void) {}
+import "C"
+
+func main() { C.f() }
diff --git a/src/cmd/go/testdata/script/gccgo_link_ldflags.txt b/src/cmd/go/testdata/script/gccgo_link_ldflags.txt
new file mode 100644
index 0000000..80526c6
--- /dev/null
+++ b/src/cmd/go/testdata/script/gccgo_link_ldflags.txt
@@ -0,0 +1,23 @@
+# Test that #cgo LDFLAGS are properly quoted.
+# The #cgo LDFLAGS below should pass a string with spaces to -L,
+# as though searching a directory with a space in its name.
+# It should not pass --nosuchoption to the external linker.
+
+[!cgo] skip
+
+go build
+
+[!exec:gccgo] skip
+
+# TODO: remove once gccgo on builder is updated
+[GOOS:aix] [GOARCH:ppc64] skip
+
+go build -compiler gccgo
+
+-- go.mod --
+module m
+-- cgo.go --
+package main
+// #cgo LDFLAGS: -L "./ -Wl,--nosuchoption"
+import "C"
+func main() {}
diff --git a/src/cmd/go/testdata/script/gccgo_m.txt b/src/cmd/go/testdata/script/gccgo_m.txt
new file mode 100644
index 0000000..beb9c50
--- /dev/null
+++ b/src/cmd/go/testdata/script/gccgo_m.txt
@@ -0,0 +1,20 @@
+# It's absurd, but builds with -compiler=gccgo used to fail to build module m.
+# golang.org/issue/34358
+
+env GO111MODULE=off
+
+[short] skip
+[cross] skip # gccgo can't necessarily cross-compile
+
+cd m
+go build
+exists m$GOEXE
+rm m$GOEXE
+[exec:gccgo] go build -compiler=gccgo
+[exec:gccgo] exists m$GOEXE
+
+-- m/go.mod --
+module m
+-- m/main.go --
+package main
+func main() {}
diff --git a/src/cmd/go/testdata/script/gccgo_mangle.txt b/src/cmd/go/testdata/script/gccgo_mangle.txt
new file mode 100644
index 0000000..7a09a80
--- /dev/null
+++ b/src/cmd/go/testdata/script/gccgo_mangle.txt
@@ -0,0 +1,15 @@
+# Issue 33871.
+
+cd m/a.0
+go build
+
+-- m/go.mod --
+module m
+-- m/a.0/a.go --
+package a
+
+type T int
+
+func (t T) M() int {
+ return int(t)
+}
diff --git a/src/cmd/go/testdata/script/gcflags_patterns.txt b/src/cmd/go/testdata/script/gcflags_patterns.txt
new file mode 100644
index 0000000..cc7b2fc
--- /dev/null
+++ b/src/cmd/go/testdata/script/gcflags_patterns.txt
@@ -0,0 +1,93 @@
+env GO111MODULE=off
+
+[!compiler:gc] skip 'using -gcflags and -ldflags'
+[short] skip
+
+# -gcflags=-e applies to named packages, not dependencies
+go build -a -n -v -gcflags=-e z1 z2
+stderr 'compile.* -p z1.* -e '
+stderr 'compile.* -p z2.* -e '
+stderr 'compile.* -p y'
+! stderr 'compile.* -p [^z].* -e '
+
+# -gcflags can specify package=flags, and can be repeated; last match wins
+go build -a -n -v -gcflags=-e -gcflags=z1=-N z1 z2
+stderr 'compile.* -p z1.* -N '
+! stderr 'compile.* -p z1.* -e '
+! stderr 'compile.* -p z2.* -N '
+stderr 'compile.* -p z2.* -e '
+stderr 'compile.* -p y'
+! stderr 'compile.* -p [^z].* -e '
+! stderr 'compile.* -p [^z].* -N '
+
+# -gcflags can have arbitrary spaces around the flags
+go build -a -n -v -gcflags=' z1 = -e ' z1
+stderr 'compile.* -p z1.* -e '
+
+# -gcflags='all=-e' should apply to all packages, even with go test
+go test -a -c -n -gcflags='all=-e' z1
+stderr 'compile.* -p z3.* -e '
+
+# this particular -gcflags argument made the compiler crash
+! go build -gcflags=-d=ssa/ z1
+stderr 'PhaseOptions usage'
+
+# check for valid -ldflags parameter
+! go build '-ldflags="-X main.X=Hello"'
+stderr 'invalid value'
+
+# -ldflags for implicit test package applies to test binary
+go test -a -c -n -gcflags=-N -ldflags=-X=x.y=z z1
+stderr 'compile.* -N .*z_test.go'
+stderr 'link.* -X=x.y=z'
+
+# -ldflags for explicit test package applies to test binary
+go test -a -c -n -gcflags=z1=-N -ldflags=z1=-X=x.y=z z1
+stderr 'compile.* -N .*z_test.go'
+stderr 'link.* -X=x.y=z'
+
+# -ldflags applies to link of command
+go build -a -n -ldflags=-X=math.pi=3 my/cmd/prog
+stderr 'link.* -X=math.pi=3'
+
+# -ldflags applies to link of command even with strange directory name
+go build -a -n -ldflags=-X=math.pi=3 my/cmd/prog/
+stderr 'link.* -X=math.pi=3'
+
+# -ldflags applies to current directory
+cd my/cmd/prog
+go build -a -n -ldflags=-X=math.pi=3
+stderr 'link.* -X=math.pi=3'
+
+# -ldflags applies to current directory even if GOPATH is funny
+[!case-sensitive] cd $WORK/GoPath/src/my/cmd/prog
+go build -a -n -ldflags=-X=math.pi=3
+stderr 'link.* -X=math.pi=3'
+
+# cgo.a should not be a dependency of internally-linked go package
+go build -ldflags='-linkmode=external -linkmode=internal' -n prog.go
+! stderr 'packagefile .*runtime/cgo.a'
+
+-- z1/z.go --
+package z1
+import _ "y"
+import _ "z2"
+
+-- z1/z_test.go --
+package z1_test
+import "testing"
+import _ "z3"
+func Test(t *testing.T) {}
+
+-- z2/z.go --
+package z2
+
+-- z3/z.go --
+package z3
+
+-- y/y.go --
+package y
+
+-- my/cmd/prog/prog.go --
+package main
+func main() {}
diff --git a/src/cmd/go/testdata/script/generate.txt b/src/cmd/go/testdata/script/generate.txt
new file mode 100644
index 0000000..58777c5
--- /dev/null
+++ b/src/cmd/go/testdata/script/generate.txt
@@ -0,0 +1,107 @@
+[short] skip
+
+# Install an echo command because Windows doesn't have it.
+env GOBIN=$WORK/tmp/bin
+go install echo.go
+env PATH=$GOBIN${:}$PATH
+
+# Test go generate handles a simple command
+go generate ./generate/simple.go
+stdout 'Success'
+
+# Test go generate handles a command alias
+go generate './generate/alias.go'
+stdout 'Now is the time for all good men'
+
+# Test go generate's variable substitution
+go generate './generate/substitution.go'
+stdout $GOARCH' substitution.go:7 pabc xyzp/substitution.go/123'
+
+# Test go generate's run and skip flags
+go generate -run y.s './generate/flag.go'
+stdout 'yes' # flag.go should select yes
+! stdout 'no' # flag.go should not select no
+
+go generate -skip th..sand './generate/flag.go'
+stdout 'yes' # flag.go should select yes
+! stdout 'no' # flag.go should not select no
+
+go generate -run . -skip th..sand './generate/flag.go'
+stdout 'yes' # flag.go should select yes
+! stdout 'no' # flag.go should not select no
+
+# Test go generate provides the right "$GOPACKAGE" name in an x_test
+go generate './generate/env_test.go'
+stdout 'main_test'
+
+# Test go generate provides the right "$PWD"
+go generate './generate/env_pwd.go'
+stdout $WORK'[/\\]gopath[/\\]src[/\\]generate'
+
+-- echo.go --
+package main
+
+import (
+ "fmt"
+ "os"
+ "strings"
+)
+
+func main() {
+ fmt.Println(strings.Join(os.Args[1:], " "))
+ fmt.Println()
+}
+-- generate/simple.go --
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Simple test for go generate.
+
+// We include a build tag that go generate should ignore.
+
+// +build ignore
+
+//go:generate echo Success
+
+package p
+-- generate/alias.go --
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that go generate handles command aliases.
+
+//go:generate -command run echo Now is the time
+//go:generate run for all good men
+
+package p
+-- generate/substitution.go --
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test go generate variable substitution.
+
+//go:generate echo $GOARCH $GOFILE:$GOLINE ${GOPACKAGE}abc xyz$GOPACKAGE/$GOFILE/123
+
+package p
+-- generate/flag.go --
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test -run flag
+
+//go:generate echo oh yes my man
+//go:generate echo no, no, a thousand times no
+
+package p
+-- generate/env_test.go --
+package main_test
+
+//go:generate echo $GOPACKAGE
+-- generate/env_pwd.go --
+package p
+
+//go:generate echo $PWD
diff --git a/src/cmd/go/testdata/script/generate_bad_imports.txt b/src/cmd/go/testdata/script/generate_bad_imports.txt
new file mode 100644
index 0000000..3da391e
--- /dev/null
+++ b/src/cmd/go/testdata/script/generate_bad_imports.txt
@@ -0,0 +1,15 @@
+[GOOS:windows] skip # skip because windows has no echo command
+
+go generate gencycle
+stdout 'hello world' # check go generate gencycle ran the generator
+
+-- go.mod --
+module gencycle
+
+go 1.16
+-- gencycle.go --
+//go:generate echo hello world
+
+package gencycle
+
+import _ "gencycle"
diff --git a/src/cmd/go/testdata/script/generate_env.txt b/src/cmd/go/testdata/script/generate_env.txt
new file mode 100644
index 0000000..cb76d30
--- /dev/null
+++ b/src/cmd/go/testdata/script/generate_env.txt
@@ -0,0 +1,32 @@
+# Install an env command because Windows and plan9 don't have it.
+env GOBIN=$WORK/tmp/bin
+go install env.go
+[GOOS:plan9] env path=$GOBIN${:}$path
+[!GOOS:plan9] env PATH=$GOBIN${:}$PATH
+
+# Test generators have access to the environment
+go generate ./printenv.go
+stdout '^GOARCH='$GOARCH
+stdout '^GOOS='$GOOS
+stdout '^GOFILE='
+stdout '^GOLINE='
+stdout '^GOPACKAGE='
+stdout '^DOLLAR='
+
+-- env.go --
+package main
+
+import (
+ "fmt"
+ "os"
+)
+
+func main() {
+ for _, v := range os.Environ() {
+ fmt.Println(v)
+ }
+}
+-- printenv.go --
+package main
+
+//go:generate env \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/generate_goroot_PATH.txt b/src/cmd/go/testdata/script/generate_goroot_PATH.txt
new file mode 100644
index 0000000..24591f0
--- /dev/null
+++ b/src/cmd/go/testdata/script/generate_goroot_PATH.txt
@@ -0,0 +1,38 @@
+# https://go.dev/issue/51473: to avoid the need for generators to rely on
+# runtime.GOROOT, 'go generate' should run the test with its own GOROOT/bin
+# at the beginning of $PATH.
+
+[short] skip
+
+[!GOOS:plan9] env PATH=
+[GOOS:plan9] env path=
+go generate .
+
+[!GOOS:plan9] env PATH=$WORK${/}bin
+[GOOS:plan9] env path=$WORK${/}bin
+go generate .
+
+-- go.mod --
+module example
+
+go 1.19
+-- main.go --
+//go:generate go run .
+
+package main
+
+import (
+ "fmt"
+ "os"
+ "os/exec"
+)
+
+func main() {
+ _, err := exec.LookPath("go")
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ }
+}
+-- $WORK/bin/README.txt --
+This directory contains no executables.
diff --git a/src/cmd/go/testdata/script/generate_invalid.txt b/src/cmd/go/testdata/script/generate_invalid.txt
new file mode 100644
index 0000000..3bede32
--- /dev/null
+++ b/src/cmd/go/testdata/script/generate_invalid.txt
@@ -0,0 +1,208 @@
+[short] skip
+
+# Install an echo command because Windows doesn't have it.
+env GOBIN=$WORK/tmp/bin
+go install echo.go
+env PATH=$GOBIN${:}$PATH
+
+# Test go generate for directory with no go files
+! go generate ./nogo
+! stdout 'Fail'
+stderr 'no Go files'
+
+# Test go generate for module which doesn't exist should fail
+! go generate foo.bar/nothing
+stderr 'no required module provides package foo.bar/nothing'
+
+# Test go generate for package where all .go files are excluded by build
+# constraints
+go generate -v ./excluded
+! stdout 'Fail'
+! stderr 'go' # -v shouldn't list any files
+
+# Test go generate for "package" with no package clause in any file
+go generate ./nopkg
+stdout 'Success a'
+! stdout 'Fail'
+
+# Test go generate for package with inconsistent package clauses
+# $GOPACKAGE should depend on each file's package clause
+go generate ./inconsistent
+stdout 'Success a'
+stdout 'Success b'
+stdout -count=2 'Success c'
+! stdout 'Fail'
+
+# Test go generate for syntax errors before and after package clauses
+go generate ./syntax
+stdout 'Success a'
+stdout 'Success b'
+! stdout 'Fail'
+
+# Test go generate for files importing non-existent packages
+go generate ./importerr
+stdout 'Success a'
+stdout 'Success b'
+stdout 'Success c'
+
+-- echo.go --
+package main
+
+import (
+ "fmt"
+ "os"
+ "strings"
+)
+
+func main() {
+ fmt.Println(strings.Join(os.Args[1:], " "))
+ fmt.Println()
+}
+
+-- go.mod --
+module m
+
+go 1.16
+-- nogo/foo.txt --
+Text file in a directory without go files.
+Go generate should ignore this directory.
+//go:generate echo Fail nogo
+
+-- excluded/a.go --
+// Include a build tag that go generate should exclude.
+// Go generate should ignore this file.
+
+// +build a
+
+//go:generate echo Fail a
+
+package excluded
+
+-- excluded/b.go --
+// Include a build tag that go generate should exclude.
+// Go generate should ignore this file.
+
+//go:generate echo Fail b
+
+// +build b
+
+package excluded
+
+
+-- nopkg/a.go --
+// Go file with package clause after comment.
+// Go generate should process this file.
+
+/* Pre-comment */ package nopkg
+//go:generate echo Success a
+
+-- nopkg/b.go --
+// Go file with commented package clause.
+// Go generate should ignore this file.
+
+//package nopkg
+
+//go:generate echo Fail b
+
+-- nopkg/c.go --
+// Go file with package clause inside multiline comment.
+// Go generate should ignore this file.
+
+/*
+package nopkg
+*/
+
+//go:generate echo Fail c
+
+-- nopkg/d.go --
+// Go file with package clause inside raw string literal.
+// Go generate should ignore this file.
+
+const foo = `
+package nopkg
+`
+//go:generate echo Fail d
+
+-- nopkg/e.go --
+// Go file without package clause.
+// Go generate should ignore this file.
+
+//go:generate echo Fail e
+
+-- inconsistent/a.go --
+// Valid go file with inconsistent package name.
+// Go generate should process this file with GOPACKAGE=a
+
+package a
+//go:generate echo Success $GOPACKAGE
+
+-- inconsistent/b.go --
+// Valid go file with inconsistent package name.
+// Go generate should process this file with GOPACKAGE=b
+
+//go:generate echo Success $GOPACKAGE
+package b
+
+-- inconsistent/c.go --
+// Go file with two package clauses.
+// Go generate should process this file with GOPACKAGE=c
+
+//go:generate echo Success $GOPACKAGE
+package c
+// Invalid package clause, should be ignored:
+package cinvalid
+//go:generate echo Success $GOPACKAGE
+
+-- inconsistent/d.go --
+// Go file with invalid package name.
+// Go generate should ignore this file.
+
+package +d+
+//go:generate echo Fail $GOPACKAGE
+
+-- syntax/a.go --
+// Go file with syntax error after package clause.
+// Go generate should process this file.
+
+package syntax
+123
+//go:generate echo Success a
+
+-- syntax/b.go --
+// Go file with syntax error after package clause.
+// Go generate should process this file.
+
+package syntax; 123
+//go:generate echo Success b
+
+-- syntax/c.go --
+// Go file with syntax error before package clause.
+// Go generate should ignore this file.
+
+foo
+package syntax
+//go:generate echo Fail c
+
+-- importerr/a.go --
+// Go file which imports non-existing package.
+// Go generate should process this file.
+
+package importerr
+//go:generate echo Success a
+import "foo"
+
+-- importerr/b.go --
+// Go file which imports non-existing package.
+// Go generate should process this file.
+
+//go:generate echo Success b
+package importerr
+import "bar"
+
+-- importerr/c.go --
+// Go file which imports non-existing package.
+// Go generate should process this file.
+
+package importerr
+import "moo"
+//go:generate echo Success c
diff --git a/src/cmd/go/testdata/script/generate_workspace.txt b/src/cmd/go/testdata/script/generate_workspace.txt
new file mode 100644
index 0000000..5ba2393
--- /dev/null
+++ b/src/cmd/go/testdata/script/generate_workspace.txt
@@ -0,0 +1,27 @@
+# This is a regression test for Issue #56098: Go generate
+# wasn't initializing workspace mode
+
+[short] skip
+
+go generate ./mod
+cmp ./mod/got.txt want.txt
+
+-- go.work --
+go 1.22
+
+use ./mod
+-- mod/go.mod --
+module example.com/mod
+-- mod/gen.go --
+//go:generate go run gen.go got.txt
+
+package main
+
+import "os"
+
+func main() {
+ outfile := os.Args[1]
+ os.WriteFile(outfile, []byte("Hello World!\n"), 0644)
+}
+-- want.txt --
+Hello World! \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/get_404_meta.txt b/src/cmd/go/testdata/script/get_404_meta.txt
new file mode 100644
index 0000000..7665155
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_404_meta.txt
@@ -0,0 +1,15 @@
+# golang.org/issue/13037: 'go get' was not parsing <meta> tags in 404 served over HTTPS.
+
+[!net:bazil.org] skip
+[!git] skip
+
+env GONOSUMDB=bazil.org,github.com,golang.org
+env GO111MODULE=on
+env GOPROXY=direct
+go get bazil.org/fuse/fs/fstestutil
+
+
+-- go.mod --
+module m
+
+go 1.18
diff --git a/src/cmd/go/testdata/script/get_insecure.txt b/src/cmd/go/testdata/script/get_insecure.txt
new file mode 100644
index 0000000..f29ec2d
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_insecure.txt
@@ -0,0 +1,41 @@
+[!net:insecure.go-get-issue-15410.appspot.com] skip
+[!git] skip
+
+env PATH=$WORK/tmp/bin${:}$PATH
+go build -o $WORK/tmp/bin/ssh ssh.go
+
+# Modules: Set up
+env GOPATH=$WORK/m/gp
+mkdir $WORK/m
+cp module_file $WORK/m/go.mod
+cd $WORK/m
+env GO111MODULE=on
+env GOPROXY=''
+
+# Modules: Try go get -d of HTTP-only repo (should fail).
+! go get -d insecure.go-get-issue-15410.appspot.com/pkg/p
+
+# Modules: Try again with GOINSECURE (should succeed).
+env GOINSECURE=insecure.go-get-issue-15410.appspot.com
+env GONOSUMDB=insecure.go-get-issue-15410.appspot.com
+go get -d insecure.go-get-issue-15410.appspot.com/pkg/p
+
+# Modules: Try updating without GOINSECURE (should fail).
+env GOINSECURE=''
+env GONOSUMDB=''
+! go get -d -u -f insecure.go-get-issue-15410.appspot.com/pkg/p
+
+go list -m ...
+stdout 'insecure.go-get-issue'
+
+-- ssh.go --
+// stub out uses of ssh by go get
+package main
+
+import "os"
+
+func main() {
+ os.Exit(1)
+}
+-- module_file --
+module m
diff --git a/src/cmd/go/testdata/script/get_insecure_no_longer_supported.txt b/src/cmd/go/testdata/script/get_insecure_no_longer_supported.txt
new file mode 100644
index 0000000..00bf32f
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_insecure_no_longer_supported.txt
@@ -0,0 +1,13 @@
+# GOPATH: Set up
+env GO111MODULE=off
+
+# GOPATH: Fetch with insecure, should error
+! go get -insecure test
+stderr 'go: -insecure flag is no longer supported; use GOINSECURE instead'
+
+# Modules: Set up
+env GO111MODULE=on
+
+# Modules: Fetch with insecure, should error
+! go get -insecure test
+stderr 'go: -insecure flag is no longer supported; use GOINSECURE instead'
diff --git a/src/cmd/go/testdata/script/get_issue53955.txt b/src/cmd/go/testdata/script/get_issue53955.txt
new file mode 100644
index 0000000..685c6fa
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_issue53955.txt
@@ -0,0 +1,79 @@
+# Regression test for https://go.dev/issue/53955.
+# New remote tags were erroneously added to the local clone of a repo
+# only *after* extracting version information for a locally-cached commit,
+# causing the version information to have incomplete Tags and Version fields.
+
+[short] skip 'constructs a local git repo'
+[!git] skip
+[!net:github.com] skip 'does not actually use github.com because of insteadOf, but silence network check just in case'
+
+# Redirect git to a test-specific .gitconfig.
+# GIT_CONFIG_GLOBAL suffices for git 2.32.0 and newer.
+# For older git versions we also set $HOME.
+env GIT_CONFIG_GLOBAL=$WORK${/}home${/}gopher${/}.gitconfig
+env HOME=$WORK${/}home${/}gopher
+exec git config --global --show-origin user.name
+stdout 'Go Gopher'
+
+# Inject a local repo in place of a remote one, so that we can
+# add commits to the repo partway through the test.
+env GIT_ALLOW_PROTOCOL=file
+env GOPRIVATE=github.com/golang/issue53955
+
+[!GOOS:windows] exec git config --global 'url.file://'$WORK'/repo.insteadOf' 'https://github.com/golang/issue53955'
+[GOOS:windows] exec git config --global 'url.file:///'$WORK'/repo.insteadOf' 'https://github.com/golang/issue53955'
+
+cd $WORK/repo
+
+env GIT_AUTHOR_NAME='Go Gopher'
+env GIT_AUTHOR_EMAIL='gopher@golang.org'
+env GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME
+env GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL
+
+exec git init
+
+env GIT_COMMITTER_DATE=2022-07-19T11:07:00-04:00
+env GIT_AUTHOR_DATE=2022-07-19T11:07:00-04:00
+exec git add go.mod issue53955.go
+exec git commit -m 'initial commit'
+exec git branch -m main
+exec git tag v1.0.9
+
+env GIT_COMMITTER_DATE=2022-07-19T11:07:01-04:00
+env GIT_AUTHOR_DATE=2022-07-19T11:07:01-04:00
+exec git add extra.go
+exec git commit -m 'next commit'
+exec git show-ref --tags --heads
+cmp stdout $WORK/.git-refs-1
+
+cd $WORK/m
+go get -x github.com/golang/issue53955@2cb3d49f
+stderr '^go: added github.com/golang/issue53955 v1.0.10-0.20220719150701-2cb3d49f8874$'
+
+cd $WORK/repo
+exec git tag v1.0.10
+
+cd $WORK/m
+go get -x github.com/golang/issue53955@v1.0.10
+! stderr 'v1\.0\.10 is not a tag'
+stderr '^go: upgraded github.com/golang/issue53955 v.* => v1\.0\.10$'
+
+-- $WORK/repo/go.mod --
+module github.com/golang/issue53955
+
+go 1.18
+-- $WORK/repo/issue53955.go --
+package issue53955
+-- $WORK/repo/extra.go --
+package issue53955
+-- $WORK/.git-refs-1 --
+2cb3d49f8874b9362ed0ddd2a6512e4108bbf6b1 refs/heads/main
+050526ebf5883191e990529eb3cc9345abaf838c refs/tags/v1.0.9
+-- $WORK/m/go.mod --
+module m
+
+go 1.18
+-- $WORK/home/gopher/.gitconfig --
+[user]
+ name = Go Gopher
+ email = gopher@golang.org
diff --git a/src/cmd/go/testdata/script/go_badcmd.txt b/src/cmd/go/testdata/script/go_badcmd.txt
new file mode 100644
index 0000000..661375a
--- /dev/null
+++ b/src/cmd/go/testdata/script/go_badcmd.txt
@@ -0,0 +1,2 @@
+! go asdf
+stderr '^go asdf: unknown command'
diff --git a/src/cmd/go/testdata/script/go_version.txt b/src/cmd/go/testdata/script/go_version.txt
new file mode 100644
index 0000000..1a787e1
--- /dev/null
+++ b/src/cmd/go/testdata/script/go_version.txt
@@ -0,0 +1,9 @@
+# test that go version doesn't panic on non-go binaries
+# See Issue #49181
+
+[exec:/bin/true] cp /bin/true true
+[exec:C:\windows\system32\help.exe] cp C:\windows\system32\help.exe help.exe
+
+go version -m .
+! stdout .
+! stderr .
diff --git a/src/cmd/go/testdata/script/godebug_default.txt b/src/cmd/go/testdata/script/godebug_default.txt
new file mode 100644
index 0000000..5bb8cac
--- /dev/null
+++ b/src/cmd/go/testdata/script/godebug_default.txt
@@ -0,0 +1,114 @@
+env GO111MODULE=on
+env GOTRACEBACK=single
+
+# Go 1.21 work module should leave panicnil with an implicit default.
+cp go.mod.21 go.mod
+go list -f '{{.Module.GoVersion}} {{.DefaultGODEBUG}}'
+! stdout panicnil
+stdout randautoseed=0
+
+# Go 1.21 work module should NOT set panicnil=1 in Go 1.20 dependency.
+cp go.mod.21 go.mod
+go list -f '{{.Module.GoVersion}} {{.DefaultGODEBUG}}' q
+! stdout panicnil=1
+! stdout randautoseed
+
+go mod download rsc.io/panicnil # for go.sum
+go list -f '{{.Module.GoVersion}} {{.DefaultGODEBUG}}' rsc.io/panicnil
+! stdout panicnil=1
+! stdout randautoseed
+
+# Go 1.20 work module should set panicnil=1.
+cp go.mod.20 go.mod
+go list -f '{{.Module.GoVersion}} {{.DefaultGODEBUG}}'
+stdout panicnil=1
+stdout randautoseed=0
+
+# Go 1.20 work module should set panicnil=1 in Go 1.20 dependency.
+cp go.mod.20 go.mod
+go list -f '{{.Module.GoVersion}} {{.DefaultGODEBUG}}' q
+stdout panicnil=1
+! stdout randautoseed
+
+# Go 1.21 workspace should leave panicnil with an implicit default.
+cat q/go.mod
+cp go.work.21 go.work
+go list -f '{{.Module.GoVersion}} {{.DefaultGODEBUG}}'
+! stdout panicnil
+stdout randautoseed=0
+rm go.work
+
+# Go 1.20 workspace with Go 1.21 module cannot happen.
+cp go.work.20 go.work
+cp go.mod.21 go.mod
+! go list -f '{{.Module.GoVersion}} {{.DefaultGODEBUG}}'
+stderr 'go: module . listed in go.work file requires go >= 1.21'
+rm go.work
+
+[short] skip
+
+# Programs in Go 1.21 work module should trigger run-time error.
+cp go.mod.21 go.mod
+! go run .
+stderr 'panic: panic called with nil argument'
+
+! go run rsc.io/panicnil
+stderr 'panic: panic called with nil argument'
+
+# Programs in Go 1.20 work module use old panic nil behavior.
+cp go.mod.20 go.mod
+! go run .
+stderr 'panic: nil'
+
+! go run rsc.io/panicnil
+stderr 'panic: nil'
+
+# Programs in no module at all should use their go.mod file.
+rm go.mod
+! go run rsc.io/panicnil@v1.0.0
+stderr 'panic: nil'
+
+rm go.mod
+! go run rsc.io/panicnil@v1.1.0
+stderr 'panic: panic called with nil argument'
+
+-- go.work.21 --
+go 1.21
+use .
+use ./q
+
+-- go.work.20 --
+go 1.20
+use .
+use ./q
+
+-- go.mod.21 --
+go 1.21
+module m
+require q v1.0.0
+replace q => ./q
+require rsc.io/panicnil v1.0.0
+
+-- go.mod.20 --
+go 1.20
+module m
+require q v1.0.0
+replace q => ./q
+require rsc.io/panicnil v1.0.0
+
+-- p.go --
+//go:debug randautoseed=0
+
+package main
+
+func main() {
+ panic(nil)
+}
+
+-- q/go.mod --
+go 1.20
+module q
+
+-- q/q.go --
+package main
+func main() {}
diff --git a/src/cmd/go/testdata/script/godebug_unknown.txt b/src/cmd/go/testdata/script/godebug_unknown.txt
new file mode 100644
index 0000000..57dacbc
--- /dev/null
+++ b/src/cmd/go/testdata/script/godebug_unknown.txt
@@ -0,0 +1,9 @@
+! go build
+stderr 'p.go:1:1: invalid //go:debug: unknown //go:debug setting "x"'
+
+-- go.mod --
+module m
+-- p.go --
+//go:debug x=y
+package main
+func main() {}
diff --git a/src/cmd/go/testdata/script/goflags.txt b/src/cmd/go/testdata/script/goflags.txt
new file mode 100644
index 0000000..1120860
--- /dev/null
+++ b/src/cmd/go/testdata/script/goflags.txt
@@ -0,0 +1,64 @@
+env GO111MODULE=off
+
+# GOFLAGS sets flags for commands
+
+env GOFLAGS='-e -f={{.Dir}} --test.benchtime=1s -count=10'
+go list asdfasdfasdf # succeeds because of -e
+go list runtime
+stdout '[\\/]runtime$'
+
+env GOFLAGS=-race OLDGOARCH=$GOARCH OLDGOOS=$GOOS GOARCH=386 GOOS=linux
+! go list runtime
+stderr 'race is not supported on linux/386'
+
+env GOARCH=$OLDGOARCH GOOS=$OLDGOOS
+
+# go env succeeds even though -f={{.Dir}} is inappropriate
+go env
+
+# bad flags are diagnosed
+env GOFLAGS=-typoflag
+! go list runtime
+stderr 'unknown flag -typoflag'
+
+env GOFLAGS=-
+! go list runtime
+stderr '^go: parsing \$GOFLAGS: non-flag "-"'
+
+env GOFLAGS=--
+! go list runtime
+stderr '^go: parsing \$GOFLAGS: non-flag "--"'
+
+env GOFLAGS=---oops
+! go list runtime
+stderr '^go: parsing \$GOFLAGS: non-flag "---oops"'
+
+env GOFLAGS=-=noname
+! go list runtime
+stderr '^go: parsing \$GOFLAGS: non-flag "-=noname"'
+
+env GOFLAGS=-f
+! go list runtime
+stderr '^go: flag needs an argument: -f \(from (\$GOFLAGS|%GOFLAGS%)\)$'
+
+env GOFLAGS=-e=asdf
+! go list runtime
+stderr '^go: invalid boolean value \"asdf\" for flag -e \(from (\$GOFLAGS|%GOFLAGS%)\)'
+
+# except in go bug (untested) and go env
+go env
+stdout GOFLAGS
+
+# Flags listed in GOFLAGS should be safe to duplicate on the command line.
+env GOFLAGS=-tags=magic
+go list -tags=magic
+go test -tags=magic -c -o $devnull
+go vet -tags=magic
+
+# GOFLAGS uses the same quoting rules (quoted.Split) as the rest of
+# the go command env variables
+env GOFLAGS='"-tags=magic wizardry"'
+go list
+
+-- foo_test.go --
+package foo
diff --git a/src/cmd/go/testdata/script/goline_order.txt b/src/cmd/go/testdata/script/goline_order.txt
new file mode 100644
index 0000000..6212cd6
--- /dev/null
+++ b/src/cmd/go/testdata/script/goline_order.txt
@@ -0,0 +1,74 @@
+# Check that go lines are always >= go lines of dependencies.
+
+# Using too old a release cannot even complete module load.
+env TESTGO_VERSION=go1.21.1
+env TESTGO_VERSION_SWITCH=switch
+cp go.mod go.mod.orig
+
+# If the offending module is not imported, it's not detected.
+go list
+cmp go.mod go.mod.orig
+
+# Adding the import produces the error.
+# Maybe this should auto-switch, but it requires more plumbing to get this error through,
+# and it's a misconfigured system that should not arise in practice, so not switching is fine.
+! go list -deps -tags usem1
+cmp go.mod go.mod.orig
+stderr '^go: module ./m1 requires go >= 1.21.2 \(running go 1.21.1\)$'
+
+# go get go@1.21.2 fixes the error.
+cp go.mod.orig go.mod
+go get go@1.21.2
+go list -deps -tags usem1
+
+# go get -tags usem1 fixes the error.
+cp go.mod.orig go.mod
+go get -tags usem1
+go list -deps -tags usem1
+
+# go get fixes the error.
+cp go.mod.orig go.mod
+go get
+go list -deps -tags usem1
+
+# Using a new enough release reports the error after module load and suggests 'go mod tidy'
+env TESTGO_VERSION=go1.21.2
+cp go.mod.orig go.mod
+! go list -deps -tags usem1
+stderr 'updates to go.mod needed'
+stderr 'go mod tidy'
+go mod tidy
+go list -deps -tags usem1
+
+# go get also works
+cp go.mod.orig go.mod
+! go list -deps -tags usem1
+stderr 'updates to go.mod needed'
+stderr 'go mod tidy'
+go get go@1.21.2
+go list -deps -tags usem1
+
+
+-- go.mod --
+module m
+go 1.21.1
+
+require m1 v0.0.1
+
+replace m1 => ./m1
+
+-- m1/go.mod --
+go 1.21.2
+
+-- p.go --
+//go:build usem1
+
+package p
+
+import _ "m1"
+
+-- p1.go --
+package p
+
+-- m1/p.go --
+package p
diff --git a/src/cmd/go/testdata/script/gopath_install.txt b/src/cmd/go/testdata/script/gopath_install.txt
new file mode 100644
index 0000000..6c572ea
--- /dev/null
+++ b/src/cmd/go/testdata/script/gopath_install.txt
@@ -0,0 +1,53 @@
+# Regression test for 'go install' locations in GOPATH mode.
+env GO111MODULE=off
+[short] skip
+
+# Without $GOBIN set, binaries should be installed into the GOPATH bin directory.
+env GOBIN=
+rm $GOPATH/bin/go-cmd-test$GOEXE
+go install go-cmd-test
+exists $GOPATH/bin/go-cmd-test$GOEXE
+
+# With $GOBIN set, binaries should be installed to $GOBIN.
+env GOBIN=$WORK/bin1
+mkdir -p $GOBIN
+go install go-cmd-test
+exists $GOBIN/go-cmd-test$GOEXE
+
+# Issue 11065: installing to the current directory should create an executable.
+cd go-cmd-test
+env GOBIN=$PWD
+go install
+exists ./go-cmd-test$GOEXE
+cd ..
+
+# Without $GOBIN set, installing a program outside $GOPATH should fail
+# (there is nowhere to install it).
+env GOPATH= # reset to default ($HOME/go, which does not exist)
+env GOBIN=
+! go install go-cmd-test/helloworld.go
+stderr '^go: no install location for \.go files listed on command line \(GOBIN not set\)$'
+
+# With $GOBIN set, should install there.
+env GOBIN=$WORK/bin1
+go install go-cmd-test/helloworld.go
+exists $GOBIN/helloworld$GOEXE
+
+# We can't assume that we can write to GOROOT, because it may not be writable.
+# However, we can check its install location using 'go list'.
+# cmd/fix should be installed to GOROOT/pkg, not GOPATH/bin.
+env GOPATH=$PWD
+go list -f '{{.Target}}' cmd/fix
+stdout $GOROOT'[/\\]pkg[/\\]tool[/\\]'$GOOS'_'$GOARCH'[/\\]fix'$GOEXE'$'
+
+# GOBIN should not affect toolchain install locations.
+env GOBIN=$WORK/bin1
+go list -f '{{.Target}}' cmd/fix
+stdout $GOROOT'[/\\]pkg[/\\]tool[/\\]'$GOOS'_'$GOARCH'[/\\]fix'$GOEXE'$'
+
+-- go-cmd-test/helloworld.go --
+package main
+
+func main() {
+ println("hello world")
+}
diff --git a/src/cmd/go/testdata/script/gopath_local.txt b/src/cmd/go/testdata/script/gopath_local.txt
new file mode 100644
index 0000000..efde0e7
--- /dev/null
+++ b/src/cmd/go/testdata/script/gopath_local.txt
@@ -0,0 +1,117 @@
+env GO111MODULE=off # Relative imports only work in GOPATH mode.
+
+[short] skip
+
+# Imports should be resolved relative to the source file.
+go build testdata/local/easy.go
+exec ./easy$GOEXE
+stdout '^easysub\.Hello'
+
+# Ignored files should be able to import the package built from
+# non-ignored files in the same directory.
+go build -o easysub$GOEXE testdata/local/easysub/main.go
+exec ./easysub$GOEXE
+stdout '^easysub\.Hello'
+
+# Files in relative-imported packages should be able to
+# use relative imports themselves.
+go build testdata/local/hard.go
+exec ./hard$GOEXE
+stdout '^sub\.Hello'
+
+# Explicit source files listed on the command line should not install without
+# GOBIN set, since individual source files aren't part of the containing GOPATH.
+! go install testdata/local/easy.go
+stderr '^go: no install location for \.go files listed on command line \(GOBIN not set\)$'
+
+[GOOS:windows] stop # Windows does not allow the ridiculous directory name we're about to use.
+
+env BAD_DIR_NAME='#$%:, &()*;<=>?\^{}'
+
+mkdir -p testdata/$BAD_DIR_NAME/easysub
+mkdir -p testdata/$BAD_DIR_NAME/sub/sub
+
+cp testdata/local/easy.go testdata/$BAD_DIR_NAME/easy.go
+cp testdata/local/easysub/easysub.go testdata/$BAD_DIR_NAME/easysub/easysub.go
+cp testdata/local/easysub/main.go testdata/$BAD_DIR_NAME/easysub/main.go
+cp testdata/local/hard.go testdata/$BAD_DIR_NAME/hard.go
+cp testdata/local/sub/sub.go testdata/$BAD_DIR_NAME/sub/sub.go
+cp testdata/local/sub/sub/subsub.go testdata/$BAD_DIR_NAME/sub/sub/subsub.go
+
+# Imports should be resolved relative to the source file.
+go build testdata/$BAD_DIR_NAME/easy.go
+exec ./easy$GOEXE
+stdout '^easysub\.Hello'
+
+# Ignored files should be able to import the package built from
+# non-ignored files in the same directory.
+go build -o easysub$GOEXE testdata/$BAD_DIR_NAME/easysub/main.go
+exec ./easysub$GOEXE
+stdout '^easysub\.Hello'
+
+# Files in relative-imported packages should be able to
+# use relative imports themselves.
+go build testdata/$BAD_DIR_NAME/hard.go
+exec ./hard$GOEXE
+stdout '^sub\.Hello'
+
+# Explicit source files listed on the command line should not install without
+# GOBIN set, since individual source files aren't part of the containing GOPATH.
+! go install testdata/$BAD_DIR_NAME/easy.go
+stderr '^go: no install location for \.go files listed on command line \(GOBIN not set\)$'
+
+-- testdata/local/easy.go --
+package main
+
+import "./easysub"
+
+func main() {
+ easysub.Hello()
+}
+-- testdata/local/easysub/easysub.go --
+package easysub
+
+import "fmt"
+
+func Hello() {
+ fmt.Println("easysub.Hello")
+}
+-- testdata/local/easysub/main.go --
+// +build ignore
+
+package main
+
+import "."
+
+func main() {
+ easysub.Hello()
+}
+-- testdata/local/hard.go --
+package main
+
+import "./sub"
+
+func main() {
+ sub.Hello()
+}
+-- testdata/local/sub/sub.go --
+package sub
+
+import (
+ "fmt"
+
+ subsub "./sub"
+)
+
+func Hello() {
+ fmt.Println("sub.Hello")
+ subsub.Hello()
+}
+-- testdata/local/sub/sub/subsub.go --
+package subsub
+
+import "fmt"
+
+func Hello() {
+ fmt.Println("subsub.Hello")
+}
diff --git a/src/cmd/go/testdata/script/gopath_paths.txt b/src/cmd/go/testdata/script/gopath_paths.txt
new file mode 100644
index 0000000..04265b1
--- /dev/null
+++ b/src/cmd/go/testdata/script/gopath_paths.txt
@@ -0,0 +1,43 @@
+# Regression test for GOPATH validation in GOPATH mode.
+env GO111MODULE=off
+
+env ORIG_GOPATH=$GOPATH
+
+# The literal path '.' in GOPATH should be rejected.
+env GOPATH=.
+! go build go-cmd-test/helloworld.go
+stderr 'GOPATH entry is relative'
+
+# It should still be rejected if the requested package can be
+# found using another entry.
+env GOPATH=${:}$ORIG_GOPATH${:}.
+! go build go-cmd-test
+stderr 'GOPATH entry is relative'
+
+# GOPATH cannot be a relative subdirectory of the working directory.
+env ORIG_GOPATH
+stdout 'ORIG_GOPATH='$WORK[/\\]gopath
+cd $WORK
+env GOPATH=gopath
+! go build gopath/src/go-cmd-test/helloworld.go
+stderr 'GOPATH entry is relative'
+
+# Blank paths in GOPATH should be rejected as relative (issue 21928).
+env GOPATH=' '${:}$ORIG_GOPATH
+! go build go-cmd-test
+stderr 'GOPATH entry is relative'
+
+[short] stop
+
+# Empty paths in GOPATH should be ignored (issue 21928).
+env GOPATH=${:}$ORIG_GOPATH
+env GOPATH
+go install go-cmd-test
+exists $ORIG_GOPATH/bin/go-cmd-test$GOEXE
+
+-- go-cmd-test/helloworld.go --
+package main
+
+func main() {
+ println("hello world")
+}
diff --git a/src/cmd/go/testdata/script/gopath_std_vendor.txt b/src/cmd/go/testdata/script/gopath_std_vendor.txt
new file mode 100644
index 0000000..4aaf46b
--- /dev/null
+++ b/src/cmd/go/testdata/script/gopath_std_vendor.txt
@@ -0,0 +1,44 @@
+env GO111MODULE=off
+
+[!compiler:gc] skip
+
+go list -f '{{.Dir}}' vendor/golang.org/x/net/http2/hpack
+stdout $GOPATH[/\\]src[/\\]vendor
+
+# A package importing 'net/http' should resolve its dependencies
+# to the package 'vendor/golang.org/x/net/http2/hpack' within GOROOT.
+cd importnethttp
+go list -deps -f '{{.ImportPath}} {{.Dir}}'
+stdout ^vendor/golang.org/x/net/http2/hpack
+stdout $GOROOT[/\\]src[/\\]vendor[/\\]golang.org[/\\]x[/\\]net[/\\]http2[/\\]hpack
+! stdout $GOPATH[/\\]src[/\\]vendor
+
+# In the presence of $GOPATH/src/vendor/golang.org/x/net/http2/hpack,
+# a package in GOPATH importing 'golang.org/x/net/http2/hpack' should
+# resolve its dependencies in GOPATH/src.
+cd ../issue16333
+go build .
+
+go list -deps -f '{{.ImportPath}} {{.Dir}}' .
+stdout $GOPATH[/\\]src[/\\]vendor[/\\]golang.org[/\\]x[/\\]net[/\\]http2[/\\]hpack
+! stdout $GOROOT[/\\]src[/\\]vendor
+
+go list -test -deps -f '{{.ImportPath}} {{.Dir}}' .
+stdout $GOPATH[/\\]src[/\\]vendor[/\\]golang.org[/\\]x[/\\]net[/\\]http2[/\\]hpack
+! stdout $GOROOT[/\\]src[/\\]vendor
+
+-- issue16333/issue16333.go --
+package vendoring17
+
+import _ "golang.org/x/net/http2/hpack"
+-- issue16333/issue16333_test.go --
+package vendoring17
+
+import _ "testing"
+import _ "golang.org/x/net/http2/hpack"
+-- importnethttp/http.go --
+package importnethttp
+
+import _ "net/http"
+-- $GOPATH/src/vendor/golang.org/x/net/http2/hpack/hpack.go --
+package hpack
diff --git a/src/cmd/go/testdata/script/gopath_vendor_dup_err.txt b/src/cmd/go/testdata/script/gopath_vendor_dup_err.txt
new file mode 100644
index 0000000..5f1e09a
--- /dev/null
+++ b/src/cmd/go/testdata/script/gopath_vendor_dup_err.txt
@@ -0,0 +1,24 @@
+env GO111MODULE=off
+
+# Issue 17119: Test more duplicate load errors.
+! go build dupload
+! stderr 'duplicate load|internal error'
+stderr 'dupload/vendor/p must be imported as p'
+
+-- dupload/dupload.go --
+package main
+
+import (
+ _ "dupload/p2"
+ _ "p"
+)
+
+func main() {}
+-- dupload/p/p.go --
+package p
+-- dupload/p2/p2.go --
+package p2
+
+import _ "dupload/vendor/p"
+-- dupload/vendor/p/p.go --
+package p
diff --git a/src/cmd/go/testdata/script/goroot_executable.txt b/src/cmd/go/testdata/script/goroot_executable.txt
new file mode 100644
index 0000000..e20dbd8
--- /dev/null
+++ b/src/cmd/go/testdata/script/goroot_executable.txt
@@ -0,0 +1,115 @@
+[compiler:gccgo] skip
+[short] skip 'builds and links another cmd/go'
+
+mkdir $WORK/new/bin
+
+# In this test, we are specifically checking the logic for deriving
+# the value of GOROOT from runtime.GOROOT.
+# GOROOT_FINAL changes the default behavior of runtime.GOROOT,
+# and will thus cause the test to fail if it is set when our
+# new cmd/go is built.
+env GOROOT_FINAL=
+
+# $GOROOT/bin/go is whatever the user has already installed
+# (using make.bash or similar). We can't make assumptions about what
+# options it may have been built with, such as -trimpath or GOROOT_FINAL.
+# Instead, we build a fresh copy of the binary with known settings.
+go build -o $WORK/new/bin/go$GOEXE cmd/go &
+go build -trimpath -o $WORK/bin/check$GOEXE check.go &
+wait
+
+env TESTGOROOT=$GOROOT
+env GOROOT=
+
+# Relocated Executable
+exec $WORK/bin/check$GOEXE $WORK/new/bin/go$GOEXE $TESTGOROOT
+
+# Relocated Tree:
+# If the binary is sitting in a bin dir next to ../pkg/tool, that counts as a GOROOT,
+# so it should find the new tree.
+mkdir $WORK/new/pkg/tool
+exec $WORK/bin/check$GOEXE $WORK/new/bin/go$GOEXE $WORK/new
+
+[!symlink] stop 'The rest of the test cases require symlinks'
+
+# Symlinked Executable:
+# With a symlink into go tree, we should still find the go tree.
+mkdir $WORK/other/bin
+symlink $WORK/other/bin/go$GOEXE -> $WORK/new/bin/go$GOEXE
+exec $WORK/bin/check$GOEXE $WORK/new/bin/go$GOEXE $WORK/new
+
+rm $WORK/new/pkg
+
+# Runtime GOROOT:
+# Binaries built in the new tree should report the
+# new tree when they call runtime.GOROOT.
+symlink $WORK/new/src -> $TESTGOROOT/src
+symlink $WORK/new/pkg -> $TESTGOROOT/pkg
+exec $WORK/new/bin/go$GOEXE run check_runtime_goroot.go $WORK/new
+
+-- check.go --
+package main
+
+import (
+ "fmt"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+)
+
+func main() {
+ exe := os.Args[1]
+ want := os.Args[2]
+ cmd := exec.Command(exe, "env", "GOROOT")
+ out, err := cmd.CombinedOutput()
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "%s env GOROOT: %v, %s\n", exe, err, out)
+ os.Exit(1)
+ }
+ goroot, err := filepath.EvalSymlinks(strings.TrimSpace(string(out)))
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ want, err = filepath.EvalSymlinks(want)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ if !strings.EqualFold(goroot, want) {
+ fmt.Fprintf(os.Stderr, "go env GOROOT:\nhave %s\nwant %s\n", goroot, want)
+ os.Exit(1)
+ }
+ fmt.Fprintf(os.Stderr, "go env GOROOT: %s\n", goroot)
+
+}
+-- check_runtime_goroot.go --
+package main
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "runtime"
+ "strings"
+)
+
+func main() {
+ goroot, err := filepath.EvalSymlinks(runtime.GOROOT())
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ want, err := filepath.EvalSymlinks(os.Args[1])
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ if !strings.EqualFold(goroot, want) {
+ fmt.Fprintf(os.Stderr, "go env GOROOT:\nhave %s\nwant %s\n", goroot, want)
+ os.Exit(1)
+ }
+ fmt.Fprintf(os.Stderr, "go env GOROOT: %s\n", goroot)
+
+}
diff --git a/src/cmd/go/testdata/script/goroot_executable_trimpath.txt b/src/cmd/go/testdata/script/goroot_executable_trimpath.txt
new file mode 100644
index 0000000..a3f0c39
--- /dev/null
+++ b/src/cmd/go/testdata/script/goroot_executable_trimpath.txt
@@ -0,0 +1,101 @@
+# Regression test for https://go.dev/issue/62119:
+# A 'go' command cross-compiled with a different GOHOSTOS
+# should be able to locate its GOROOT using os.Executable.
+#
+# (This also tests a 'go' command built with -trimpath
+# that is not cross-compiled, since we need to build that
+# configuration for the test anyway.)
+
+[short] skip 'builds and links another cmd/go'
+
+mkdir $WORK/new/bin
+mkdir $WORK/new/bin/${GOOS}_${GOARCH}
+
+# In this test, we are specifically checking the logic for deriving
+# the value of GOROOT from os.Executable when runtime.GOROOT is
+# trimmed away.
+# GOROOT_FINAL changes the default behavior of runtime.GOROOT,
+# so we explicitly clear it to remove it as a confounding variable.
+env GOROOT_FINAL=
+
+# $GOROOT/bin/go is whatever the user has already installed
+# (using make.bash or similar). We can't make assumptions about what
+# options it may have been built with, such as -trimpath or GOROOT_FINAL.
+# Instead, we build a fresh copy of the binary with known settings.
+go build -trimpath -o $WORK/new/bin/go$GOEXE cmd/go &
+go build -trimpath -o $WORK/bin/check$GOEXE check.go &
+wait
+
+env TESTGOROOT=$GOROOT
+env GOROOT=
+
+# Unset GOPATH and any variables that its default may be derived from,
+# so that we can check for a spurious warning.
+env GOPATH=
+env HOME=''
+env USERPROFILE=''
+env home=''
+
+# Relocated Executable
+# Since we built with -trimpath and the binary isn't installed in a
+# normal-looking GOROOT, this command should fail.
+
+! exec $WORK/new/bin/go$GOEXE env GOROOT
+stderr '^go: cannot find GOROOT directory: ''go'' binary is trimmed and GOROOT is not set$'
+! stderr 'GOPATH set to GOROOT'
+
+# Cross-compiled binaries in cmd are installed to a ${GOOS}_${GOARCH} subdirectory,
+# so we also want to try a copy there.
+# (Note that the script engine's 'exec' engine already works around
+# https://go.dev/issue/22315, so we don't have to do that explicitly in the
+# 'check' program we use later.)
+cp $WORK/new/bin/go$GOEXE $WORK/new/bin/${GOOS}_${GOARCH}/go$GOEXE
+! exec $WORK/new/bin/${GOOS}_${GOARCH}/go$GOEXE env GOROOT
+stderr '^go: cannot find GOROOT directory: ''go'' binary is trimmed and GOROOT is not set$'
+! stderr 'GOPATH set to GOROOT'
+
+# Relocated Tree:
+# If the binary is sitting in a bin dir next to ../pkg/tool, that counts as a GOROOT,
+# so it should find the new tree.
+mkdir $WORK/new/pkg/tool
+exec $WORK/bin/check$GOEXE $WORK/new/bin/go$GOEXE $WORK/new
+exec $WORK/bin/check$GOEXE $WORK/new/bin/${GOOS}_${GOARCH}/go$GOEXE $WORK/new
+! stderr 'GOPATH set to GOROOT'
+
+-- check.go --
+package main
+
+import (
+ "fmt"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+)
+
+func main() {
+ exe := os.Args[1]
+ want := os.Args[2]
+ cmd := exec.Command(exe, "env", "GOROOT")
+ out, err := cmd.CombinedOutput()
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "%s env GOROOT: %v, %s\n", exe, err, out)
+ os.Exit(1)
+ }
+ goroot, err := filepath.EvalSymlinks(strings.TrimSpace(string(out)))
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ want, err = filepath.EvalSymlinks(want)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ if !strings.EqualFold(goroot, want) {
+ fmt.Fprintf(os.Stderr, "go env GOROOT:\nhave %s\nwant %s\n", goroot, want)
+ os.Exit(1)
+ }
+ fmt.Fprintf(os.Stderr, "go env GOROOT: %s\n", goroot)
+
+}
diff --git a/src/cmd/go/testdata/script/gotoolchain_local.txt b/src/cmd/go/testdata/script/gotoolchain_local.txt
new file mode 100644
index 0000000..db7e082
--- /dev/null
+++ b/src/cmd/go/testdata/script/gotoolchain_local.txt
@@ -0,0 +1,256 @@
+# This test uses the fake toolchain switch support in cmd/go/internal/toolchain.Switch
+# to exercise all the version selection logic without needing actual toolchains.
+# See gotoolchain_net.txt and gotoolchain_path.txt for tests of network and PATH toolchains.
+
+env TESTGO_VERSION=go1.500
+env TESTGO_VERSION_SWITCH=switch
+
+# GOTOOLCHAIN=auto runs default toolchain without a go.mod or go.work
+env GOTOOLCHAIN=auto
+go version
+stdout go1.500
+
+# GOTOOLCHAIN=path runs default toolchain without a go.mod or go.work
+env GOTOOLCHAIN=path
+go version
+stdout go1.500
+
+# GOTOOLCHAIN=asdf is a syntax error
+env GOTOOLCHAIN=asdf
+! go version
+stderr '^go: invalid GOTOOLCHAIN "asdf"$'
+
+# GOTOOLCHAIN=version is used directly.
+env GOTOOLCHAIN=go1.600
+go version
+stdout go1.600
+
+env GOTOOLCHAIN=go1.400
+go version
+stdout go1.400
+
+# GOTOOLCHAIN=version+auto sets a minimum.
+env GOTOOLCHAIN=go1.600+auto
+go version
+stdout go1.600
+
+env GOTOOLCHAIN=go1.400.0+auto
+go version
+stdout go1.400.0
+
+# GOTOOLCHAIN=version+path sets a minimum too.
+env GOTOOLCHAIN=go1.600+path
+go version
+stdout go1.600
+
+env GOTOOLCHAIN=go1.400+path
+go version
+stdout go1.400
+
+# Create a go.mod file and test interactions with auto and path.
+
+# GOTOOLCHAIN=auto uses go line if newer than local toolchain.
+env GOTOOLCHAIN=auto
+go mod init m
+go mod edit -go=1.700 -toolchain=none
+go version
+stdout 1.700
+
+go mod edit -go=1.300 -toolchain=none
+go version
+stdout 1.500 # local toolchain is newer
+
+go mod edit -go=1.700 -toolchain=go1.300
+go version
+stdout go1.700 # toolchain too old, ignored
+
+go mod edit -go=1.300 -toolchain=default
+go version
+stdout go1.500
+
+go mod edit -go=1.700 -toolchain=default
+go version
+stdout go1.500 # toolchain local is like GOTOOLCHAIN=local and wins
+! go build
+stderr '^go: go.mod requires go >= 1.700 \(running go 1.500; go.mod sets toolchain default\)'
+
+# GOTOOLCHAIN=path does the same.
+env GOTOOLCHAIN=path
+go mod edit -go=1.700 -toolchain=none
+go version
+stdout 1.700
+
+go mod edit -go=1.300 -toolchain=none
+go version
+stdout 1.500 # local toolchain is newer
+
+go mod edit -go=1.700 -toolchain=go1.300
+go version
+stdout go1.700 # toolchain too old, ignored
+
+go mod edit -go=1.300 -toolchain=default
+go version
+stdout go1.500
+
+go mod edit -go=1.700 -toolchain=default
+go version
+stdout go1.500 # toolchain default applies even if older than go line
+! go build
+stderr '^go: go.mod requires go >= 1.700 \(running go 1.500; GOTOOLCHAIN=path; go.mod sets toolchain default\)'
+
+# GOTOOLCHAIN=min+auto with toolchain default uses min, not local
+
+env GOTOOLCHAIN=go1.400+auto
+go mod edit -go=1.300 -toolchain=default
+go version
+stdout 1.400 # not 1.500 local toolchain
+
+env GOTOOLCHAIN=go1.600+auto
+go mod edit -go=1.300 -toolchain=default
+go version
+stdout 1.600 # not 1.500 local toolchain
+
+# GOTOOLCHAIN names can have -suffix
+env GOTOOLCHAIN=go1.800-bigcorp
+go version
+stdout go1.800-bigcorp
+
+env GOTOOLCHAIN=auto
+go mod edit -go=1.999 -toolchain=go1.800-bigcorp
+go version
+stdout go1.999
+
+go mod edit -go=1.777 -toolchain=go1.800-bigcorp
+go version
+stdout go1.800-bigcorp
+
+# go.work takes priority over go.mod
+go mod edit -go=1.700 -toolchain=go1.999-wrong
+go work init
+go work edit -go=1.400 -toolchain=go1.600-right
+go version
+stdout go1.600-right
+
+go work edit -go=1.400 -toolchain=default
+go version
+stdout go1.500
+
+# go.work misconfiguration does not break go work edit
+# ('go 1.600 / toolchain local' forces use of 1.500 which can't normally load that go.work; allow work edit to fix it.)
+go work edit -go=1.600 -toolchain=default
+go version
+stdout go1.500
+
+go work edit -toolchain=none
+go version
+stdout go1.600
+
+rm go.work
+
+# go.mod misconfiguration does not break go mod edit
+go mod edit -go=1.600 -toolchain=default
+go version
+stdout go1.500
+
+go mod edit -toolchain=none
+go version
+stdout go1.600
+
+# toolchain built with a custom version should know how it compares to others
+
+env TESTGO_VERSION=go1.500-bigcorp
+go mod edit -go=1.499 -toolchain=none
+go version
+stdout go1.500-bigcorp
+
+go mod edit -go=1.499 -toolchain=go1.499
+go version
+stdout go1.500-bigcorp
+
+go mod edit -go=1.500 -toolchain=none
+go version
+stdout go1.500-bigcorp
+
+go mod edit -go=1.500 -toolchain=go1.500
+go version
+stdout go1.500-bigcorp
+
+go mod edit -go=1.501 -toolchain=none
+go version
+stdout go1.501
+
+ # If toolchain > go, we must upgrade to the indicated toolchain (not just the go version).
+go mod edit -go=1.499 -toolchain=go1.501
+go version
+stdout go1.501
+
+env TESTGO_VERSION='go1.500 (bigcorp)'
+go mod edit -go=1.499 -toolchain=none
+go version
+stdout 'go1.500 \(bigcorp\)'
+
+go mod edit -go=1.500 -toolchain=none
+go version
+stdout 'go1.500 \(bigcorp\)'
+
+go mod edit -go=1.501 -toolchain=none
+go version
+stdout go1.501
+
+# go install m@v and go run m@v should ignore go.mod and use m@v
+env TESTGO_VERSION=go1.2.3
+go mod edit -go=1.999 -toolchain=go1.998
+
+! go install rsc.io/fortune/nonexist@v0.0.1
+stderr '^go: rsc.io/fortune@v0.0.1 requires go >= 1.21rc999; switching to go1.22.9$'
+stderr '^go: rsc.io/fortune/nonexist@v0.0.1: module rsc.io/fortune@v0.0.1 found, but does not contain package rsc.io/fortune/nonexist'
+
+! go run rsc.io/fortune/nonexist@v0.0.1
+stderr '^go: rsc.io/fortune@v0.0.1 requires go >= 1.21rc999; switching to go1.22.9$'
+stderr '^go: rsc.io/fortune/nonexist@v0.0.1: module rsc.io/fortune@v0.0.1 found, but does not contain package rsc.io/fortune/nonexist'
+
+# go install should handle unknown flags to find m@v
+! go install -unknownflag rsc.io/fortune/nonexist@v0.0.1
+stderr '^go: rsc.io/fortune@v0.0.1 requires go >= 1.21rc999; switching to go1.22.9$'
+stderr '^flag provided but not defined: -unknownflag'
+
+! go install -unknownflag arg rsc.io/fortune/nonexist@v0.0.1
+stderr '^go: rsc.io/fortune@v0.0.1 requires go >= 1.21rc999; switching to go1.22.9$'
+stderr '^flag provided but not defined: -unknownflag'
+
+# go run cannot handle unknown boolean flags
+! go run -unknownflag rsc.io/fortune/nonexist@v0.0.1
+! stderr switching
+stderr '^flag provided but not defined: -unknownflag'
+
+! go run -unknownflag oops rsc.io/fortune/nonexist@v0.0.1
+! stderr switching
+stderr '^flag provided but not defined: -unknownflag'
+
+# go run can handle unknown flag with argument.
+! go run -unknown=flag rsc.io/fortune/nonexist@v0.0.1
+stderr '^go: rsc.io/fortune@v0.0.1 requires go >= 1.21rc999; switching to go1.22.9$'
+stderr '^flag provided but not defined: -unknown'
+
+# go install m@v should handle queries
+! go install rsc.io/fortune/nonexist@v0.0
+stderr '^go: rsc.io/fortune@v0.0.1 requires go >= 1.21rc999; switching to go1.22.9$'
+stderr '^go: rsc.io/fortune/nonexist@v0.0: module rsc.io/fortune@v0.0 found \(v0.0.1\), but does not contain package rsc.io/fortune/nonexist'
+
+# go run m@v should handle queries
+! go install rsc.io/fortune/nonexist@v0
+stderr '^go: rsc.io/fortune@v0.0.1 requires go >= 1.21rc999; switching to go1.22.9$'
+stderr '^go: rsc.io/fortune/nonexist@v0: module rsc.io/fortune@v0 found \(v0.0.1\), but does not contain package rsc.io/fortune/nonexist'
+
+# go install m@v should use local toolchain if not upgrading
+! go install rsc.io/fortune/nonexist@v1
+! stderr go1.22.9
+! stderr switching
+stderr '^go: downloading rsc.io/fortune v1.0.0$'
+stderr '^go: rsc.io/fortune/nonexist@v1: module rsc.io/fortune@v1 found \(v1.0.0\), but does not contain package rsc.io/fortune/nonexist'
+
+# go run m@v should use local toolchain if not upgrading
+! go run rsc.io/fortune/nonexist@v1
+! stderr go1.22.9
+! stderr switching
+stderr '^go: rsc.io/fortune/nonexist@v1: module rsc.io/fortune@v1 found \(v1.0.0\), but does not contain package rsc.io/fortune/nonexist'
diff --git a/src/cmd/go/testdata/script/gotoolchain_loop.txt b/src/cmd/go/testdata/script/gotoolchain_loop.txt
new file mode 100644
index 0000000..a803d2e
--- /dev/null
+++ b/src/cmd/go/testdata/script/gotoolchain_loop.txt
@@ -0,0 +1,65 @@
+env GOTOOLCHAIN=auto
+env TESTGO_VERSION=go1.21.1
+
+# Basic switch should work.
+env TESTGO_VERSION_SWITCH=switch
+go version
+stdout go1.21.99
+
+# Toolchain target mismatch should be detected.
+env TESTGO_VERSION_SWITCH=mismatch
+! go version
+stderr '^go: toolchain go1.21.1 invoked to provide go1.21.99$'
+
+# Toolchain loop should be detected.
+env TESTGO_VERSION_SWITCH=loop
+! go version
+stderr -count=10 '^go: switching from go1.21.1 to go1.21.99 \[depth 9[0-9]\]$'
+stderr -count=1 '^go: switching from go1.21.1 to go1.21.99 \[depth 100\]$'
+stderr '^go: too many toolchain switches$'
+
+[short] skip
+
+# Internal env vars should not leak to go test or go run.
+env TESTGO_VERSION_SWITCH=switch
+go version
+stdout go1.21.99
+go test
+stdout clean
+go run .
+stdout clean
+
+-- go.mod --
+module m
+go 1.21.99
+
+-- m_test.go --
+package main
+
+import "testing"
+
+func TestEnv(t *testing.T) {
+ // the check is in func init in m.go
+}
+
+-- m.go --
+package main
+
+import "os"
+
+func init() {
+ envs := []string{
+ "GOTOOLCHAIN_INTERNAL_SWITCH_COUNT",
+ "GOTOOLCHAIN_INTERNAL_SWITCH_VERSION",
+ }
+ for _, e := range envs {
+ if v := os.Getenv(e); v != "" {
+ panic("$"+e+"="+v)
+ }
+ }
+ os.Stdout.WriteString("clean\n")
+}
+
+func main() {
+}
+
diff --git a/src/cmd/go/testdata/script/gotoolchain_modcmds.txt b/src/cmd/go/testdata/script/gotoolchain_modcmds.txt
new file mode 100644
index 0000000..1edd6d8
--- /dev/null
+++ b/src/cmd/go/testdata/script/gotoolchain_modcmds.txt
@@ -0,0 +1,45 @@
+env TESTGO_VERSION=go1.21.0
+env TESTGO_VERSION_SWITCH=switch
+
+# If the main module's go.mod file lists a version lower than the version
+# required by its dependencies, the commands that fetch and diagnose the module
+# graph (such as 'go mod graph' and 'go mod verify') should fail explicitly:
+# they can't interpret the graph themselves, and they aren't allowed to update
+# the go.mod file to record a specific, stable toolchain version that can.
+
+! go mod verify
+stderr '^go: rsc.io/future@v1.0.0: module rsc.io/future@v1.0.0 requires go >= 1.999 \(running go 1.21.0\)'
+
+! go mod graph
+stderr '^go: rsc.io/future@v1.0.0: module rsc.io/future@v1.0.0 requires go >= 1.999 \(running go 1.21.0\)'
+
+# TODO(#64008): 'go mod download' without arguments should fail too.
+
+
+# 'go get' should update the main module's go.mod file to a version compatible with the
+# go version required for rsc.io/future, not fail.
+go get .
+stderr '^go: module rsc.io/future@v1.0.0 requires go >= 1.999; switching to go1.999testmod$'
+stderr '^go: upgraded go 1.21 => 1.999$'
+stderr '^go: added toolchain go1.999testmod$'
+
+
+# Now, the various 'go mod' subcommands should succeed.
+
+go mod download
+
+go mod verify
+
+go mod graph
+
+
+-- go.mod --
+module example
+
+go 1.21
+
+require rsc.io/future v1.0.0
+-- example.go --
+package example
+
+import _ "rsc.io/future"
diff --git a/src/cmd/go/testdata/script/gotoolchain_net.txt b/src/cmd/go/testdata/script/gotoolchain_net.txt
new file mode 100644
index 0000000..1d6473c
--- /dev/null
+++ b/src/cmd/go/testdata/script/gotoolchain_net.txt
@@ -0,0 +1,70 @@
+# This test only checks that basic network lookups work.
+# The full test of toolchain version selection is in gotoolchain.txt.
+
+# This test is sensitive to "new" Go experiments, so
+# update the environment to remove any existing GOEXPERIMENT
+# setting, see #62016 for more on this.
+env GOEXPERIMENT=''
+
+env TESTGO_VERSION=go1.21actual
+
+# GOTOOLCHAIN from network, does not exist
+env GOTOOLCHAIN=go1.9999x
+! go version
+stderr 'go: download go1.9999x for .*: toolchain not available'
+
+# GOTOOLCHAIN from network
+[!exec:/bin/sh] stop 'the fake proxy serves shell scripts instead of binaries'
+env GOTOOLCHAIN=go1.999testmod
+go version
+stderr 'go: downloading go1.999testmod \(.*/.*\)'
+
+# GOTOOLCHAIN cached from network
+go version
+! stderr downloading
+stdout go1.999testmod
+
+# GOTOOLCHAIN with GOSUMDB enabled but at a bad URL should operate in cache and not try badurl
+env oldsumdb=$GOSUMDB
+env GOSUMDB=$oldsumdb' http://badurl'
+go version
+! stderr downloading
+stdout go1.999testmod
+
+# GOTOOLCHAIN with GOSUMB=off should fail, because it cannot access even the cached sumdb info
+# without the sumdb name.
+env GOSUMDB=off
+! go version
+stderr '^go: golang.org/toolchain@v0.0.1-go1.999testmod.[a-z0-9\-]*: verifying module: checksum database disabled by GOSUMDB=off$'
+
+# GOTOOLCHAIN with GOSUMDB enabled but at a bad URL should fail if cache is incomplete
+env GOSUMDB=$oldsumdb' http://badurl'
+rm $GOPATH/pkg/mod/cache/download/sumdb
+! go version
+! stderr downloading
+stderr 'panic: use of network' # test catches network access
+env GOSUMDB=$oldsumdb
+
+# Test a real GOTOOLCHAIN
+[short] skip
+[!net:golang.org] skip
+[!net:sum.golang.org] skip
+[!GOOS:darwin] [!GOOS:windows] [!GOOS:linux] skip
+[!GOARCH:amd64] [!GOARCH:arm64] skip
+
+env GOPROXY=
+[go-builder] env GOSUMDB=
+[!go-builder] env GOSUMDB=sum.golang.org # Set explicitly in case GOROOT/go.env is modified.
+env GOTOOLCHAIN=go1.20.1
+
+ # Avoid resolving a "go1.20.1" from the user's real $PATH.
+ # That would not only cause the "downloading go1.20.1" message
+ # to be suppressed, but may spuriously fail:
+ # golang.org/dl/go1.20.1 expects to find its GOROOT in $HOME/sdk,
+ # but the script environment sets HOME=/no-home.
+env PATH=
+env path=
+
+go version
+stderr '^go: downloading go1.20.1 '
+stdout go1.20.1
diff --git a/src/cmd/go/testdata/script/gotoolchain_path.txt b/src/cmd/go/testdata/script/gotoolchain_path.txt
new file mode 100644
index 0000000..9628348
--- /dev/null
+++ b/src/cmd/go/testdata/script/gotoolchain_path.txt
@@ -0,0 +1,86 @@
+# This test only checks that basic PATH lookups work.
+# The full test of toolchain version selection is in gotoolchain.txt.
+
+[short] skip
+
+env TESTGO_VERSION=go1.21pre3
+
+# Compile a fake toolchain to put in the path under various names.
+env GOTOOLCHAIN=
+mkdir $WORK/bin
+go build -o $WORK/bin/ ./fakego.go # adds .exe extension implicitly on Windows
+cp $WORK/bin/fakego$GOEXE $WORK/bin/go1.50.0$GOEXE
+
+[!GOOS:plan9] env PATH=$WORK/bin
+[GOOS:plan9] env path=$WORK/bin
+
+go version
+stdout go1.21pre3
+
+# GOTOOLCHAIN=go1.50.0
+env GOTOOLCHAIN=go1.50.0
+! go version
+stderr 'running go1.50.0 from PATH'
+
+# GOTOOLCHAIN=path with toolchain line
+env GOTOOLCHAIN=local
+go mod init m
+go mod edit -toolchain=go1.50.0
+grep go1.50.0 go.mod
+env GOTOOLCHAIN=path
+! go version
+stderr 'running go1.50.0 from PATH'
+
+# GOTOOLCHAIN=path with go line
+env GOTOOLCHAIN=local
+go mod edit -toolchain=none -go=1.50.0
+grep 'go 1.50.0' go.mod
+! grep toolchain go.mod
+env GOTOOLCHAIN=path
+! go version
+stderr 'running go1.50.0 from PATH'
+
+# GOTOOLCHAIN=auto with toolchain line
+env GOTOOLCHAIN=local
+go mod edit -toolchain=go1.50.0 -go=1.21
+grep 'go 1.21$' go.mod
+grep 'toolchain go1.50.0' go.mod
+env GOTOOLCHAIN=auto
+! go version
+stderr 'running go1.50.0 from PATH'
+
+# GOTOOLCHAIN=auto with go line
+env GOTOOLCHAIN=local
+go mod edit -toolchain=none -go=1.50.0
+grep 'go 1.50.0$' go.mod
+! grep toolchain go.mod
+env GOTOOLCHAIN=auto
+! go version
+stderr 'running go1.50.0 from PATH'
+
+# NewerToolchain should find Go 1.50.0.
+env GOTOOLCHAIN=local
+go mod edit -toolchain=none -go=1.22
+grep 'go 1.22$' go.mod
+! grep toolchain go.mod
+env GOTOOLCHAIN=path
+! go run rsc.io/fortune@v0.0.1
+stderr 'running go1.50.0 from PATH'
+
+-- fakego.go --
+package main
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "strings"
+)
+
+func main() {
+ exe, _ := os.Executable()
+ name := filepath.Base(exe)
+ name = strings.TrimSuffix(name, ".exe")
+ fmt.Fprintf(os.Stderr, "running %s from PATH\n", name)
+ os.Exit(1) // fail in case we are running this accidentally (like in "go mod edit")
+}
diff --git a/src/cmd/go/testdata/script/gotoolchain_version.txt b/src/cmd/go/testdata/script/gotoolchain_version.txt
new file mode 100644
index 0000000..e0736ff
--- /dev/null
+++ b/src/cmd/go/testdata/script/gotoolchain_version.txt
@@ -0,0 +1,22 @@
+[!net:proxy.golang.org] skip
+
+ # In the Go project's official release GOPROXY defaults to proxy.golang.org,
+ # but it may be changed in GOROOT/go.env (such as in third-party
+ # distributions).
+ #
+ # Make sure it is in use here, because the server for releases not served
+ # through the proxy (https://golang.org/toolchain?go-get=1) currently only
+ # serves the latest patch release for each of the supported stable releases.
+
+[go-builder] env GOPROXY=
+[!go-builder] env GOPROXY=https://proxy.golang.org
+
+go list -m -versions go
+stdout 1.20.1 # among others
+stdout 1.19rc2
+! stdout go1.20.1 # no go prefixes
+! stdout go1.19rc2
+
+go list -m -versions toolchain
+stdout go1.20.1 # among others
+stdout go1.19rc2
diff --git a/src/cmd/go/testdata/script/govcs.txt b/src/cmd/go/testdata/script/govcs.txt
new file mode 100644
index 0000000..876f606
--- /dev/null
+++ b/src/cmd/go/testdata/script/govcs.txt
@@ -0,0 +1,91 @@
+env GO111MODULE=on
+env proxy=$GOPROXY
+env GOPROXY=direct
+
+# GOVCS stops go get
+env GOVCS='*:none'
+! go get github.com/google/go-cmp
+stderr '^go: GOVCS disallows using git for public github.com/google/go-cmp; see ''go help vcs''$'
+env GOPRIVATE='github.com/google'
+! go get github.com/google/go-cmp
+stderr '^go: GOVCS disallows using git for private github.com/google/go-cmp; see ''go help vcs''$'
+
+# public pattern works
+env GOPRIVATE='github.com/google'
+env GOVCS='public:all,private:none'
+! go get github.com/google/go-cmp
+stderr '^go: GOVCS disallows using git for private github.com/google/go-cmp; see ''go help vcs''$'
+
+# private pattern works
+env GOPRIVATE='hubgit.com/google'
+env GOVCS='private:all,public:none'
+! go get github.com/google/go-cmp
+stderr '^go: GOVCS disallows using git for public github.com/google/go-cmp; see ''go help vcs''$'
+
+# other patterns work (for more patterns, see TestGOVCS)
+env GOPRIVATE=
+env GOVCS='github.com:svn|hg'
+! go get github.com/google/go-cmp
+stderr '^go: GOVCS disallows using git for public github.com/google/go-cmp; see ''go help vcs''$'
+env GOVCS='github.com/google/go-cmp/inner:git,github.com:svn|hg'
+! go get github.com/google/go-cmp
+stderr '^go: GOVCS disallows using git for public github.com/google/go-cmp; see ''go help vcs''$'
+
+# bad patterns are reported (for more bad patterns, see TestGOVCSErrors)
+env GOVCS='git'
+! go get github.com/google/go-cmp
+stderr '^go: github.com/google/go-cmp: malformed entry in GOVCS \(missing colon\): "git"$'
+
+env GOVCS=github.com:hg,github.com:git
+! go get github.com/google/go-cmp
+stderr '^go: github.com/google/go-cmp: unreachable pattern in GOVCS: "github.com:git" after "github.com:hg"$'
+
+# bad GOVCS patterns do not stop commands that do not need to check VCS
+go list
+env GOPROXY=$proxy
+go get rsc.io/quote # ok because used proxy
+env GOPROXY=direct
+
+# svn is disallowed by default
+env GOPRIVATE=
+env GOVCS=
+! go get rsc.io/nonexist.svn/hello
+stderr '^go: rsc.io/nonexist.svn/hello: GOVCS disallows using svn for public rsc.io/nonexist.svn; see ''go help vcs''$'
+
+# fossil is disallowed by default
+env GOPRIVATE=
+env GOVCS=
+! go get rsc.io/nonexist.fossil/hello
+stderr '^go: rsc.io/nonexist.fossil/hello: GOVCS disallows using fossil for public rsc.io/nonexist.fossil; see ''go help vcs''$'
+
+# bzr is disallowed by default
+env GOPRIVATE=
+env GOVCS=
+! go get rsc.io/nonexist.bzr/hello
+stderr '^go: rsc.io/nonexist.bzr/hello: GOVCS disallows using bzr for public rsc.io/nonexist.bzr; see ''go help vcs''$'
+
+# git is OK by default
+env GOVCS=
+env GONOSUMDB='*'
+[net:rsc.io] [git] [!short] go get rsc.io/sampler
+
+# hg is OK by default
+env GOVCS=
+env GONOSUMDB='*'
+[exec:hg] [!short] go get vcs-test.golang.org/go/custom-hg-hello
+
+# git can be disallowed
+env GOVCS=public:hg
+! go get rsc.io/nonexist.git/hello
+stderr '^go: rsc.io/nonexist.git/hello: GOVCS disallows using git for public rsc.io/nonexist.git; see ''go help vcs''$'
+
+# hg can be disallowed
+env GOVCS=public:git
+! go get rsc.io/nonexist.hg/hello
+stderr '^go: rsc.io/nonexist.hg/hello: GOVCS disallows using hg for public rsc.io/nonexist.hg; see ''go help vcs''$'
+
+-- go.mod --
+module m
+
+-- p.go --
+package p
diff --git a/src/cmd/go/testdata/script/help.txt b/src/cmd/go/testdata/script/help.txt
new file mode 100644
index 0000000..fb15e93
--- /dev/null
+++ b/src/cmd/go/testdata/script/help.txt
@@ -0,0 +1,51 @@
+env GO111MODULE=off
+
+# go help shows overview.
+go help
+stdout 'Go is a tool'
+stdout 'bug.*start a bug report'
+
+# go help bug shows usage for bug
+go help bug
+stdout 'usage: go bug'
+stdout 'bug report'
+
+# go bug help is an error (bug takes no arguments)
+! go bug help
+stderr 'bug takes no arguments'
+
+# go help mod shows mod subcommands
+go help mod
+stdout 'go mod <command>'
+stdout tidy
+
+# go help mod tidy explains tidy
+go help mod tidy
+stdout 'usage: go mod tidy'
+
+# go mod help tidy does too
+go mod help tidy
+stdout 'usage: go mod tidy'
+
+# go mod --help doesn't print help but at least suggests it.
+! go mod --help
+stderr 'Run ''go help mod'' for usage.'
+
+# Earlier versions of Go printed the same as 'go -h' here.
+# Also make sure we print the short help line.
+! go vet -h
+stderr 'usage: go vet .*'
+stderr 'Run ''go help vet'' for details.'
+stderr 'Run ''go tool vet help'' for a full list of flags and analyzers.'
+stderr 'Run ''go tool vet -help'' for an overview.'
+
+# Earlier versions of Go printed a large document here, instead of these two
+# lines.
+! go test -h
+stderr 'usage: go test'
+stderr 'Run ''go help test'' and ''go help testflag'' for details.'
+
+# go help get shows usage for get
+go help get
+stdout 'usage: go get'
+stdout 'specific module versions'
diff --git a/src/cmd/go/testdata/script/import_cycle.txt b/src/cmd/go/testdata/script/import_cycle.txt
new file mode 100644
index 0000000..901f43c
--- /dev/null
+++ b/src/cmd/go/testdata/script/import_cycle.txt
@@ -0,0 +1,12 @@
+env GO111MODULE=off
+
+! go build selfimport
+stderr -count=1 'import cycle not allowed'
+
+# 'go list' shouldn't hang forever.
+go list -e -json selfimport
+
+-- $GOPATH/src/selfimport/selfimport.go --
+package selfimport
+
+import "selfimport"
diff --git a/src/cmd/go/testdata/script/import_ignore.txt b/src/cmd/go/testdata/script/import_ignore.txt
new file mode 100644
index 0000000..83a39a0
--- /dev/null
+++ b/src/cmd/go/testdata/script/import_ignore.txt
@@ -0,0 +1,11 @@
+cp go.mod go.mod.orig
+go mod tidy
+cmp go.mod go.mod.orig
+
+-- go.mod --
+module m.test
+
+go 1.16
+-- .ignore.go --
+package p
+import _ "golang.org/x/mod/modfile" \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/import_main.txt b/src/cmd/go/testdata/script/import_main.txt
new file mode 100644
index 0000000..bc2cc4d
--- /dev/null
+++ b/src/cmd/go/testdata/script/import_main.txt
@@ -0,0 +1,114 @@
+env GO111MODULE=off
+
+# Test that you cannot import a main package.
+# See golang.org/issue/4210 and golang.org/issue/17475.
+
+[short] skip
+cd $WORK
+
+# Importing package main from that package main's test should work.
+go build x
+go test -c x
+
+# Importing package main from another package should fail.
+! go build p1
+stderr 'import "x" is a program, not an importable package'
+
+# ... even in that package's test.
+go build p2
+! go test -c p2
+stderr 'import "x" is a program, not an importable package'
+
+# ... even if that package's test is an xtest.
+go build p3
+! go test p3
+stderr 'import "x" is a program, not an importable package'
+
+# ... even if that package is a package main
+go build p4
+! go test -c p4
+stderr 'import "x" is a program, not an importable package'
+
+# ... even if that package is a package main using an xtest.
+go build p5
+! go test -c p5
+stderr 'import "x" is a program, not an importable package'
+
+-- x/main.go --
+package main
+
+var X int
+
+func main() {}
+-- x/main_test.go --
+package main_test
+
+import (
+ "testing"
+ xmain "x"
+)
+
+var _ = xmain.X
+
+func TestFoo(t *testing.T) {}
+-- p1/p.go --
+package p1
+
+import xmain "x"
+
+var _ = xmain.X
+-- p2/p.go --
+package p2
+-- p2/p_test.go --
+package p2
+
+import (
+ "testing"
+ xmain "x"
+)
+
+var _ = xmain.X
+
+func TestFoo(t *testing.T) {}
+-- p3/p.go --
+package p
+-- p3/p_test.go --
+package p_test
+
+import (
+ "testing"
+ xmain "x"
+)
+
+var _ = xmain.X
+
+func TestFoo(t *testing.T) {}
+-- p4/p.go --
+package main
+
+func main() {}
+-- p4/p_test.go --
+package main
+
+import (
+ "testing"
+ xmain "x"
+)
+
+var _ = xmain.X
+
+func TestFoo(t *testing.T) {}
+-- p5/p.go --
+package main
+func main() {}
+-- p5/p_test.go --
+package main_test
+
+import (
+ "testing"
+ xmain "x"
+)
+
+var _ = xmain.X
+
+func TestFoo(t *testing.T) {}
diff --git a/src/cmd/go/testdata/script/import_unix_tag.txt b/src/cmd/go/testdata/script/import_unix_tag.txt
new file mode 100644
index 0000000..b88ca1e
--- /dev/null
+++ b/src/cmd/go/testdata/script/import_unix_tag.txt
@@ -0,0 +1,32 @@
+# Regression test for https://go.dev/issue/54712: the "unix" build constraint
+# was not applied consistently during package loading.
+
+go list -x -f '{{if .Module}}{{.ImportPath}}{{end}}' -deps .
+stdout 'example.com/version'
+
+-- go.mod --
+module example
+
+go 1.19
+
+require example.com/version v1.1.0
+-- go.sum --
+example.com/version v1.1.0 h1:VdPnGmIF1NJrntStkxGrF3L/OfhaL567VzCjncGUgtM=
+example.com/version v1.1.0/go.mod h1:S7K9BnT4o5wT4PCczXPfWVzpjD4ud4e7AJMQJEgiu2Q=
+-- main_notunix.go --
+//go:build !(aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris)
+
+package main
+
+import _ "example.com/version"
+
+func main() {}
+
+-- main_unix.go --
+//go:build unix
+
+package main
+
+import _ "example.com/version"
+
+func main() {}
diff --git a/src/cmd/go/testdata/script/index.txt b/src/cmd/go/testdata/script/index.txt
new file mode 100644
index 0000000..6a2d13c
--- /dev/null
+++ b/src/cmd/go/testdata/script/index.txt
@@ -0,0 +1,6 @@
+# Check that standard library packages are cached.
+go list -json math # refresh cache
+env GODEBUG=gofsystrace=1,gofsystracelog=fsys.log
+go list -json math
+! grep math/abs.go fsys.log
+grep 'openIndexPackage .*[\\/]math$' fsys.log
diff --git a/src/cmd/go/testdata/script/install_cgo_excluded.txt b/src/cmd/go/testdata/script/install_cgo_excluded.txt
new file mode 100644
index 0000000..5a2b460
--- /dev/null
+++ b/src/cmd/go/testdata/script/install_cgo_excluded.txt
@@ -0,0 +1,15 @@
+env CGO_ENABLED=0
+
+! go install cgotest
+stderr 'build constraints exclude all Go files'
+
+-- go.mod --
+module cgotest
+
+go 1.16
+-- m.go --
+package cgotest
+
+import "C"
+
+var _ C.int
diff --git a/src/cmd/go/testdata/script/install_cleans_build.txt b/src/cmd/go/testdata/script/install_cleans_build.txt
new file mode 100644
index 0000000..dc85eb8
--- /dev/null
+++ b/src/cmd/go/testdata/script/install_cleans_build.txt
@@ -0,0 +1,25 @@
+env GO111MODULE=off
+[short] skip
+
+# 'go install' with no arguments should clean up after go build
+cd mycmd
+go build
+exists mycmd$GOEXE
+go install
+! exists mycmd$GOEXE
+
+# 'go install mycmd' does not clean up, even in the mycmd directory
+go build
+exists mycmd$GOEXE
+go install mycmd
+exists mycmd$GOEXE
+
+# 'go install mycmd' should not clean up in an unrelated current directory either
+cd ..
+cp mycmd/mycmd$GOEXE mycmd$GOEXE
+go install mycmd
+exists mycmd$GOEXE
+
+-- mycmd/main.go --
+package main
+func main() {}
diff --git a/src/cmd/go/testdata/script/install_cmd_gobin.txt b/src/cmd/go/testdata/script/install_cmd_gobin.txt
new file mode 100644
index 0000000..049bf41
--- /dev/null
+++ b/src/cmd/go/testdata/script/install_cmd_gobin.txt
@@ -0,0 +1,10 @@
+# Check that commands in cmd are install to $GOROOT/bin, not $GOBIN.
+# Verifies golang.org/issue/32674.
+env GOBIN=gobin
+mkdir gobin
+go list -f '{{.Target}}' cmd/go
+stdout $GOROOT${/}bin${/}go$GOEXE
+
+# Check that tools are installed to $GOTOOLDIR, not $GOBIN.
+go list -f '{{.Target}}' cmd/compile
+stdout $GOROOT${/}pkg${/}tool${/}${GOOS}_${GOARCH}${/}compile$GOEXE
diff --git a/src/cmd/go/testdata/script/install_cross_gobin.txt b/src/cmd/go/testdata/script/install_cross_gobin.txt
new file mode 100644
index 0000000..7679a7e
--- /dev/null
+++ b/src/cmd/go/testdata/script/install_cross_gobin.txt
@@ -0,0 +1,25 @@
+env GO111MODULE=off
+[short] skip # rebuilds std for alternate architecture
+
+cd mycmd
+go build mycmd
+
+# cross-compile install with implicit GOBIN=$GOPATH/bin can make subdirectory
+env GOARCH=386
+[GOARCH:386] env GOARCH=amd64
+env GOOS=linux
+go install mycmd
+exists $GOPATH/bin/linux_$GOARCH/mycmd
+
+# cross-compile install with explicit GOBIN cannot make subdirectory
+env GOBIN=$WORK/bin
+! go install mycmd
+! exists $GOBIN/linux_$GOARCH
+
+# The install directory for a cross-compiled standard command should include GOARCH.
+go list -f '{{.Target}}' cmd/pack
+stdout ${GOROOT}[/\\]pkg[/\\]tool[/\\]${GOOS}_${GOARCH}[/\\]pack$
+
+-- mycmd/x.go --
+package main
+func main() {}
diff --git a/src/cmd/go/testdata/script/install_dep_version.txt b/src/cmd/go/testdata/script/install_dep_version.txt
new file mode 100644
index 0000000..58330e6
--- /dev/null
+++ b/src/cmd/go/testdata/script/install_dep_version.txt
@@ -0,0 +1,8 @@
+# Regression test for Issue #54908. When running a go install module@version
+# with --mod=readonly moduleInfo was not setting the GoVersion for the module
+# because the checksumOk function was failing because modfetch.GoSumFile
+# was not set when running outside of a module.
+
+env GOTOOLCHAIN=local
+
+go install --mod=readonly example.com/depends/on/generics@v1.0.0 \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/install_goroot_targets.txt b/src/cmd/go/testdata/script/install_goroot_targets.txt
new file mode 100644
index 0000000..f26ee82
--- /dev/null
+++ b/src/cmd/go/testdata/script/install_goroot_targets.txt
@@ -0,0 +1,27 @@
+[short] skip
+
+# Packages in std do not have an install target.
+go list -f '{{.Target}}' fmt
+! stdout .
+go list -export -f '{{.Export}}' fmt
+stdout $GOCACHE
+
+# With GODEBUG=installgoroot=all, fmt has a target.
+# (Though we can't try installing it without modifying goroot).
+env GODEBUG=installgoroot=all
+go list -f '{{.Target}}' fmt
+stdout fmt\.a
+
+# However, the fake packages "builtin" and "unsafe" do not.
+go list -f '{{.Target}}' builtin unsafe
+! stdout .
+go install builtin unsafe # Should succeed as no-ops.
+
+# With CGO_ENABLED=0, packages that would have
+# an install target with cgo on no longer do.
+env GODEBUG=
+env CGO_ENABLED=0
+go list -f '{{.Target}}' runtime/cgo
+! stdout .
+go list -export -f '{{.Export}}' runtime/cgo
+stdout $GOCACHE
diff --git a/src/cmd/go/testdata/script/install_modcacherw_issue64282.txt b/src/cmd/go/testdata/script/install_modcacherw_issue64282.txt
new file mode 100644
index 0000000..3e1e6e5
--- /dev/null
+++ b/src/cmd/go/testdata/script/install_modcacherw_issue64282.txt
@@ -0,0 +1,45 @@
+# Regression test for https://go.dev/issue/64282.
+#
+# 'go install' and 'go run' with pkg@version arguments should make
+# a best effort to parse flags relevant to downloading modules
+# (currently only -modcacherw) before actually downloading the module
+# to identify which toolchain version to use.
+#
+# However, the best-effort flag parsing should not interfere with
+# actual flag parsing if we don't switch toolchains. In particular,
+# unrecognized flags should still be diagnosed after the module for
+# the requested package has been downloaded and checked for toolchain
+# upgrades.
+
+
+! go install -cake=delicious -modcacherw example.com/printversion@v0.1.0
+stderr '^flag provided but not defined: -cake$'
+ # Because the -modcacherw flag was set, we should be able to modify the contents
+ # of a directory within the module cache.
+cp $WORK/extraneous.txt $GOPATH/pkg/mod/example.com/printversion@v0.1.0/extraneous_file.go
+go clean -modcache
+
+
+! go install -unknownflag -tags -modcacherw example.com/printversion@v0.1.0
+stderr '^flag provided but not defined: -unknownflag$'
+cp $WORK/extraneous.txt $GOPATH/pkg/mod/example.com/printversion@v0.1.0/extraneous_file.go
+go clean -modcache
+
+
+# Also try it with a 'go install' that succeeds.
+# (But skip in short mode, because linking a binary is expensive.)
+[!short] go install -modcacherw example.com/printversion@v0.1.0
+[!short] cp $WORK/extraneous.txt $GOPATH/pkg/mod/example.com/printversion@v0.1.0/extraneous_file.go
+[!short] go clean -modcache
+
+
+# The flag should also be applied if given in GOFLAGS
+# instead of on the command line.
+env GOFLAGS=-modcacherw
+! go install -cake=delicious example.com/printversion@v0.1.0
+stderr '^flag provided but not defined: -cake$'
+cp $WORK/extraneous.txt $GOPATH/pkg/mod/example.com/printversion@v0.1.0/extraneous_file.go
+
+
+-- $WORK/extraneous.txt --
+This is not a Go source file.
diff --git a/src/cmd/go/testdata/script/install_move_not_stale.txt b/src/cmd/go/testdata/script/install_move_not_stale.txt
new file mode 100644
index 0000000..de191cf
--- /dev/null
+++ b/src/cmd/go/testdata/script/install_move_not_stale.txt
@@ -0,0 +1,26 @@
+# Check to see that the distribution is not stale
+# even when it's been moved to a different directory.
+# Simulate that by creating a symlink to the tree.
+
+# We use net instead of std because stale std has
+# the behavior of checking that all std targets
+# are stale rather than any of them.
+
+[!symlink] skip
+[short] skip
+
+go build net
+! stale net
+
+symlink new -> $GOROOT
+env OLDGOROOT=$GOROOT
+env GOROOT=$WORK${/}gopath${/}src${/}new
+go env GOROOT
+stdout $WORK[\\/]gopath[\\/]src[\\/]new
+cd new
+! stale net
+
+# Add a control case to check that std is
+# stale with an empty cache
+env GOCACHE=$WORK${/}gopath${/}cache
+stale net
diff --git a/src/cmd/go/testdata/script/install_msan_and_race_and_asan_require_cgo.txt b/src/cmd/go/testdata/script/install_msan_and_race_and_asan_require_cgo.txt
new file mode 100644
index 0000000..d8f2aba
--- /dev/null
+++ b/src/cmd/go/testdata/script/install_msan_and_race_and_asan_require_cgo.txt
@@ -0,0 +1,22 @@
+# Tests Issue #21895
+
+env CGO_ENABLED=0
+
+[GOOS:darwin] [!short] [race] go build -race triv.go
+
+[!GOOS:darwin] [race] ! go install -race triv.go
+[!GOOS:darwin] [race] stderr '-race requires cgo'
+[!GOOS:darwin] [race] ! stderr '-msan'
+
+[msan] ! go install -msan triv.go
+[msan] stderr '-msan requires cgo'
+[msan] ! stderr '-race'
+
+[asan] ! go install -asan triv.go
+[asan] stderr '(-asan: the version of $(go env CC) could not be parsed)|(-asan: C compiler is not gcc or clang)|(-asan is not supported with [A-Za-z]+ compiler (\d+)\.(\d+))|(-asan requires cgo)'
+[asan] ! stderr '-msan'
+
+-- triv.go --
+package main
+
+func main() {}
diff --git a/src/cmd/go/testdata/script/install_rebuild_removed.txt b/src/cmd/go/testdata/script/install_rebuild_removed.txt
new file mode 100644
index 0000000..5db3778
--- /dev/null
+++ b/src/cmd/go/testdata/script/install_rebuild_removed.txt
@@ -0,0 +1,44 @@
+env GO111MODULE=off
+
+# go command should detect package staleness as source file set changes
+go install mypkg
+! stale mypkg
+
+# z.go was not compiled; removing it should NOT make mypkg stale
+rm mypkg/z.go
+! stale mypkg
+
+# y.go was compiled; removing it should make mypkg stale
+rm mypkg/y.go
+stale mypkg
+
+# go command should detect executable staleness too
+go install mycmd
+! stale mycmd
+rm mycmd/z.go
+! stale mycmd
+rm mycmd/y.go
+stale mycmd
+
+-- mypkg/x.go --
+package mypkg
+
+-- mypkg/y.go --
+package mypkg
+
+-- mypkg/z.go --
+// +build missingtag
+
+package mypkg
+
+-- mycmd/x.go --
+package main
+func main() {}
+
+-- mycmd/y.go --
+package main
+
+-- mycmd/z.go --
+// +build missingtag
+
+package main
diff --git a/src/cmd/go/testdata/script/install_relative_gobin_fail.txt b/src/cmd/go/testdata/script/install_relative_gobin_fail.txt
new file mode 100644
index 0000000..aa14524
--- /dev/null
+++ b/src/cmd/go/testdata/script/install_relative_gobin_fail.txt
@@ -0,0 +1,12 @@
+env GOBIN=.
+! go install
+stderr 'cannot install, GOBIN must be an absolute path'
+
+-- go.mod --
+module triv
+
+go 1.16
+-- triv.go --
+package main
+
+func main() {}
diff --git a/src/cmd/go/testdata/script/install_shadow_gopath.txt b/src/cmd/go/testdata/script/install_shadow_gopath.txt
new file mode 100644
index 0000000..148e6cc
--- /dev/null
+++ b/src/cmd/go/testdata/script/install_shadow_gopath.txt
@@ -0,0 +1,18 @@
+# Tests Issue #3562
+# go get foo.io (not foo.io/subdir) was not working consistently.
+
+env GO111MODULE=off
+env GOPATH=$WORK/gopath1${:}$WORK/gopath2
+
+mkdir $WORK/gopath1/src/test
+mkdir $WORK/gopath2/src/test
+cp main.go $WORK/gopath2/src/test/main.go
+cd $WORK/gopath2/src/test
+
+! go install
+stderr 'no install location for.*gopath2.src.test: hidden by .*gopath1.src.test'
+
+-- main.go --
+package main
+
+func main() {}
diff --git a/src/cmd/go/testdata/script/issue36000.txt b/src/cmd/go/testdata/script/issue36000.txt
new file mode 100644
index 0000000..4173275
--- /dev/null
+++ b/src/cmd/go/testdata/script/issue36000.txt
@@ -0,0 +1,6 @@
+# Tests golang.org/issue/36000
+
+[!cgo] skip
+
+# go env with CGO flags should not make NUL file
+go env CGO_CFLAGS
diff --git a/src/cmd/go/testdata/script/issue53586.txt b/src/cmd/go/testdata/script/issue53586.txt
new file mode 100644
index 0000000..db405cd
--- /dev/null
+++ b/src/cmd/go/testdata/script/issue53586.txt
@@ -0,0 +1,18 @@
+[short] skip # sleeps to make mtime cacheable
+
+go mod init example
+
+cd subdir
+go mod init example/subdir
+sleep 2s # allow go.mod mtime to be cached
+
+go list -f '{{.Dir}}: {{.ImportPath}}' ./pkg
+stdout $PWD${/}pkg': example/subdir/pkg$'
+
+rm go.mod # expose ../go.mod
+
+go list -f '{{.Dir}}: {{.ImportPath}}' ./pkg
+stdout $PWD${/}pkg': example/subdir/pkg$'
+
+-- subdir/pkg/pkg.go --
+package pkg
diff --git a/src/cmd/go/testdata/script/ldflag.txt b/src/cmd/go/testdata/script/ldflag.txt
new file mode 100644
index 0000000..6ceb33b
--- /dev/null
+++ b/src/cmd/go/testdata/script/ldflag.txt
@@ -0,0 +1,44 @@
+# Issue #42565
+
+[!cgo] skip
+
+# We can't build package bad, which uses #cgo LDFLAGS.
+cd bad
+! go build
+stderr no-such-warning
+
+# We can build package ok with the same flags in CGO_LDFLAGS.
+env CGO_LDFLAGS=-Wno-such-warning -Wno-unknown-warning-option
+cd ../ok
+go build
+
+# Build a main program that actually uses LDFLAGS.
+cd ..
+go build -ldflags=-v
+
+# Because we passed -v the Go linker should print the external linker
+# command which should include the flag we passed in CGO_LDFLAGS.
+stderr no-such-warning
+
+-- go.mod --
+module ldflag
+
+-- bad/bad.go --
+package bad
+
+// #cgo LDFLAGS: -Wno-such-warning -Wno-unknown-warning
+import "C"
+
+func F() {}
+-- ok/ok.go --
+package ok
+
+import "C"
+
+func F() {}
+-- main.go --
+package main
+
+import _ "ldflag/ok"
+
+func main() {}
diff --git a/src/cmd/go/testdata/script/link_external_undef.txt b/src/cmd/go/testdata/script/link_external_undef.txt
new file mode 100644
index 0000000..f320505
--- /dev/null
+++ b/src/cmd/go/testdata/script/link_external_undef.txt
@@ -0,0 +1,48 @@
+
+# Test case for issue 47993, in which the linker crashes
+# on a bad input instead of issuing an error and exiting.
+
+# This test requires external linking, so use cgo as a proxy
+[!cgo] skip
+
+! go build -ldflags='-linkmode=external' .
+! stderr 'panic'
+stderr '^.*undefined symbol in relocation.*'
+
+-- go.mod --
+
+module issue47993
+
+go 1.16
+
+-- main.go --
+
+package main
+
+type M struct {
+ b bool
+}
+
+// Note the body-less func def here. This is what causes the problems.
+func (m *M) run(fp func())
+
+func doit(m *M) {
+ InAsm()
+ m.run(func() {
+ })
+}
+
+func main() {
+ m := &M{true}
+ doit(m)
+}
+
+func InAsm()
+
+-- main.s --
+
+// Add an assembly function so as to leave open the possibility
+// that body-less functions in Go might be defined in assembly.
+
+// Currently we just need an empty file here.
+
diff --git a/src/cmd/go/testdata/script/link_matching_actionid.txt b/src/cmd/go/testdata/script/link_matching_actionid.txt
new file mode 100644
index 0000000..b8d423d
--- /dev/null
+++ b/src/cmd/go/testdata/script/link_matching_actionid.txt
@@ -0,0 +1,38 @@
+# Checks that an identical binary is built with -trimpath from the same
+# source files, with GOROOT in two different locations.
+# Verifies golang.org/issue/38989
+
+[short] skip
+[!symlink] skip
+
+# Symlink the compiler to a local path
+env GOROOT=$WORK/goroot1
+symlink $GOROOT -> $TESTGO_GOROOT
+
+# Set up fresh GOCACHE
+env GOCACHE=$WORK/gocache1
+mkdir $GOCACHE
+
+# Build a simple binary
+go build -o binary1 -trimpath -x main.go
+
+# Now repeat the same process with the compiler at a different local path
+env GOROOT=$WORK/goroot2
+symlink $GOROOT -> $TESTGO_GOROOT
+
+env GOCACHE=$WORK/gocache2
+mkdir $GOCACHE
+
+go build -o binary2 -trimpath -x main.go
+
+# Check that the binaries match exactly
+go tool buildid binary1
+cp stdout buildid1
+go tool buildid binary2
+cp stdout buildid2
+cmp buildid1 buildid2
+
+
+-- main.go --
+package main
+func main() {}
diff --git a/src/cmd/go/testdata/script/link_syso_deps.txt b/src/cmd/go/testdata/script/link_syso_deps.txt
new file mode 100644
index 0000000..6bb9005
--- /dev/null
+++ b/src/cmd/go/testdata/script/link_syso_deps.txt
@@ -0,0 +1,55 @@
+# Test that syso in deps is available to cgo.
+
+[!compiler:gc] skip 'requires syso support'
+[!cgo] skip
+[short] skip 'invokes system C compiler'
+
+# External linking is not supported on linux/ppc64.
+# See: https://github.com/golang/go/issues/8912
+[GOOS:linux] [GOARCH:ppc64] skip
+
+cc -c -o syso/x.syso syso/x.c
+cc -c -o syso2/x.syso syso2/x.c
+go build m/cgo
+
+-- go.mod --
+module m
+
+go 1.18
+-- cgo/x.go --
+package cgo
+
+// extern void f(void);
+// extern void g(void);
+import "C"
+
+func F() {
+ C.f()
+}
+
+func G() {
+ C.g()
+}
+
+-- cgo/x2.go --
+package cgo
+
+import _ "m/syso"
+
+-- syso/x.c --
+//go:build ignore
+
+void f() {}
+
+-- syso/x.go --
+package syso
+
+import _ "m/syso2"
+
+-- syso2/x.c --
+//go:build ignore
+
+void g() {}
+
+-- syso2/x.go --
+package syso2
diff --git a/src/cmd/go/testdata/script/link_syso_issue33139.txt b/src/cmd/go/testdata/script/link_syso_issue33139.txt
new file mode 100644
index 0000000..b0d4a7c
--- /dev/null
+++ b/src/cmd/go/testdata/script/link_syso_issue33139.txt
@@ -0,0 +1,45 @@
+# Test that we can use the external linker with a host syso file that is
+# embedded in a package, that is referenced by a Go assembly function.
+# See issue 33139.
+
+[!compiler:gc] skip
+[!cgo] skip
+[short] skip 'invokes system C compiler'
+
+# External linking is not supported on linux/ppc64.
+# See: https://github.com/golang/go/issues/8912
+[GOOS:linux] [GOARCH:ppc64] skip
+
+cc -c -o syso/objTestImpl.syso syso/src/objTestImpl.c
+go build -ldflags='-linkmode=external' ./cmd/main.go
+
+-- go.mod --
+module m
+
+go 1.16
+-- syso/objTest.s --
+#include "textflag.h"
+
+TEXT ·ObjTest(SB), NOSPLIT, $0
+ // We do not actually execute this function in the test above, thus
+ // there is no stack frame setup here.
+ // We only care about Go build and/or link errors when referencing
+ // the objTestImpl symbol in the syso file.
+ JMP objTestImpl(SB)
+
+-- syso/pkg.go --
+package syso
+
+func ObjTest()
+
+-- syso/src/objTestImpl.c --
+void objTestImpl() { /* Empty */ }
+
+-- cmd/main.go --
+package main
+
+import "m/syso"
+
+func main() {
+ syso.ObjTest()
+}
diff --git a/src/cmd/go/testdata/script/linkname.txt b/src/cmd/go/testdata/script/linkname.txt
new file mode 100644
index 0000000..36ac8eb
--- /dev/null
+++ b/src/cmd/go/testdata/script/linkname.txt
@@ -0,0 +1,9 @@
+env GO111MODULE=off
+
+# check for linker name in error message about linker crash
+[!compiler:gc] skip
+! go build -ldflags=-crash_for_testing x.go
+stderr [\\/]tool[\\/].*[\\/]link
+
+-- x.go --
+package main; func main() {}
diff --git a/src/cmd/go/testdata/script/list_all_gobuild.txt b/src/cmd/go/testdata/script/list_all_gobuild.txt
new file mode 100644
index 0000000..92ad7d8
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_all_gobuild.txt
@@ -0,0 +1,42 @@
+# go list all should work with GOOS=linux because all packages build on Linux
+env GOOS=linux
+env GOARCH=amd64
+go list all
+
+# go list all should work with GOOS=darwin, but it used to fail because
+# in the absence of //go:build support, p looked like it needed q
+# (p_test.go was not properly excluded), and q was Linux-only.
+#
+# Also testing with r and s that +build lines keep working.
+env GOOS=darwin
+go list all
+
+-- go.mod --
+go 1.17
+module m
+
+-- p/p.go --
+package p
+
+-- p/p_test.go --
+//go:build linux
+
+package p
+
+import "m/q"
+
+-- q/q_linux.go --
+package q
+
+-- r/r.go --
+package r
+
+-- r/r_test.go --
+// +build linux
+
+package r
+
+import "m/s"
+
+-- s/s_linux.go --
+package s
diff --git a/src/cmd/go/testdata/script/list_ambiguous_path.txt b/src/cmd/go/testdata/script/list_ambiguous_path.txt
new file mode 100644
index 0000000..6f22314
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_ambiguous_path.txt
@@ -0,0 +1,38 @@
+# Ensures that we can correctly list package patterns ending in '.go'.
+# See golang.org/issue/34653.
+
+# A single pattern for a package ending in '.go'.
+go list ./foo.go
+stdout '^test/foo.go$'
+
+# Multiple patterns for packages including one ending in '.go'.
+go list ./bar ./foo.go
+stdout '^test/bar$'
+stdout '^test/foo.go$'
+
+# A single pattern for a Go file.
+go list ./a.go
+stdout '^command-line-arguments$'
+
+# A single typo-ed pattern for a Go file. This should
+# treat the wrong pattern as if it were a package.
+! go list ./foo.go/b.go
+stderr '^stat .*[/\\]foo\.go[/\\]b\.go: directory not found$'
+
+# Multiple patterns for Go files with a typo. This should
+# treat the wrong pattern as if it were a nonexistent file.
+! go list ./foo.go/a.go ./foo.go/b.go
+[GOOS:plan9] stderr 'stat ./foo.go/b.go: ''./foo.go/b.go'' does not exist'
+[GOOS:windows] stderr './foo.go/b.go: The system cannot find the file specified'
+[!GOOS:plan9] [!GOOS:windows] stderr './foo.go/b.go: no such file or directory'
+
+-- a.go --
+package main
+-- bar/a.go --
+package bar
+-- foo.go/a.go --
+package foo.go
+-- go.mod --
+module "test"
+
+go 1.13
diff --git a/src/cmd/go/testdata/script/list_bad_import.txt b/src/cmd/go/testdata/script/list_bad_import.txt
new file mode 100644
index 0000000..dbec350
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_bad_import.txt
@@ -0,0 +1,72 @@
+env GO111MODULE=off
+[short] skip
+
+# This test matches mod_list_bad_import, but in GOPATH mode.
+# Please keep them in sync.
+
+env GO111MODULE=off
+cd example.com
+
+# Without -e, listing an otherwise-valid package with an unsatisfied direct import should fail.
+# BUG: Today it succeeds.
+go list -f '{{if .Error}}error{{end}} {{if .Incomplete}}incomplete{{end}} {{range .DepsErrors}}bad dep: {{.Err}}{{end}}' example.com/direct
+! stdout ^error
+stdout 'incomplete'
+stdout 'bad dep: .*example.com[/\\]notfound'
+
+# Listing with -deps should also fail.
+! go list -deps example.com/direct
+stderr example.com[/\\]notfound
+
+# But -e -deps should succeed.
+go list -e -deps example.com/direct
+stdout example.com/notfound
+
+
+# Listing an otherwise-valid package that imports some *other* package with an
+# unsatisfied import should also fail.
+# BUG: Today, it succeeds.
+go list -f '{{if .Error}}error{{end}} {{if .Incomplete}}incomplete{{end}} {{range .DepsErrors}}bad dep: {{.Err}}{{end}}' example.com/indirect
+! stdout ^error
+stdout incomplete
+stdout 'bad dep: .*example.com[/\\]notfound'
+
+# Again, -deps should fail.
+! go list -deps example.com/indirect
+stderr example.com[/\\]notfound
+
+# But -deps -e should succeed.
+go list -e -deps example.com/indirect
+stdout example.com/notfound
+
+
+# Listing the missing dependency directly should fail outright...
+! go list -f '{{if .Error}}error{{end}} {{if .Incomplete}}incomplete{{end}}' example.com/notfound
+stderr 'no Go files in .*example.com[/\\]notfound'
+! stdout error
+! stdout incomplete
+
+# ...but listing with -e should succeed.
+go list -e -f '{{if .Error}}error{{end}} {{if .Incomplete}}incomplete{{end}}' example.com/notfound
+stdout error
+stdout incomplete
+
+
+# The pattern "all" should match only packages that actually exist,
+# ignoring those whose existence is merely implied by imports.
+go list -e -f '{{.ImportPath}}' all
+stdout example.com/direct
+stdout example.com/indirect
+! stdout example.com/notfound
+
+
+-- example.com/direct/direct.go --
+package direct
+import _ "example.com/notfound"
+
+-- example.com/indirect/indirect.go --
+package indirect
+import _ "example.com/direct"
+
+-- example.com/notfound/README --
+This directory intentionally left blank.
diff --git a/src/cmd/go/testdata/script/list_case_collision.txt b/src/cmd/go/testdata/script/list_case_collision.txt
new file mode 100644
index 0000000..181a202
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_case_collision.txt
@@ -0,0 +1,41 @@
+# Tests golang.org/issue/4773
+
+go list -json example/a
+stdout 'case-insensitive import collision'
+
+! go build example/a
+stderr 'case-insensitive import collision'
+
+# List files explicitly on command line, to encounter case-checking
+# logic even on case-insensitive filesystems.
+cp b/file.go b/FILE.go # no-op on case-insensitive filesystems
+! go list b/file.go b/FILE.go
+stderr 'case-insensitive file name collision'
+
+mkdir a/Pkg # no-op on case-insensitive filesystems
+cp a/pkg/pkg.go a/Pkg/pkg.go # no-op on case-insensitive filesystems
+! go list example/a/pkg example/a/Pkg
+
+# Test that the path reported with an indirect import is correct.
+cp b/file.go b/FILE.go
+[case-sensitive] ! go build example/c
+[case-sensitive] stderr '^package example/c\n\timports example/b: case-insensitive file name collision: "FILE.go" and "file.go"$'
+
+-- go.mod --
+module example
+
+go 1.16
+-- a/a.go --
+package p
+import (
+ _ "example/a/pkg"
+ _ "example/a/Pkg"
+)
+-- a/pkg/pkg.go --
+package pkg
+-- b/file.go --
+package b
+-- c/c.go --
+package c
+
+import _ "example/b"
diff --git a/src/cmd/go/testdata/script/list_cgo_compiled_importmap.txt b/src/cmd/go/testdata/script/list_cgo_compiled_importmap.txt
new file mode 100644
index 0000000..8693339
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_cgo_compiled_importmap.txt
@@ -0,0 +1,41 @@
+# Regression test for https://golang.org/issue/46462.
+#
+# The "runtime/cgo" import found in synthesized .go files (reported in
+# the CompiledGoFiles field) should have a corresponding entry in the
+# ImportMap field when a runtime/cgo variant (such as a test variant)
+# will be used.
+
+[short] skip # -compiled can be slow (because it compiles things)
+[!cgo] skip
+[GOOS:darwin] skip # net package does not import "C" on Darwin
+[GOOS:windows] skip # net package does not import "C" on Windows
+[GOOS:plan9] skip # net package does not import "C" on Plan 9
+
+env CGO_ENABLED=1
+env GOFLAGS=-tags=netcgo # Force net to use cgo
+
+
+# "runtime/cgo [runtime.test]" appears in the test dependencies of "runtime",
+# because "runtime/cgo" itself depends on "runtime"
+
+go list -deps -test -compiled -f '{{if eq .ImportPath "net [runtime.test]"}}{{printf "%q" .Imports}}{{end}}' runtime
+
+ # Control case: the explicitly-imported package "sync" is a test variant,
+ # because "sync" depends on "runtime".
+stdout '"sync \[runtime\.test\]"'
+! stdout '"sync"'
+
+ # Experiment: the implicitly-imported package "runtime/cgo" is also a test variant,
+ # because "runtime/cgo" also depends on "runtime".
+stdout '"runtime/cgo \[runtime\.test\]"'
+! stdout '"runtime/cgo"'
+
+
+# Because the import of "runtime/cgo" in the cgo-generated file actually refers
+# to "runtime/cgo [runtime.test]", the latter should be listed in the ImportMap.
+# BUG(#46462): Today, it is not.
+
+go list -deps -test -compiled -f '{{if eq .ImportPath "net [runtime.test]"}}{{printf "%q" .ImportMap}}{{end}}' runtime
+
+stdout '"sync":"sync \[runtime\.test\]"' # control
+stdout '"runtime/cgo":"runtime/cgo \[runtime\.test\]"' # experiment
diff --git a/src/cmd/go/testdata/script/list_compiled_files_issue28749.txt b/src/cmd/go/testdata/script/list_compiled_files_issue28749.txt
new file mode 100644
index 0000000..e0fb977
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_compiled_files_issue28749.txt
@@ -0,0 +1,10 @@
+go list -compiled -f {{.CompiledGoFiles}} .
+! stdout 'foo.s'
+
+-- go.mod --
+module example.com/foo
+
+go 1.20
+-- foo.go --
+package foo
+-- foo.s --
diff --git a/src/cmd/go/testdata/script/list_compiled_imports.txt b/src/cmd/go/testdata/script/list_compiled_imports.txt
new file mode 100644
index 0000000..7780b07
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_compiled_imports.txt
@@ -0,0 +1,31 @@
+env GO111MODULE=off
+
+[!cgo] skip
+
+# go list should report import "C"
+cd x
+go list -f '{{.Imports}}'
+! stdout runtime/cgo
+! stdout unsafe
+! stdout syscall
+stdout C
+stdout unicode
+stdout unicode/utf16
+
+# go list -compiled should report imports in compiled files as well,
+# adding "runtime/cgo", "unsafe", and "syscall" but not dropping "C".
+go list -compiled -f '{{.Imports}}'
+stdout runtime/cgo
+stdout unsafe
+stdout syscall
+stdout C
+stdout unicode
+stdout unicode/utf16
+
+-- x/x.go --
+package x
+import "C"
+import "unicode" // does not use unsafe, syscall, runtime/cgo, unicode/utf16
+-- x/x1.go --
+package x
+import "unicode/utf16" // does not use unsafe, syscall, runtime/cgo, unicode
diff --git a/src/cmd/go/testdata/script/list_compiler_output.txt b/src/cmd/go/testdata/script/list_compiler_output.txt
new file mode 100644
index 0000000..5230bab
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_compiler_output.txt
@@ -0,0 +1,16 @@
+[short] skip
+
+go install -gcflags=-m .
+stderr 'can inline main'
+go list -gcflags=-m -f '{{.Stale}}' .
+stdout 'false'
+! stderr 'can inline main'
+
+-- go.mod --
+module example.com/foo
+
+go 1.20
+-- main.go --
+package main
+
+func main() {}
diff --git a/src/cmd/go/testdata/script/list_constraints.txt b/src/cmd/go/testdata/script/list_constraints.txt
new file mode 100644
index 0000000..7115c36
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_constraints.txt
@@ -0,0 +1,86 @@
+# Check that files and their imports are not included in 'go list' output
+# when they are excluded by build constraints.
+
+# Linux and cgo files should be included when building in that configuration.
+env GOOS=linux
+env GOARCH=amd64
+env CGO_ENABLED=1
+go list -f '{{range .GoFiles}}{{.}} {{end}}'
+stdout '^cgotag.go empty.go suffix_linux.go tag.go $'
+go list -f '{{range .CgoFiles}}{{.}} {{end}}'
+stdout '^cgoimport.go $'
+go list -f '{{range .Imports}}{{.}} {{end}}'
+stdout '^C cgoimport cgotag suffix tag $'
+
+# Disabling cgo should exclude cgo files and their imports.
+env CGO_ENABLED=0
+go list -f '{{range .GoFiles}}{{.}} {{end}}'
+stdout 'empty.go suffix_linux.go tag.go'
+go list -f '{{range .CgoFiles}}{{.}} {{end}}'
+! stdout .
+go list -f '{{range .Imports}}{{.}} {{end}}'
+stdout '^suffix tag $'
+
+# Changing OS should exclude linux sources.
+env GOOS=darwin
+go list -f '{{range .GoFiles}}{{.}} {{end}}'
+stdout '^empty.go $'
+go list -f '{{range .Imports}}{{.}} {{end}}'
+stdout '^$'
+
+# Enabling a tag should include files that require it.
+go list -tags=extra -f '{{range .GoFiles}}{{.}} {{end}}'
+stdout '^empty.go extra.go $'
+go list -tags=extra -f '{{range .Imports}}{{.}} {{end}}'
+stdout '^extra $'
+
+# Packages that require a tag should not be listed unless the tag is on.
+! go list ./tagonly
+go list -tags=extra ./tagonly
+stdout m/tagonly
+
+-- go.mod --
+module m
+
+go 1.13
+
+-- empty.go --
+package p
+
+-- extra.go --
+// +build extra
+
+package p
+
+import _ "extra"
+
+-- suffix_linux.go --
+package p
+
+import _ "suffix"
+
+-- tag.go --
+// +build linux
+
+package p
+
+import _ "tag"
+
+-- cgotag.go --
+// +build cgo
+
+package p
+
+import _ "cgotag"
+
+-- cgoimport.go --
+package p
+
+import "C"
+
+import _ "cgoimport"
+
+-- tagonly/tagonly.go --
+// +build extra
+
+package tagonly
diff --git a/src/cmd/go/testdata/script/list_dedup_packages.txt b/src/cmd/go/testdata/script/list_dedup_packages.txt
new file mode 100644
index 0000000..30c68dd
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_dedup_packages.txt
@@ -0,0 +1,31 @@
+# Setup
+env GO111MODULE=off
+mkdir $WORK/tmp/testdata/src/xtestonly
+cp f.go $WORK/tmp/testdata/src/xtestonly/f.go
+cp f_test.go $WORK/tmp/testdata/src/xtestonly/f_test.go
+env GOPATH=$WORK/tmp/testdata
+cd $WORK
+
+# Check output of go list to ensure no duplicates
+go list xtestonly ./tmp/testdata/src/xtestonly/...
+cmp stdout $WORK/gopath/src/wantstdout
+
+-- wantstdout --
+xtestonly
+-- f.go --
+package xtestonly
+
+func F() int { return 42 }
+-- f_test.go --
+package xtestonly_test
+
+import (
+ "testing"
+ "xtestonly"
+)
+
+func TestF(t *testing.T) {
+ if x := xtestonly.F(); x != 42 {
+ t.Errorf("f.F() = %d, want 42", x)
+ }
+}
diff --git a/src/cmd/go/testdata/script/list_empty_import.txt b/src/cmd/go/testdata/script/list_empty_import.txt
new file mode 100644
index 0000000..4d76f09
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_empty_import.txt
@@ -0,0 +1,9 @@
+! go list a.go
+! stdout .
+stderr 'invalid import path'
+! stderr panic
+
+-- a.go --
+package a
+
+import ""
diff --git a/src/cmd/go/testdata/script/list_err_cycle.txt b/src/cmd/go/testdata/script/list_err_cycle.txt
new file mode 100644
index 0000000..44b82a6
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_err_cycle.txt
@@ -0,0 +1,15 @@
+# Check that we don't get infinite recursion when loading a package with
+# an import cycle and another error. Verifies #25830.
+! go list
+stderr 'found packages a \(a.go\) and b \(b.go\)'
+
+-- go.mod --
+module errcycle
+
+go 1.16
+-- a.go --
+package a
+
+import _ "errcycle"
+-- b.go --
+package b \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/list_err_stack.txt b/src/cmd/go/testdata/script/list_err_stack.txt
new file mode 100644
index 0000000..a7be9fd
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_err_stack.txt
@@ -0,0 +1,27 @@
+
+# golang.org/issue/40544: regression in error stacks for parse errors
+
+env GO111MODULE=off
+cd sandbox/foo
+go list -e -json .
+stdout '"sandbox/foo"'
+stdout '"sandbox/bar"'
+stdout '"Pos": "..(/|\\\\)bar(/|\\\\)bar.go:1:1"'
+stdout '"Err": "expected ''package'', found ackage"'
+
+env GO111MODULE=on
+go list -e -json .
+stdout '"sandbox/foo"'
+stdout '"sandbox/bar"'
+stdout '"Pos": "..(/|\\\\)bar(/|\\\\)bar.go:1:1"'
+stdout '"Err": "expected ''package'', found ackage"'
+
+-- sandbox/go.mod --
+module sandbox
+
+-- sandbox/foo/foo.go --
+package pkg
+
+import "sandbox/bar"
+-- sandbox/bar/bar.go --
+ackage bar \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/list_export_e.txt b/src/cmd/go/testdata/script/list_export_e.txt
new file mode 100644
index 0000000..6d5dd39
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_export_e.txt
@@ -0,0 +1,30 @@
+! go list -export ./...
+stderr '^# example.com/p2\np2'${/}'main\.go:7:.*'
+! stderr '^go build '
+
+go list -f '{{with .Error}}{{.}}{{end}}' -e -export ./...
+! stderr '.'
+stdout '^# example.com/p2\np2'${/}'main\.go:7:.*'
+
+go list -export -e -f '{{.ImportPath}} -- {{.Incomplete}} -- {{.Error}}' ./...
+stdout 'example.com/p1 -- false -- <nil>'
+stdout 'example.com/p2 -- true -- # example.com/p2'
+
+go list -e -export -json=Error ./...
+stdout '"Err": "# example.com/p2'
+
+-- go.mod --
+module example.com
+-- p1/p1.go --
+package p1
+
+const Name = "p1"
+-- p2/main.go --
+package main
+
+import "fmt"
+import "example.com/p1"
+
+func main() {
+ fmt.Println(p1.Name == 5)
+}
diff --git a/src/cmd/go/testdata/script/list_export_embed.txt b/src/cmd/go/testdata/script/list_export_embed.txt
new file mode 100644
index 0000000..da74998
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_export_embed.txt
@@ -0,0 +1,17 @@
+# Regression test for https://go.dev/issue/58885:
+# 'go list -json=Export' should not fail due to missing go:embed metadata.
+
+[short] skip 'runs the compiler to produce export data'
+
+go list -json=Export -export .
+
+-- go.mod --
+module example
+go 1.20
+-- example.go --
+package example
+
+import _ "embed"
+
+//go:embed example.go
+var src string
diff --git a/src/cmd/go/testdata/script/list_find.txt b/src/cmd/go/testdata/script/list_find.txt
new file mode 100644
index 0000000..d450fc9
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_find.txt
@@ -0,0 +1,22 @@
+env GO111MODULE=off
+
+# go list -find should not report imports
+
+go list -f {{.Incomplete}} x/y/z... # should probably exit non-zero but never has
+stdout true
+go list -find -f '{{.Incomplete}} {{.Imports}}' x/y/z...
+stdout '^false \[\]'
+
+# go list -find -compiled should use cached sources the second time it's run.
+# It might not find the same cached sources as "go build", but the sources
+# should be identical. "go build" derives action IDs (which are used as cache
+# keys) from dependencies' action IDs. "go list -find" won't know what the
+# dependencies are, so it's can't construct the same action IDs.
+[short] skip
+go list -find -compiled net
+go list -find -compiled -x net
+! stderr 'cgo'
+
+-- x/y/z/z.go --
+package z
+import "does/not/exist"
diff --git a/src/cmd/go/testdata/script/list_find_nodeps.txt b/src/cmd/go/testdata/script/list_find_nodeps.txt
new file mode 100644
index 0000000..e08ce78
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_find_nodeps.txt
@@ -0,0 +1,49 @@
+# Issue #46092
+# go list -find should always return a package with an empty Deps list
+
+# The linker loads implicit dependencies
+go list -find -f {{.Deps}} ./cmd
+stdout '\[\]'
+
+# Cgo translation may add imports of "unsafe", "runtime/cgo" and "syscall"
+go list -find -f {{.Deps}} ./cgo
+stdout '\[\]'
+
+# SWIG adds imports of some standard packages
+go list -find -f {{.Deps}} ./swig
+stdout '\[\]'
+
+-- go.mod --
+module listfind
+
+-- cmd/main.go --
+package main
+
+func main() {}
+
+-- cgo/pkg.go --
+package cgopkg
+
+/*
+#include <limits.h>
+*/
+import "C"
+
+func F() {
+ println(C.INT_MAX)
+}
+
+-- cgo/pkg_notcgo.go --
+//go:build !cgo
+// +build !cgo
+
+package cgopkg
+
+func F() {
+ println(0)
+}
+
+-- swig/pkg.go --
+package swigpkg
+
+-- swig/a.swigcxx --
diff --git a/src/cmd/go/testdata/script/list_gofile_in_goroot.txt b/src/cmd/go/testdata/script/list_gofile_in_goroot.txt
new file mode 100644
index 0000000..b4ff3cb
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_gofile_in_goroot.txt
@@ -0,0 +1,76 @@
+# Return an error if the user tries to list a go source file directly in $GOROOT/src.
+# Tests golang.org/issue/36587
+
+env GOROOT=$WORK/goroot
+env GOPATH=$WORK/gopath
+
+go env GOROOT
+stdout $WORK[/\\]goroot
+
+# switch to GOROOT/src
+cd $GOROOT/src
+
+# In module mode, 'go list ./...' should not treat .go files in GOROOT/src as an
+# importable package, since that directory has no valid import path.
+env GO111MODULE=on
+go list ...
+stdout -count=1 '^.+$'
+stdout '^fmt$'
+! stdout foo
+
+go list ./...
+stdout -count=1 '^.+$'
+stdout '^fmt$'
+! stdout foo
+
+go list std
+stdout -count=1 '^.+$'
+stdout '^fmt$'
+
+! go list .
+stderr '^GOROOT/src is not an importable package$'
+
+# In GOPATH mode, 'go list ./...' should synthesize a legacy GOPATH-mode path —
+# not a standard-library or empty path — for the errant package.
+env GO111MODULE=off
+go list ./...
+stdout -count=2 '^.+$' # Both 'fmt' and GOROOT/src should be listed.
+stdout '^fmt$'
+[!GOOS:windows] stdout ^_$WORK/goroot/src$
+[GOOS:windows] stdout goroot/src$ # On windows the ":" in the volume name is mangled
+
+go list ...
+! stdout goroot/src
+
+go list std
+! stdout goroot/src
+
+go list .
+[!GOOS:windows] stdout ^_$WORK/goroot/src$
+[GOOS:windows] stdout goroot/src$
+
+# switch to GOPATH/src
+cd $GOPATH/src
+
+# GO111MODULE=off,GOPATH
+env GO111MODULE=off
+go list ./...
+[!GOOS:windows] stdout ^_$WORK/gopath/src$
+[GOOS:windows] stdout gopath/src$
+
+go list all
+! stdout gopath/src
+
+-- $WORK/goroot/src/go.mod --
+module std
+
+go 1.14
+-- $WORK/goroot/src/foo.go --
+package foo
+-- $WORK/goroot/src/fmt/fmt.go --
+package fmt
+-- $WORK/goroot/src/cmd/README --
+This directory must exist in order for the 'cmd' pattern to have something to
+match against.
+-- $GOPATH/src/foo.go --
+package foo
diff --git a/src/cmd/go/testdata/script/list_gomod_in_gopath.txt b/src/cmd/go/testdata/script/list_gomod_in_gopath.txt
new file mode 100644
index 0000000..064f33a
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_gomod_in_gopath.txt
@@ -0,0 +1,23 @@
+# Issue 46119
+
+# When a module is inside a GOPATH workspace, Package.Root should be set to
+# Module.Dir instead of $GOPATH/src.
+
+env GOPATH=$WORK/tmp
+cd $WORK/tmp/src/test
+
+go list -f {{.Root}}
+stdout ^$PWD$
+
+# Were we really inside a GOPATH workspace?
+env GO111MODULE=off
+go list -f {{.Root}}
+stdout ^$WORK/tmp$
+
+-- $WORK/tmp/src/test/go.mod --
+module test
+
+-- $WORK/tmp/src/test/main.go --
+package main
+
+func main() {}
diff --git a/src/cmd/go/testdata/script/list_goroot_symlink.txt b/src/cmd/go/testdata/script/list_goroot_symlink.txt
new file mode 100644
index 0000000..041ae55
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_goroot_symlink.txt
@@ -0,0 +1,62 @@
+# Regression test for https://go.dev/issue/57754: 'go list' failed if ../src
+# relative to the location of the go executable was a symlink to the real src
+# directory. (cmd/go expects that ../src is GOROOT/src, but it appears that the
+# Debian build of the Go toolchain is attempting to split GOROOT into binary and
+# source artifacts in different parent directories.)
+
+[short] skip 'copies the cmd/go binary'
+[!symlink] skip 'tests symlink-specific behavior'
+[GOOS:darwin] skip 'Lstat on darwin does not conform to POSIX pathname resolution; see #59586'
+[GOOS:ios] skip 'Lstat on ios does not conform to POSIX pathname resolution; see #59586'
+
+# Ensure that the relative path to $WORK/lib/goroot/src from $PWD is a different
+# number of ".." hops than the relative path to it from $WORK/share/goroot/src.
+
+cd $WORK
+
+# Construct a fake GOROOT in $WORK/lib/goroot whose src directory is a symlink
+# to a subdirectory of $WORK/share. This mimics the directory structure reported
+# in https://go.dev/issue/57754.
+#
+# Symlink everything else to the original $GOROOT to avoid needless copying work.
+
+mkdir $WORK/lib/goroot
+mkdir $WORK/share/goroot
+symlink $WORK/share/goroot/src -> $GOROOT${/}src
+symlink $WORK/lib/goroot/src -> ../../share/goroot/src
+symlink $WORK/lib/goroot/pkg -> $GOROOT${/}pkg
+
+# Verify that our symlink shenanigans don't prevent cmd/go from finding its
+# GOROOT using os.Executable.
+#
+# To do so, we copy the actual cmd/go executable — which is implemented as the
+# cmd/go test binary instead of the original $GOROOT/bin/go, which may be
+# arbitrarily stale — into the bin subdirectory of the fake GOROOT, causing
+# os.Executable to report a path in that directory.
+
+mkdir $WORK/lib/goroot/bin
+cp $TESTGO_EXE $WORK/lib/goroot/bin/go$GOEXE
+
+env GOROOT='' # Clear to force cmd/go to find GOROOT itself.
+exec $WORK/lib/goroot/bin/go env GOROOT
+stdout $WORK${/}lib${/}goroot
+
+# Now verify that 'go list' can find standard-library packages in the symlinked
+# source tree, with paths matching the one reported by 'go env GOROOT'.
+
+exec $WORK/lib/goroot/bin/go list -f '{{.ImportPath}}: {{.Dir}}' encoding/binary
+stdout '^encoding/binary: '$WORK${/}lib${/}goroot${/}src${/}encoding${/}binary'$'
+
+exec $WORK/lib/goroot/bin/go list -f '{{.ImportPath}}: {{.Dir}}' std
+stdout '^encoding/binary: '$WORK${/}lib${/}goroot${/}src${/}encoding${/}binary'$'
+
+# Most path lookups in GOROOT are not sensitive to symlinks. However, patterns
+# involving '...' wildcards must use Walk to check the GOROOT tree, which makes
+# them more sensitive to symlinks (because Walk doesn't follow them).
+#
+# So we check such a pattern to confirm that it works and reports a path relative
+# to $GOROOT/src (and not the symlink target).
+
+exec $WORK/lib/goroot/bin/go list -f '{{.ImportPath}}: {{.Dir}}' .../binary
+stdout '^encoding/binary: '$WORK${/}lib${/}goroot${/}src${/}encoding${/}binary'$'
+! stderr .
diff --git a/src/cmd/go/testdata/script/list_import_cycle_deps_errors.txt b/src/cmd/go/testdata/script/list_import_cycle_deps_errors.txt
new file mode 100644
index 0000000..e2c5cf9
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_import_cycle_deps_errors.txt
@@ -0,0 +1,75 @@
+go list -e -deps -json=ImportPath,Error,DepsErrors m/a
+cmp stdout want
+
+-- want --
+{
+ "ImportPath": "m/c",
+ "DepsErrors": [
+ {
+ "ImportStack": [
+ "m/a",
+ "m/b",
+ "m/c",
+ "m/a"
+ ],
+ "Pos": "",
+ "Err": "import cycle not allowed"
+ }
+ ]
+}
+{
+ "ImportPath": "m/b",
+ "DepsErrors": [
+ {
+ "ImportStack": [
+ "m/a",
+ "m/b",
+ "m/c",
+ "m/a"
+ ],
+ "Pos": "",
+ "Err": "import cycle not allowed"
+ }
+ ]
+}
+{
+ "ImportPath": "m/a",
+ "Error": {
+ "ImportStack": [
+ "m/a",
+ "m/b",
+ "m/c",
+ "m/a"
+ ],
+ "Pos": "",
+ "Err": "import cycle not allowed"
+ },
+ "DepsErrors": [
+ {
+ "ImportStack": [
+ "m/a",
+ "m/b",
+ "m/c",
+ "m/a"
+ ],
+ "Pos": "",
+ "Err": "import cycle not allowed"
+ }
+ ]
+}
+-- go.mod --
+module m
+
+go 1.21
+-- a/a.go --
+package a
+
+import _ "m/b"
+-- b/b.go --
+package b
+
+import _ "m/c"
+-- c/c.go --
+package c
+
+import _ "m/a" \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/list_import_err.txt b/src/cmd/go/testdata/script/list_import_err.txt
new file mode 100644
index 0000000..c2b7d7c
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_import_err.txt
@@ -0,0 +1,22 @@
+# Test that errors importing packages are reported on the importing package,
+# not the imported package.
+
+env GO111MODULE=off # simplify vendor layout for test
+
+go list -e -deps -f '{{.ImportPath}}: {{.Error}}' ./importvendor
+stdout 'importvendor: importvendor[\\/]p.go:2:8: vendor/p must be imported as p'
+stdout 'vendor/p: <nil>'
+
+go list -e -deps -f '{{.ImportPath}}: {{.Error}}' ./importinternal
+stdout 'importinternal: package importinternal\n\timportinternal[\\/]p.go:2:8: use of internal package other/internal/p not allowed'
+stdout 'other/internal/p: <nil>'
+-- importvendor/p.go --
+package importvendor
+import "vendor/p"
+-- importinternal/p.go --
+package importinternal
+import "other/internal/p"
+-- other/internal/p/p.go --
+package p
+-- vendor/p/p.go --
+package p \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/list_importmap.txt b/src/cmd/go/testdata/script/list_importmap.txt
new file mode 100644
index 0000000..3c59cfd
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_importmap.txt
@@ -0,0 +1,27 @@
+env GO111MODULE=off
+
+# gccgo does not have standard packages.
+[compiler:gccgo] skip
+
+# fmt should have no rewritten imports.
+# The import from a/b should map c/d to a's vendor directory.
+go list -f '{{.ImportPath}}: {{.ImportMap}}' fmt a/b
+stdout 'fmt: map\[\]'
+stdout 'a/b: map\[c/d:a/vendor/c/d\]'
+
+# flag [fmt.test] should import fmt [fmt.test] as fmt
+# fmt.test should import testing [fmt.test] as testing
+# fmt.test should not import a modified os
+go list -deps -test -f '{{.ImportPath}} MAP: {{.ImportMap}}{{"\n"}}{{.ImportPath}} IMPORT: {{.Imports}}' fmt
+stdout '^flag \[fmt\.test\] MAP: map\[fmt:fmt \[fmt\.test\]\]'
+stdout '^fmt\.test MAP: map\[(.* )?testing:testing \[fmt\.test\]'
+! stdout '^fmt\.test MAP: map\[(.* )?os:'
+stdout '^fmt\.test IMPORT: \[fmt \[fmt\.test\] fmt_test \[fmt\.test\] os reflect testing \[fmt\.test\] testing/internal/testdeps \[fmt\.test\]\]'
+
+
+-- a/b/b.go --
+package b
+
+import _ "c/d"
+-- a/vendor/c/d/d.go --
+package d
diff --git a/src/cmd/go/testdata/script/list_issue_56509.txt b/src/cmd/go/testdata/script/list_issue_56509.txt
new file mode 100644
index 0000000..b402b2b
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_issue_56509.txt
@@ -0,0 +1,35 @@
+# Test that a directory with an .s file that has a comment that can't
+# be parsed isn't matched as a go directory. (This was happening because
+# non-go files with unparsable comments were being added to InvalidGoFiles
+# leading the package matching code to think there were Go files in the
+# directory.)
+
+cd bar
+go list ./...
+! stdout .
+cd ..
+
+[short] skip
+
+# Test that an unparsable .s file is completely ignored when its name
+# has build tags that cause it to be filtered out, but produces an error
+# when it is included
+
+env GOARCH=arm64
+env GOOS=linux
+go build ./baz
+
+env GOARCH=amd64
+env GOOS=linux
+! go build ./baz
+
+-- go.mod --
+module example.com/foo
+
+go 1.20
+-- bar/bar.s --
+;/
+-- baz/baz.go --
+package bar
+-- baz/baz_amd64.s --
+;/
diff --git a/src/cmd/go/testdata/script/list_issue_59905.txt b/src/cmd/go/testdata/script/list_issue_59905.txt
new file mode 100644
index 0000000..48c40d0
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_issue_59905.txt
@@ -0,0 +1,88 @@
+# Expect no panic
+go list -f '{{if .DepsErrors}}{{.DepsErrors}}{{end}}' -export -e -deps
+cmpenv stdout wanterr_59905
+
+# Expect no panic (Issue 61816)
+cp level1b_61816.txt level1b/pkg.go
+go list -f '{{if .DepsErrors}}{{.DepsErrors}}{{end}}' -export -e -deps
+cmpenv stdout wanterr_61816
+
+-- wanterr_59905 --
+[# test/main/level1a
+level1a${/}pkg.go:5:2: level2x redeclared in this block
+ level1a${/}pkg.go:4:2: other declaration of level2x
+level1a${/}pkg.go:5:2: "test/main/level1a/level2y" imported as level2x and not used
+level1a${/}pkg.go:8:39: undefined: level2y
+ # test/main/level1b
+level1b${/}pkg.go:5:2: level2x redeclared in this block
+ level1b${/}pkg.go:4:2: other declaration of level2x
+level1b${/}pkg.go:5:2: "test/main/level1b/level2y" imported as level2x and not used
+level1b${/}pkg.go:8:39: undefined: level2y
+]
+-- wanterr_61816 --
+[level1b${/}pkg.go:4:2: package foo is not in std ($GOROOT${/}src${/}foo)]
+[# test/main/level1a
+level1a${/}pkg.go:5:2: level2x redeclared in this block
+ level1a${/}pkg.go:4:2: other declaration of level2x
+level1a${/}pkg.go:5:2: "test/main/level1a/level2y" imported as level2x and not used
+level1a${/}pkg.go:8:39: undefined: level2y
+ level1b${/}pkg.go:4:2: package foo is not in std ($GOROOT${/}src${/}foo)]
+-- level1b_61816.txt --
+package level1b
+
+import (
+ "foo"
+)
+
+func Print() { println(level2x.Value, level2y.Value) }
+
+-- go.mod --
+module test/main
+
+go 1.20
+-- main.go --
+package main
+
+import (
+ "test/main/level1a"
+ "test/main/level1b"
+)
+
+func main() {
+ level1a.Print()
+ level1b.Print()
+}
+-- level1a/pkg.go --
+package level1a
+
+import (
+ "test/main/level1a/level2x"
+ "test/main/level1a/level2y"
+)
+
+func Print() { println(level2x.Value, level2y.Value) }
+-- level1a/level2x/pkg.go --
+package level2x
+
+var Value = "1a/2x"
+-- level1a/level2y/pkg.go --
+package level2x
+
+var Value = "1a/2y"
+-- level1b/pkg.go --
+package level1b
+
+import (
+ "test/main/level1b/level2x"
+ "test/main/level1b/level2y"
+)
+
+func Print() { println(level2x.Value, level2y.Value) }
+-- level1b/level2x/pkg.go --
+package level2x
+
+var Value = "1b/2x"
+-- level1b/level2y/pkg.go --
+package level2x
+
+var Value = "1b/2y" \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/list_json_fields.txt b/src/cmd/go/testdata/script/list_json_fields.txt
new file mode 100644
index 0000000..7e008ea
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_json_fields.txt
@@ -0,0 +1,113 @@
+# Test using -json flag to specify specific fields.
+
+# Test -json produces "full" output by looking for multiple fields present.
+go list -json .
+stdout '"Name": "a"'
+stdout '"Stale": true'
+# Same thing for -json=true
+go list -json=true .
+stdout '"Name": "a"'
+stdout '"Stale": true'
+
+# Test -json=false produces non-json output.
+go list -json=false
+cmp stdout want-non-json.txt
+
+# Test -json=<field> keeps only that field.
+go list -json=Name
+cmp stdout want-json-name.txt
+
+# Test -json=<field> with multiple fields.
+go list -json=ImportPath,Name,GoFiles,Imports
+cmp stdout want-json-multiple.txt
+
+# Test -json=<field> with Deps outputs the Deps field.
+go list -json=Deps
+stdout '"Deps": \['
+stdout '"errors",'
+
+# Test -json=<field> with *EmbedPatterns outputs embed patterns.
+cd embed
+go list -json=EmbedPatterns,TestEmbedPatterns,XTestEmbedPatterns
+stdout '"EmbedPatterns": \['
+stdout '"TestEmbedPatterns": \['
+stdout '"XTestEmbedPatterns": \['
+# Test -json=<field> with *EmbedFiles fails due to broken file reference.
+! go list -json=EmbedFiles
+stderr 'no matching files found'
+! go list -json=TestEmbedFiles
+stderr 'no matching files found'
+! go list -json=XTestEmbedFiles
+stderr 'no matching files found'
+cd ..
+
+[!git] skip
+
+# Test -json=<field> without Stale skips computing buildinfo
+cd repo
+exec git init
+# Control case: with -json=Stale cmd/go executes git status to compute buildinfo
+go list -json=Stale -x
+stderr 'git status'
+# Test case: without -json=Stale cmd/go skips git status
+go list -json=Name -x
+! stderr 'git status'
+
+-- go.mod --
+module example.com/a
+
+go 1.18
+-- a.go --
+package a
+
+import "fmt"
+
+func F() {
+ fmt.Println("hey there")
+}
+-- want-non-json.txt --
+example.com/a
+-- want-json-name.txt --
+{
+ "Name": "a"
+}
+-- want-json-multiple.txt --
+{
+ "ImportPath": "example.com/a",
+ "Name": "a",
+ "GoFiles": [
+ "a.go"
+ ],
+ "Imports": [
+ "fmt"
+ ]
+}
+-- repo/go.mod --
+module example.com/repo
+-- repo/main.go --
+package main
+
+func main() {}
+-- embed/go.mod --
+module example.com/embed
+-- embed/embed.go --
+package embed
+
+import _ "embed"
+
+//go:embed non-existing-file.txt
+var s string
+-- embed/embed_test.go --
+package embed
+
+import _ "embed"
+
+//go:embed non-existing-file.txt
+var s string
+-- embed/embed_xtest_test.go --
+package embed_test
+
+import _ "embed"
+
+//go:embed non-existing-file.txt
+var s string
diff --git a/src/cmd/go/testdata/script/list_json_with_f.txt b/src/cmd/go/testdata/script/list_json_with_f.txt
new file mode 100644
index 0000000..2011a6e
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_json_with_f.txt
@@ -0,0 +1,20 @@
+[short] skip
+
+# list -json should generate output on stdout
+go list -json ./...
+stdout .
+# list -f should generate output on stdout
+go list -f '{{.}}' ./...
+stdout .
+
+# test passing first -json then -f
+! go list -json -f '{{.}}' ./...
+stderr '^go list -f cannot be used with -json$'
+
+# test passing first -f then -json
+! go list -f '{{.}}' -json ./...
+stderr '^go list -f cannot be used with -json$'
+-- go.mod --
+module m
+-- list_test.go --
+package list_test
diff --git a/src/cmd/go/testdata/script/list_legacy_mod.txt b/src/cmd/go/testdata/script/list_legacy_mod.txt
new file mode 100644
index 0000000..ab901d7
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_legacy_mod.txt
@@ -0,0 +1,48 @@
+# In GOPATH mode, module legacy support does path rewriting very similar to vendoring.
+
+env GO111MODULE=off
+
+go list -f '{{range .Imports}}{{.}}{{"\n"}}{{end}}' old/p1
+stdout ^new/p1$
+
+go list -f '{{range .Imports}}{{.}}{{"\n"}}{{end}}' new/p1
+stdout ^new/p2$ # not new/v2/p2
+! stdout ^new/v2
+stdout ^new/sub/x/v1/y$ # not new/sub/v2/x/v1/y
+! stdout ^new/sub/v2
+stdout ^new/sub/inner/x # not new/sub/v2/inner/x
+
+go build old/p1 new/p1
+
+-- new/go.mod --
+module "new/v2"
+-- new/new.go --
+package new
+
+import _ "new/v2/p2"
+-- new/p1/p1.go --
+package p1
+
+import _ "old/p2"
+import _ "new/v2"
+import _ "new/v2/p2"
+import _ "new/sub/v2/x/v1/y" // v2 is module, v1 is directory in module
+import _ "new/sub/inner/x" // new/sub/inner/go.mod overrides new/sub/go.mod
+-- new/p2/p2.go --
+package p2
+-- new/sub/go.mod --
+module new/sub/v2
+-- new/sub/inner/go.mod --
+module new/sub/inner
+-- new/sub/inner/x/x.go --
+package x
+-- new/sub/x/v1/y/y.go --
+package y
+-- old/p1/p1.go --
+package p1
+
+import _ "old/p2"
+import _ "new/p1"
+import _ "new"
+-- old/p2/p2.go --
+package p2
diff --git a/src/cmd/go/testdata/script/list_linkshared.txt b/src/cmd/go/testdata/script/list_linkshared.txt
new file mode 100644
index 0000000..baae1e2
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_linkshared.txt
@@ -0,0 +1,16 @@
+env GO111MODULE=on
+
+# golang.org/issue/35759: 'go list -linkshared'
+# panicked if invoked on a test-only package.
+
+[!buildmode:shared] skip
+
+go list -f '{{.ImportPath}}: {{.Target}} {{.Shlib}}' -linkshared .
+stdout '^example.com: $'
+
+-- go.mod --
+module example.com
+
+go 1.14
+-- x.go --
+package x
diff --git a/src/cmd/go/testdata/script/list_load_err.txt b/src/cmd/go/testdata/script/list_load_err.txt
new file mode 100644
index 0000000..f1b9205
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_load_err.txt
@@ -0,0 +1,95 @@
+# go list -e -deps should list imports from any file it can read, even if
+# other files in the same package cause go/build.Import to return an error.
+# Verifies golang.org/issue/38568
+
+go list -e -deps ./scan
+stdout m/want
+
+go list -e -deps ./multi
+stdout m/want
+
+go list -e -deps ./constraint
+stdout m/want
+
+[cgo] go list -e -test -deps ./cgotest
+[cgo] stdout m/want
+
+[cgo] go list -e -deps ./cgoflag
+[cgo] stdout m/want
+
+
+# go list -e should include files with errors in GoFiles, TestGoFiles, and
+# other lists, assuming they match constraints.
+# Verifies golang.org/issue/39986
+go list -e -f '{{range .GoFiles}}{{.}},{{end}}' ./scan
+stdout '^good.go,scan.go,$'
+
+go list -e -f '{{range .GoFiles}}{{.}},{{end}}' ./multi
+stdout '^a.go,b.go,$'
+
+go list -e -f '{{range .GoFiles}}{{.}},{{end}}' ./constraint
+stdout '^good.go,$'
+go list -e -f '{{range .IgnoredGoFiles}}{{.}},{{end}}' ./constraint
+stdout '^constraint.go,$'
+
+[cgo] go list -e -f '{{range .XTestGoFiles}}{{.}},{{end}}' ./cgotest
+[cgo] stdout '^cgo_test.go,$'
+
+[cgo] go list -e -f '{{range .GoFiles}}{{.}},{{end}}' ./cgoflag
+[cgo] stdout '^cgoflag.go,$'
+
+-- go.mod --
+module m
+
+go 1.14
+
+-- want/want.go --
+package want
+
+-- scan/scan.go --
+// scan error
+ʕ◔ϖ◔ʔ
+
+-- scan/good.go --
+package scan
+
+import _ "m/want"
+
+-- multi/a.go --
+package a
+
+-- multi/b.go --
+package b
+
+import _ "m/want"
+
+-- constraint/constraint.go --
+// +build !!nope
+
+package constraint
+
+-- constraint/good.go --
+package constraint
+
+import _ "m/want"
+
+-- cgotest/cgo_test.go --
+package cgo_test
+
+// cgo is not allowed in tests.
+// See golang.org/issue/18647
+
+import "C"
+import (
+ "testing"
+ _ "m/want"
+)
+
+func Test(t *testing.T) {}
+
+-- cgoflag/cgoflag.go --
+package cgoflag
+
+// #cgo ʕ◔ϖ◔ʔ:
+
+import _ "m/want"
diff --git a/src/cmd/go/testdata/script/list_module_when_error.txt b/src/cmd/go/testdata/script/list_module_when_error.txt
new file mode 100644
index 0000000..844164c
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_module_when_error.txt
@@ -0,0 +1,19 @@
+# The Module field should be populated even if there is an error loading the package.
+
+env GO111MODULE=on
+
+go list -e -f {{.Module}}
+stdout '^mod.com$'
+
+-- go.mod --
+module mod.com
+
+go 1.16
+
+-- blah.go --
+package blah
+
+import _ "embed"
+
+//go:embed README.md
+var readme string
diff --git a/src/cmd/go/testdata/script/list_overlay.txt b/src/cmd/go/testdata/script/list_overlay.txt
new file mode 100644
index 0000000..1153975
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_overlay.txt
@@ -0,0 +1,63 @@
+# Test listing with overlays
+
+# Overlay in an existing directory
+go list -overlay overlay.json -f '{{.GoFiles}}' .
+stdout '^\[f.go\]$'
+
+# Overlays in a non-existing directory
+go list -overlay overlay.json -f '{{.GoFiles}}' ./dir
+stdout '^\[g.go\]$'
+
+# Overlays in an existing directory with already existing files
+go list -overlay overlay.json -f '{{.GoFiles}}' ./dir2
+stdout '^\[h.go i.go\]$'
+
+# Overlay that removes a file from a directory
+! go list ./dir3 # contains a file without a package statement
+go list -overlay overlay.json -f '{{.GoFiles}}' ./dir3 # overlay removes that file
+
+# Walking through an overlay
+go list -overlay overlay.json ./...
+cmp stdout want-list.txt
+
+# TODO(#39958): assembly files, C files, files that require cgo preprocessing
+
+-- want-list.txt --
+m
+m/dir
+m/dir2
+m/dir3
+-- go.mod --
+// TODO(#39958): Support and test overlays including go.mod itself (especially if mod=readonly)
+module m
+
+go 1.16
+
+-- dir2/h.go --
+package dir2
+
+-- dir3/good.go --
+package dir3
+-- dir3/bad.go --
+// no package statement
+-- overlay.json --
+{
+ "Replace": {
+ "f.go": "overlay/f_go",
+ "dir/g.go": "overlay/dir_g_go",
+ "dir2/i.go": "overlay/dir2_i_go",
+ "dir3/bad.go": ""
+ }
+}
+-- overlay/f_go --
+package m
+
+func f() {
+}
+-- overlay/dir_g_go --
+package m
+
+func g() {
+}
+-- overlay/dir2_i_go --
+package dir2
diff --git a/src/cmd/go/testdata/script/list_parse_err.txt b/src/cmd/go/testdata/script/list_parse_err.txt
new file mode 100644
index 0000000..0a3eb02
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_parse_err.txt
@@ -0,0 +1,45 @@
+# 'go list' without -e should fail and print errors on stderr.
+! go list ./p
+stderr '^p[/\\]b.go:2:2: expected ''package'', found ''EOF''$'
+! go list -f '{{range .Imports}}{{.}} {{end}}' ./p
+stderr '^p[/\\]b.go:2:2: expected ''package'', found ''EOF''$'
+! go list -test ./t
+stderr '^go: can''t load test package: t[/\\]t_test.go:8:1: expected declaration, found ʕ'
+! go list -test -f '{{range .Imports}}{{.}} {{end}}' ./t
+stderr '^go: can''t load test package: t[/\\]t_test.go:8:1: expected declaration, found ʕ'
+
+# 'go list -e' should report imports, even if some files have parse errors
+# before the import block.
+go list -e -f '{{range .Imports}}{{.}} {{end}}' ./p
+stdout '^fmt '
+
+# 'go list' should report the position of the error if there's only one.
+go list -e -f '{{.Error.Pos}} => {{.Error.Err}}' ./p
+stdout 'b.go:[0-9:]+ => expected ''package'', found ''EOF'''
+
+# 'go test' should report the position of the error if there's only one.
+go list -e -test -f '{{if .Error}}{{.Error.Pos}} => {{.Error.Err}}{{end}}' ./t
+stdout 't_test.go:[0-9:]+ => expected declaration, found ʕ'
+
+-- go.mod --
+module m
+
+go 1.13
+
+-- p/a.go --
+package a
+
+import "fmt"
+
+-- p/b.go --
+// no package statement
+
+-- t/t_test.go --
+package t
+
+import "testing"
+
+func Test(t *testing.T) {}
+
+// scan error
+ʕ◔ϖ◔ʔ
diff --git a/src/cmd/go/testdata/script/list_perm.txt b/src/cmd/go/testdata/script/list_perm.txt
new file mode 100644
index 0000000..14d6f72
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_perm.txt
@@ -0,0 +1,83 @@
+env GO111MODULE=on
+
+# Establish baseline behavior, before mucking with file permissions.
+
+go list ./noread/...
+stdout '^example.com/noread$'
+
+go list example.com/noread/...
+stdout '^example.com/noread$'
+
+go list ./empty/...
+stderr 'matched no packages'
+
+# Make the directory ./noread unreadable, and verify that 'go list' reports an
+# explicit error for a pattern that should match it (rather than treating it as
+# equivalent to an empty directory).
+
+[root] stop # Root typically ignores file permissions.
+[GOOS:windows] skip # Does not have Unix-style directory permissions.
+[GOOS:plan9] skip # Might not have Unix-style directory permissions.
+
+chmod 000 noread
+
+# Check explicit paths.
+
+! go list ./noread
+! stdout '^example.com/noread$'
+! stderr 'matched no packages'
+
+! go list example.com/noread
+! stdout '^example.com/noread$'
+! stderr 'matched no packages'
+
+# Check filesystem-relative patterns.
+
+! go list ./...
+! stdout '^example.com/noread$'
+! stderr 'matched no packages'
+stderr '^pattern ./...: '
+
+! go list ./noread/...
+! stdout '^example.com/noread$'
+! stderr 'matched no packages'
+stderr '^pattern ./noread/...: '
+
+
+# Check module-prefix patterns.
+
+! go list example.com/...
+! stdout '^example.com/noread$'
+! stderr 'matched no packages'
+stderr '^pattern example.com/...: '
+
+! go list example.com/noread/...
+! stdout '^example.com/noread$'
+! stderr 'matched no packages'
+stderr '^pattern example.com/noread/...: '
+
+
+[short] stop
+
+# Check global patterns, which should still
+# fail due to errors in the local module.
+
+! go list all
+! stdout '^example.com/noread$'
+! stderr 'matched no packages'
+stderr '^pattern all: '
+
+! go list ...
+! stdout '^example.com/noread$'
+! stderr 'matched no packages'
+stderr '^pattern ...: '
+
+
+-- go.mod --
+module example.com
+go 1.15
+-- noread/noread.go --
+// Package noread exists, but will be made unreadable.
+package noread
+-- empty/README.txt --
+This directory intentionally left empty.
diff --git a/src/cmd/go/testdata/script/list_pkgconfig_error.txt b/src/cmd/go/testdata/script/list_pkgconfig_error.txt
new file mode 100644
index 0000000..f554d2a
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_pkgconfig_error.txt
@@ -0,0 +1,16 @@
+[!cgo] skip 'test verifies cgo pkg-config errors'
+[!exec:pkg-config] skip 'test requires pkg-config tool'
+
+! go list -export .
+stderr '^# example\n# \[pkg-config .*\]\n(.*\n)*Package .* not found'
+
+-- go.mod --
+module example
+go 1.20
+-- example.go --
+package example
+
+// #cgo pkg-config: libnot-a-valid-cgo-library
+import "C"
+
+package main() {}
diff --git a/src/cmd/go/testdata/script/list_replace_absolute_windows.txt b/src/cmd/go/testdata/script/list_replace_absolute_windows.txt
new file mode 100644
index 0000000..8b71921
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_replace_absolute_windows.txt
@@ -0,0 +1,38 @@
+# Test a replacement with an absolute path (so the path isn't
+# cleaned by having filepath.Abs called on it). This checks
+# whether the modindex logic cleans the modroot path before using
+# it.
+
+[!GOOS:windows] skip
+[short] skip
+
+go run print_go_mod.go # use this program to write a go.mod with an absolute path
+cp stdout go.mod
+
+go list -modfile=go.mod all
+-- print_go_mod.go --
+//go:build ignore
+package main
+
+import (
+ "fmt"
+ "os"
+)
+
+func main() {
+ work := os.Getenv("WORK")
+fmt.Printf(`module example.com/mod
+
+require b.com v0.0.0
+
+replace b.com => %s\gopath\src/modb
+`, work)
+}
+-- a.go --
+package a
+
+import _ "b.com/b"
+-- modb/go.mod --
+module b.com
+-- modb/b/b.go --
+package b
diff --git a/src/cmd/go/testdata/script/list_reserved.txt b/src/cmd/go/testdata/script/list_reserved.txt
new file mode 100644
index 0000000..b9c5361
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_reserved.txt
@@ -0,0 +1,7 @@
+# https://golang.org/issue/37641: the paths "example" and "test" are reserved
+# for end users, and must never exist in the standard library.
+
+go list example/... test/...
+stderr 'go: warning: "example/..." matched no packages$'
+stderr 'go: warning: "test/..." matched no packages$'
+! stdout .
diff --git a/src/cmd/go/testdata/script/list_shadow.txt b/src/cmd/go/testdata/script/list_shadow.txt
new file mode 100644
index 0000000..660508d
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_shadow.txt
@@ -0,0 +1,25 @@
+env GO111MODULE=off
+env GOPATH=$WORK/gopath/src/shadow/root1${:}$WORK/gopath/src/shadow/root2
+
+# The math in root1 is not "math" because the standard math is.
+go list -f '({{.ImportPath}}) ({{.ConflictDir}})' ./shadow/root1/src/math
+stdout '^\(.*(\\|/)src(\\|/)shadow(\\|/)root1(\\|/)src(\\|/)math\) \('$GOROOT'(\\|/)?src(\\|/)math\)$'
+
+# The foo in root1 is "foo".
+go list -f '({{.ImportPath}}) ({{.ConflictDir}})' ./shadow/root1/src/foo
+stdout '^\(foo\) \(\)$'
+
+# The foo in root2 is not "foo" because the foo in root1 got there first.
+go list -f '({{.ImportPath}}) ({{.ConflictDir}})' ./shadow/root2/src/foo
+stdout '^\(.*gopath(\\|/)src(\\|/)shadow(\\|/)root2(\\|/)src(\\|/)foo\) \('$WORK'(\\|/)?gopath(\\|/)src(\\|/)shadow(\\|/)root1(\\|/)src(\\|/)foo\)$'
+
+# The error for go install should mention the conflicting directory.
+! go install -n ./shadow/root2/src/foo
+stderr 'go: no install location for '$WORK'(\\|/)?gopath(\\|/)src(\\|/)shadow(\\|/)root2(\\|/)src(\\|/)foo: hidden by '$WORK'(\\|/)?gopath(\\|/)src(\\|/)shadow(\\|/)root1(\\|/)src(\\|/)foo'
+
+-- shadow/root1/src/foo/foo.go --
+package foo
+-- shadow/root1/src/math/math.go --
+package math
+-- shadow/root2/src/foo/foo.go --
+package foo \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/list_split_main.txt b/src/cmd/go/testdata/script/list_split_main.txt
new file mode 100644
index 0000000..74e7d5d
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_split_main.txt
@@ -0,0 +1,25 @@
+# This test checks that a "main" package with an external test package
+# is recompiled only once.
+# Verifies golang.org/issue/34321.
+
+env GO111MODULE=off
+
+go list -e -test -deps -f '{{if not .Standard}}{{.ImportPath}}{{end}}' pkg
+cmp stdout want
+
+-- $GOPATH/src/pkg/pkg.go --
+package main
+
+func main() {}
+
+-- $GOPATH/src/pkg/pkg_test.go --
+package main
+
+import "testing"
+
+func Test(t *testing.T) {}
+
+-- want --
+pkg
+pkg [pkg.test]
+pkg.test
diff --git a/src/cmd/go/testdata/script/list_std.txt b/src/cmd/go/testdata/script/list_std.txt
new file mode 100644
index 0000000..64c4766
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_std.txt
@@ -0,0 +1,25 @@
+env GO111MODULE=off
+
+[!compiler:gc] skip
+[short] skip
+
+# Listing GOROOT should only find standard packages.
+cd $GOROOT/src
+go list -f '{{if not .Standard}}{{.ImportPath}}{{end}}' ./...
+! stdout .
+
+# Standard packages should include cmd, but not cmd/vendor.
+go list ./...
+stdout cmd/compile
+! stdout vendor/golang.org
+! stdout cmd/vendor
+
+# In GOPATH mode, packages vendored into GOROOT should be reported as standard.
+go list -f '{{if .Standard}}{{.ImportPath}}{{end}}' std cmd
+stdout golang.org/x/net/http2/hpack
+stdout cmd/vendor/golang\.org/x/arch/x86/x86asm
+
+# However, vendored packages should not match wildcard patterns beginning with cmd.
+go list cmd/...
+stdout cmd/compile
+! stdout cmd/vendor
diff --git a/src/cmd/go/testdata/script/list_std_vendor.txt b/src/cmd/go/testdata/script/list_std_vendor.txt
new file mode 100644
index 0000000..834babe
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_std_vendor.txt
@@ -0,0 +1,33 @@
+# https://golang.org/issue/44725: packages in std should have the same
+# dependencies regardless of whether they are listed from within or outside
+# GOROOT/src.
+
+# Control case: net, viewed from outside the 'std' module,
+# should depend on vendor/golang.org/… instead of golang.org/….
+
+go list -deps net
+stdout '^vendor/golang.org/x/net'
+! stdout '^golang.org/x/net'
+cp stdout $WORK/net-deps.txt
+
+
+# It should still report the same package dependencies when viewed from
+# within GOROOT/src.
+
+cd $GOROOT/src
+
+go list -deps net
+stdout '^vendor/golang.org/x/net'
+! stdout '^golang.org/x/net'
+cmp stdout $WORK/net-deps.txt
+
+
+# However, 'go mod' and 'go get' subcommands should report the original module
+# dependencies, not the vendored packages.
+
+[!net:golang.org] stop
+
+env GOPROXY=
+env GOWORK=off
+go mod why -m golang.org/x/net
+stdout '^# golang.org/x/net\nnet\ngolang.org/x/net'
diff --git a/src/cmd/go/testdata/script/list_swigcxx.txt b/src/cmd/go/testdata/script/list_swigcxx.txt
new file mode 100644
index 0000000..731c1e5
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_swigcxx.txt
@@ -0,0 +1,30 @@
+# go list should not report SWIG-generated C++ files in CompiledGoFiles.
+
+[!exec:swig] skip
+[!exec:g++] skip
+[!cgo] skip
+
+# CompiledGoFiles should contain 4 files:
+# a.go
+# _cgo_import.go [gc only]
+# _cgo_gotypes.go
+# a.cgo1.go
+#
+# These names we see here, other than a.go, will be from the build cache,
+# so we just count them.
+
+go list -f '{{.CompiledGoFiles}}' -compiled=true example/swig
+
+stdout a\.go
+[compiler:gc] stdout -count=3 $GOCACHE
+[compiler:gccgo] stdout -count=2 $GOCACHE
+
+-- go.mod --
+module example
+
+go 1.16
+
+-- swig/a.go --
+package swig
+
+-- swig/a.swigcxx --
diff --git a/src/cmd/go/testdata/script/list_symlink.txt b/src/cmd/go/testdata/script/list_symlink.txt
new file mode 100644
index 0000000..f74ca86
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_symlink.txt
@@ -0,0 +1,12 @@
+[!symlink] skip
+env GO111MODULE=off
+
+mkdir $WORK/tmp/src
+symlink $WORK/tmp/src/dir1 -> $WORK/tmp
+cp p.go $WORK/tmp/src/dir1/p.go
+env GOPATH=$WORK/tmp
+go list -f '{{.Root}}' dir1
+stdout '^'$WORK/tmp'$'
+
+-- p.go --
+package p
diff --git a/src/cmd/go/testdata/script/list_symlink_dotdotdot.txt b/src/cmd/go/testdata/script/list_symlink_dotdotdot.txt
new file mode 100644
index 0000000..8df1982
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_symlink_dotdotdot.txt
@@ -0,0 +1,20 @@
+[!symlink] skip
+
+symlink $WORK/gopath/src/sym -> $WORK/gopath/src/tree
+symlink $WORK/gopath/src/tree/squirrel -> $WORK/gopath/src/dir2 # this symlink should not be followed
+cd sym
+go list ./...
+cmp stdout $WORK/gopath/src/want_list.txt
+-- tree/go.mod --
+module example.com/tree
+
+go 1.20
+-- tree/tree.go --
+package tree
+-- tree/branch/branch.go --
+package branch
+-- dir2/squirrel.go --
+package squirrel
+-- want_list.txt --
+example.com/tree
+example.com/tree/branch
diff --git a/src/cmd/go/testdata/script/list_symlink_internal.txt b/src/cmd/go/testdata/script/list_symlink_internal.txt
new file mode 100644
index 0000000..f756a56
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_symlink_internal.txt
@@ -0,0 +1,27 @@
+[!symlink] skip
+env GO111MODULE=off
+
+mkdir $WORK/tmp/gopath/src/dir1/internal/v
+cp p.go $WORK/tmp/gopath/src/dir1/p.go
+cp v.go $WORK/tmp/gopath/src/dir1/internal/v/v.go
+symlink $WORK/tmp/symdir1 -> $WORK/tmp/gopath/src/dir1
+env GOPATH=$WORK/tmp/gopath
+cd $WORK/tmp/symdir1
+go list -f '{{.Root}}' .
+stdout '^'$WORK/tmp/gopath'$'
+
+# All of these should succeed, not die in internal-handling code.
+go run p.go &
+go build &
+go install &
+
+wait
+
+-- p.go --
+package main
+
+import _ `dir1/internal/v`
+
+func main() {}
+-- v.go --
+package v
diff --git a/src/cmd/go/testdata/script/list_symlink_issue35941.txt b/src/cmd/go/testdata/script/list_symlink_issue35941.txt
new file mode 100644
index 0000000..eb12bde
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_symlink_issue35941.txt
@@ -0,0 +1,18 @@
+[!symlink] skip
+env GO111MODULE=off
+
+# Issue 35941: suppress symlink warnings when running 'go list all'.
+symlink goproj/css -> $GOPATH/src/css
+
+go list all
+! stderr 'warning: ignoring symlink'
+
+# Show symlink warnings when patterns contain '...'.
+go list goproj/...
+stderr 'warning: ignoring symlink'
+
+-- goproj/a.go --
+package a
+
+-- css/index.css --
+body {}
diff --git a/src/cmd/go/testdata/script/list_symlink_vendor_issue14054.txt b/src/cmd/go/testdata/script/list_symlink_vendor_issue14054.txt
new file mode 100644
index 0000000..8e63a5a
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_symlink_vendor_issue14054.txt
@@ -0,0 +1,28 @@
+[!symlink] skip
+env GO111MODULE=off
+
+mkdir $WORK/tmp/gopath/src/dir1/vendor/v
+cp p.go $WORK/tmp/gopath/src/dir1/p.go
+cp v.go $WORK/tmp/gopath/src/dir1/vendor/v/v.go
+symlink $WORK/tmp/symdir1 -> $WORK/tmp/gopath/src/dir1
+env GOPATH=$WORK/tmp/gopath
+cd $WORK/tmp/symdir1
+
+go list -f '{{.Root}}' .
+stdout '^'$WORK/tmp/gopath'$'
+
+# All of these should succeed, not die in vendor-handling code.
+go run p.go &
+go build &
+go install &
+
+wait
+
+-- p.go --
+package main
+
+import _ `v`
+
+func main () {}
+-- v.go --
+package v
diff --git a/src/cmd/go/testdata/script/list_symlink_vendor_issue15201.txt b/src/cmd/go/testdata/script/list_symlink_vendor_issue15201.txt
new file mode 100644
index 0000000..19f2138
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_symlink_vendor_issue15201.txt
@@ -0,0 +1,21 @@
+[!symlink] skip
+env GO111MODULE=off
+
+mkdir $WORK/tmp/gopath/src/x/y/_vendor/src/x
+symlink $WORK/tmp/gopath/src/x/y/_vendor/src/x/y -> ../../..
+mkdir $WORK/tmp/gopath/src/x/y/_vendor/src/x/y/w
+cp w.go $WORK/tmp/gopath/src/x/y/w/w.go
+symlink $WORK/tmp/gopath/src/x/y/w/vendor -> ../_vendor/src
+mkdir $WORK/tmp/gopath/src/x/y/_vendor/src/x/y/z
+cp z.go $WORK/tmp/gopath/src/x/y/z/z.go
+
+env GOPATH=$WORK/tmp/gopath/src/x/y/_vendor${:}$WORK/tmp/gopath
+cd $WORK/tmp/gopath/src
+go list ./...
+
+-- w.go --
+package w
+
+import "x/y/z"
+-- z.go --
+package z
diff --git a/src/cmd/go/testdata/script/list_test_cycle.txt b/src/cmd/go/testdata/script/list_test_cycle.txt
new file mode 100644
index 0000000..67edf18
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_test_cycle.txt
@@ -0,0 +1,34 @@
+go list ./p
+stdout 'example/p'
+
+! go list -json=ImportPath -test ./p
+cmp stderr wanterr.txt
+
+! go list -json=ImportPath,Deps -test ./p
+cmp stderr wanterr.txt
+
+! go list -json=ImportPath,Deps -deps -test ./p
+cmp stderr wanterr.txt
+
+! go list -json=ImportPath -deps -test ./p
+cmp stderr wanterr.txt
+
+-- wanterr.txt --
+go: can't load test package: package example/p
+ imports example/q
+ imports example/r
+ imports example/p: import cycle not allowed in test
+-- go.mod --
+module example
+go 1.20
+-- p/p.go --
+package p
+-- p/p_test.go --
+package p
+import "example/q"
+-- q/q.go --
+package q
+import "example/r"
+-- r/r.go --
+package r
+import "example/p"
diff --git a/src/cmd/go/testdata/script/list_test_e.txt b/src/cmd/go/testdata/script/list_test_e.txt
new file mode 100644
index 0000000..263892b
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_test_e.txt
@@ -0,0 +1,11 @@
+env GO111MODULE=off
+
+# issue 25980: crash in go list -e -test
+go list -e -test -deps -f '{{.Error}}' p
+stdout '^p[/\\]d_test.go:2:8: cannot find package "d" in any of:'
+
+-- p/d.go --
+package d
+-- p/d_test.go --
+package d_test
+import _ "d"
diff --git a/src/cmd/go/testdata/script/list_test_err.txt b/src/cmd/go/testdata/script/list_test_err.txt
new file mode 100644
index 0000000..02bd6a1
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_test_err.txt
@@ -0,0 +1,118 @@
+env GO111MODULE=off
+
+# issue 28491: errors in test source files should not prevent
+# "go list -test" from returning useful information.
+
+# go list -e prints information for all test packages.
+# The syntax error is shown in the package error field.
+go list -e -test -deps -f '{{.ImportPath}} {{.Error | printf "%q"}}' syntaxerr
+stdout 'pkgdep <nil>'
+stdout 'testdep_a <nil>'
+stdout 'testdep_b <nil>'
+stdout 'syntaxerr <nil>'
+stdout 'syntaxerr \[syntaxerr.test\] <nil>'
+stdout 'syntaxerr_test \[syntaxerr.test\] <nil>'
+stdout 'syntaxerr\.test "[^"]*expected declaration'
+! stderr 'expected declaration'
+
+[short] stop
+
+go list -e -test -deps -f '{{.ImportPath}} {{.Error | printf "%q"}}' nameerr
+stdout 'pkgdep <nil>'
+stdout 'testdep_a <nil>'
+stdout 'testdep_b <nil>'
+stdout 'nameerr\.test "[^"]*wrong signature for TestBad'
+! stderr 'wrong signature for TestBad'
+
+# go list prints a useful error for generic test functions
+! go list -test -deps genericerr
+stderr 'wrong signature for TestGeneric, test functions cannot have type parameters'
+
+go list -e -test -deps -f '{{.ImportPath}} {{.Error | printf "%q"}}' cycleerr
+stdout 'cycleerr <nil>'
+stdout 'testdep_a <nil>'
+stdout 'testdep_cycle \[cycleerr.test\] <nil>'
+stdout 'cycleerr \[cycleerr.test\] "[^"]*import cycle not allowed in test'
+! stderr 'import cycle not allowed in test'
+
+-- syntaxerr/syntaxerr.go --
+package syntaxerr
+
+import _ "pkgdep"
+
+-- syntaxerr/syntaxerr_ie_test.go --
+package syntaxerr
+
+!!!syntax error
+
+-- syntaxerr/syntaxerr_xe_test.go --
+package syntaxerr_test
+
+!!!syntax error
+
+-- syntaxerr/syntaxerr_i_test.go --
+package syntaxerr
+
+import _ "testdep_a"
+
+-- syntaxerr/syntaxerr_x_test.go --
+package syntaxerr
+
+import _ "testdep_b"
+
+-- nameerr/nameerr.go --
+package nameerr
+
+import _ "pkgdep"
+
+-- nameerr/nameerr_i_test.go --
+package nameerr
+
+import (
+ _ "testdep_a"
+ "testing"
+)
+
+func TestBad(t *testing.B) {}
+
+-- nameerr/nameerr_x_test.go --
+package nameerr_test
+
+import (
+ _ "testdep_b"
+ "testing"
+)
+
+func TestBad(t *testing.B) {}
+
+-- genericerr/genericerr.go --
+package genericerr
+
+-- genericerr/genericerr_test.go --
+package genericerr
+
+import "testing"
+
+func TestGeneric[T any](t *testing.T) {}
+
+-- cycleerr/cycleerr_test.go --
+package cycleerr
+
+import (
+ _ "testdep_a"
+ _ "testdep_cycle"
+)
+
+-- pkgdep/pkgdep.go --
+package pkgdep
+
+-- testdep_a/testdep_a.go --
+package testdep_a
+
+-- testdep_b/testdep_b.go --
+package testdep_b
+
+-- testdep_cycle/testdep_cycle.go --
+package testdep_cycle
+
+import _ "cycleerr"
diff --git a/src/cmd/go/testdata/script/list_test_imports.txt b/src/cmd/go/testdata/script/list_test_imports.txt
new file mode 100644
index 0000000..0342eba
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_test_imports.txt
@@ -0,0 +1,21 @@
+env GO111MODULE=off
+
+# issue 26880: list with tests has wrong variant in imports
+go list -test -f '{{.ImportPath}}:{{with .Imports}} {{join . ", "}}{{end}}' a b
+cmp stdout imports.txt
+
+-- a/a.go --
+package a; import _ "b"
+-- b/b.go --
+package b
+-- b/b_test.go --
+package b
+-- b/b_x_test.go --
+package b_test; import _ "a"
+
+-- imports.txt --
+a: b
+b:
+b.test: b [b.test], b_test [b.test], os, reflect, testing, testing/internal/testdeps
+b [b.test]:
+b_test [b.test]: a [b.test]
diff --git a/src/cmd/go/testdata/script/list_test_non_go_files.txt b/src/cmd/go/testdata/script/list_test_non_go_files.txt
new file mode 100644
index 0000000..6b2b633
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_test_non_go_files.txt
@@ -0,0 +1,13 @@
+env GO111MODULE=off
+
+# issue 29899: handling files with non-Go extension
+go list -e -test -json -- c.c x.go
+stdout '"Err": "named files must be .go files: c.c"'
+
+! go list -test -json -- c.c x.go
+stderr '^named files must be \.go files: c\.c$'
+
+-- x.go --
+package main
+-- c.c --
+package c
diff --git a/src/cmd/go/testdata/script/list_test_simple.txt b/src/cmd/go/testdata/script/list_test_simple.txt
new file mode 100644
index 0000000..954897c
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_test_simple.txt
@@ -0,0 +1,67 @@
+[short] skip
+
+# Test
+go test -list=Test
+stdout TestSimple
+
+# Benchmark
+go test -list=Benchmark
+stdout BenchmarkSimple
+
+# Examples
+go test -list=Example
+stdout ExampleSimple
+stdout ExampleWithEmptyOutput
+
+-- go.mod --
+module m
+
+go 1.16
+-- bench_test.go --
+package testlist
+
+import (
+ "fmt"
+ "testing"
+)
+
+func BenchmarkSimplefunc(b *testing.B) {
+ b.StopTimer()
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ _ = fmt.Sprint("Test for bench")
+ }
+}
+-- example_test.go --
+package testlist
+
+import (
+ "fmt"
+)
+
+func ExampleSimple() {
+ fmt.Println("Test with Output.")
+
+ // Output: Test with Output.
+}
+
+func ExampleWithEmptyOutput() {
+ fmt.Println("")
+
+ // Output:
+}
+
+func ExampleNoOutput() {
+ _ = fmt.Sprint("Test with no output")
+}
+-- test_test.go --
+package testlist
+
+import (
+ "fmt"
+ "testing"
+)
+
+func TestSimple(t *testing.T) {
+ _ = fmt.Sprint("Test simple")
+}
diff --git a/src/cmd/go/testdata/script/list_wildcard_skip_nonmatching.txt b/src/cmd/go/testdata/script/list_wildcard_skip_nonmatching.txt
new file mode 100644
index 0000000..02b1088
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_wildcard_skip_nonmatching.txt
@@ -0,0 +1,17 @@
+# Test that wildcards don't look in useless directories.
+
+# First make sure that badpkg fails the list of '...'.
+! go list ./...
+stderr badpkg
+
+# Check that the list of './goodpkg...' succeeds. That implies badpkg was skipped.
+go list ./goodpkg...
+
+-- go.mod --
+module m
+
+go 1.16
+-- goodpkg/x.go --
+package goodpkg
+-- badpkg/x.go --
+pkg badpkg
diff --git a/src/cmd/go/testdata/script/load_test_pkg_err.txt b/src/cmd/go/testdata/script/load_test_pkg_err.txt
new file mode 100644
index 0000000..d088ee4
--- /dev/null
+++ b/src/cmd/go/testdata/script/load_test_pkg_err.txt
@@ -0,0 +1,30 @@
+# Tests issue 37971. Check that tests are still loaded even when the package has an error.
+
+go list -e -test d
+cmp stdout want_stdout
+
+go list -e -test -deps d
+stdout golang.org/fake/d
+
+-- want_stdout --
+d
+d.test
+d_test [d.test]
+-- go.mod --
+module d
+
+go 1.16
+-- d.go --
+package d
+
+import "net/http"
+
+const d = http.MethodGet
+func Get() string { return d; }
+-- d2.go --
+-- d_test.go --
+package d_test
+
+import "testing"
+import "golang.org/fake/d"
+func TestD(t *testing.T) { d.Get(); }
diff --git a/src/cmd/go/testdata/script/malformed_gosum_issue62345.txt b/src/cmd/go/testdata/script/malformed_gosum_issue62345.txt
new file mode 100644
index 0000000..23c41be
--- /dev/null
+++ b/src/cmd/go/testdata/script/malformed_gosum_issue62345.txt
@@ -0,0 +1,51 @@
+! go mod download
+stderr '^malformed go.sum:\n.*go.sum:3: wrong number of fields 5\n$'
+
+go mod tidy
+cmp go.sum go.sum.after-tidy
+
+-- go.mod --
+module m
+
+go 1.20
+
+require rsc.io/quote v1.5.2
+
+require (
+ golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c // indirect
+ rsc.io/sampler v1.3.0 // indirect
+ rsc.io/testonly v1.0.0 // indirect
+)
+
+-- go.sum --
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw=
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+rsc.io/quote v1.5.2 # invalid line
+rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
+rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+rsc.io/testonly v1.0.0 h1:K/VWHdO+Jv7woUXG0GzVNx1czBXUt3Ib1deaMn+xk64=
+rsc.io/testonly v1.0.0/go.mod h1:OqmGbIFOcF+XrFReLOGZ6BhMM7uMBiQwZsyNmh74SzY=
+
+-- main.go --
+package main
+
+import (
+ "fmt"
+
+ "rsc.io/quote"
+)
+
+func main() {
+ fmt.Println(quote.Hello())
+}
+
+-- go.sum.after-tidy --
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw=
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0=
+rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
+rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+rsc.io/testonly v1.0.0 h1:K/VWHdO+Jv7woUXG0GzVNx1czBXUt3Ib1deaMn+xk64=
+rsc.io/testonly v1.0.0/go.mod h1:OqmGbIFOcF+XrFReLOGZ6BhMM7uMBiQwZsyNmh74SzY=
diff --git a/src/cmd/go/testdata/script/mod_all.txt b/src/cmd/go/testdata/script/mod_all.txt
new file mode 100644
index 0000000..b71a920
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_all.txt
@@ -0,0 +1,531 @@
+# This test illustrates the relationship between the 'all' pattern and
+# the dependencies of the main module.
+
+# The package import graph used in this test looks like:
+#
+# main --------- a --------- b
+# | |
+# | a_test ---- c
+# | |
+# | c_test ---- d
+# |
+# main_test ---- t --------- u
+# |
+# t_test ---- w
+# |
+# w_test ---- x
+#
+# main/testonly_test ---- q --------- r
+# |
+# q_test ---- s
+#
+# And the module dependency graph looks like:
+#
+# main --- a.1 ---- b.1
+# \ \ \
+# \ \ c.1 -- d.1
+# \ \
+# \ t.1 ---- u.1
+# \ \
+# \ w.1 -- x.1
+# \
+# q.1 ---- r.1
+# \
+# s.1
+
+env PKGFMT='{{if .Module}}{{.ImportPath}}{{end}}'
+env MODFMT='{{.Path}}'
+
+
+# 'go list -deps' lists packages and tests in the main module,
+# along with their transitive dependencies.
+
+go list -f $PKGFMT -deps ./...
+stdout -count=4 '^.'
+stdout '^example.com/a$'
+stdout '^example.com/b$'
+stdout '^example.com/main$'
+stdout '^example.com/main/testonly'
+
+
+# 'go list -deps -test' lists transitive imports of tests and non-tests in the
+# main module.
+
+go list -f $PKGFMT -deps -test ./...
+stdout -count=13 '^.'
+stdout '^example.com/a$'
+stdout '^example.com/b$'
+stdout '^example.com/main$'
+stdout '^example.com/main.test$'
+stdout '^example.com/main \[example.com/main.test\]$'
+stdout '^example.com/main_test \[example.com/main.test\]$'
+stdout '^example.com/main/testonly$'
+stdout '^example.com/main/testonly.test$'
+stdout '^example.com/main/testonly_test \[example.com/main/testonly.test\]$'
+stdout '^example.com/q$'
+stdout '^example.com/r$'
+stdout '^example.com/t$'
+stdout '^example.com/u$'
+
+
+# 'go list all' lists the fixpoint of iterating 'go list -deps -test' starting
+# with the packages in the main module, then reducing to only the non-test
+# variants of those packages.
+
+go list -f $PKGFMT all
+stdout -count=13 '^.'
+stdout '^example.com/a$'
+stdout '^example.com/b$'
+stdout '^example.com/c$'
+stdout '^example.com/d$'
+stdout '^example.com/main$'
+stdout '^example.com/main/testonly$'
+stdout '^example.com/q$'
+stdout '^example.com/r$'
+stdout '^example.com/s$'
+stdout '^example.com/t$'
+stdout '^example.com/u$'
+stdout '^example.com/w$'
+stdout '^example.com/x$'
+
+
+# 'go list -test all' is equivalent to 'go list -test $(go list all)'
+# and both should include tests for every package in 'all'.
+
+go list -test -f $PKGFMT example.com/a example.com/b example.com/c example.com/d example.com/main example.com/main/testonly example.com/q example.com/r example.com/s example.com/t example.com/u example.com/w example.com/x
+cp stdout list-test-explicit.txt
+
+go list -test -f $PKGFMT all
+cmp stdout list-test-explicit.txt
+stdout -count=36 '^.'
+stdout '^example.com/a$'
+stdout '^example.com/b$'
+stdout '^example.com/c$'
+stdout '^example.com/d$'
+stdout '^example.com/main$'
+stdout '^example.com/main/testonly$'
+stdout '^example.com/q$'
+stdout '^example.com/r$'
+stdout '^example.com/s$'
+stdout '^example.com/t$'
+stdout '^example.com/u$'
+stdout '^example.com/w$'
+stdout '^example.com/x$'
+stdout '^example.com/a.test$'
+stdout '^example.com/a_test \[example.com/a.test\]$'
+stdout '^example.com/b.test$'
+stdout '^example.com/b_test \[example.com/b.test\]$'
+stdout '^example.com/c.test$'
+stdout '^example.com/c_test \[example.com/c.test\]$'
+stdout '^example.com/main.test$'
+stdout '^example.com/main \[example.com/main.test\]$'
+stdout '^example.com/main_test \[example.com/main.test\]$'
+stdout '^example.com/main/testonly.test$'
+stdout '^example.com/main/testonly_test \[example.com/main/testonly.test\]$'
+stdout '^example.com/q.test$'
+stdout '^example.com/q_test \[example.com/q.test\]$'
+stdout '^example.com/r.test$'
+stdout '^example.com/r_test \[example.com/r.test\]$'
+stdout '^example.com/s.test$'
+stdout '^example.com/s_test \[example.com/s.test\]$'
+stdout '^example.com/t.test$'
+stdout '^example.com/t_test \[example.com/t.test\]$'
+stdout '^example.com/u.test$'
+stdout '^example.com/u_test \[example.com/u.test\]$'
+stdout '^example.com/w.test$'
+stdout '^example.com/w_test \[example.com/w.test\]$'
+
+
+# 'go list -m all' covers the packages in 'go list -test -deps all'.
+
+go list -m -f $MODFMT all
+stdout -count=12 '^.'
+stdout '^example.com/a$'
+stdout '^example.com/b$'
+stdout '^example.com/c$'
+stdout '^example.com/d$'
+stdout '^example.com/main$'
+stdout '^example.com/q$'
+stdout '^example.com/r$'
+stdout '^example.com/s$'
+stdout '^example.com/t$'
+stdout '^example.com/u$'
+stdout '^example.com/w$'
+stdout '^example.com/x$'
+
+
+# 'go mod vendor' copies in only the packages transitively imported by the main
+# module, and omits their tests. As a result, the 'all' and '...' patterns
+# report fewer packages when using '-mod=vendor'.
+
+go mod vendor
+
+go list -f $PKGFMT -mod=vendor all
+stdout -count=8 '^.'
+stdout '^example.com/a$'
+stdout '^example.com/b$'
+stdout '^example.com/main$'
+stdout '^example.com/main/testonly$'
+stdout '^example.com/q$'
+stdout '^example.com/r$'
+stdout '^example.com/t$'
+stdout '^example.com/u$'
+
+go list -test -f $PKGFMT -mod=vendor all
+stdout -count=13 '^.'
+stdout '^example.com/a$'
+stdout '^example.com/b$'
+stdout '^example.com/main$'
+stdout '^example.com/main/testonly$'
+stdout '^example.com/q$'
+stdout '^example.com/r$'
+stdout '^example.com/t$'
+stdout '^example.com/u$'
+stdout '^example.com/main.test$'
+stdout '^example.com/main \[example.com/main.test\]$'
+stdout '^example.com/main_test \[example.com/main.test\]$'
+stdout '^example.com/main/testonly.test$'
+stdout '^example.com/main/testonly_test \[example.com/main/testonly.test\]$'
+
+rm vendor
+
+# Convert all modules to go 1.17 to enable lazy loading.
+go mod edit -go=1.17 a/go.mod
+go mod edit -go=1.17 b/go.mod
+go mod edit -go=1.17 c/go.mod
+go mod edit -go=1.17 d/go.mod
+go mod edit -go=1.17 q/go.mod
+go mod edit -go=1.17 r/go.mod
+go mod edit -go=1.17 s/go.mod
+go mod edit -go=1.17 t/go.mod
+go mod edit -go=1.17 u/go.mod
+go mod edit -go=1.17 w/go.mod
+go mod edit -go=1.17 x/go.mod
+go mod edit -go=1.17
+cmp go.mod go.mod.beforetidy
+go mod tidy
+cmp go.mod go.mod.aftertidy
+
+# With lazy loading, 'go list all' with neither -mod=vendor nor -test should
+# match -mod=vendor without -test in 1.15.
+
+go list -f $PKGFMT all
+stdout -count=8 '^.'
+stdout '^example.com/a$'
+stdout '^example.com/b$'
+stdout '^example.com/main$'
+stdout '^example.com/main/testonly$'
+stdout '^example.com/q$'
+stdout '^example.com/r$'
+stdout '^example.com/t$'
+stdout '^example.com/u$'
+
+# 'go list -test all' should expand that to include the test variants of the
+# packages in 'all', but not the dependencies of outside tests.
+
+go list -test -f $PKGFMT all
+stdout -count=25 '^.'
+stdout '^example.com/a$'
+stdout '^example.com/b$'
+stdout '^example.com/main$'
+stdout '^example.com/main/testonly$'
+stdout '^example.com/q$'
+stdout '^example.com/r$'
+stdout '^example.com/t$'
+stdout '^example.com/u$'
+stdout '^example.com/a.test$'
+stdout '^example.com/a_test \[example.com/a.test\]$'
+stdout '^example.com/b.test$'
+stdout '^example.com/b_test \[example.com/b.test\]$'
+stdout '^example.com/main.test$'
+stdout '^example.com/main \[example.com/main.test\]$'
+stdout '^example.com/main_test \[example.com/main.test\]$'
+stdout '^example.com/main/testonly.test$'
+stdout '^example.com/main/testonly_test \[example.com/main/testonly.test\]$'
+stdout '^example.com/q.test$'
+stdout '^example.com/q_test \[example.com/q.test\]$'
+stdout '^example.com/r.test$'
+stdout '^example.com/r_test \[example.com/r.test\]$'
+stdout '^example.com/t.test$'
+stdout '^example.com/t_test \[example.com/t.test\]$'
+stdout '^example.com/u.test$'
+stdout '^example.com/u_test \[example.com/u.test\]$'
+
+# 'go list -test -deps all' should include the dependencies of those tests,
+# but not the tests of the dependencies of outside tests.
+
+go list -test -deps -f $PKGFMT all
+stdout -count=28 '^.'
+stdout '^example.com/a$'
+stdout '^example.com/b$'
+stdout '^example.com/c$'
+stdout '^example.com/main$'
+stdout '^example.com/main/testonly$'
+stdout '^example.com/q$'
+stdout '^example.com/r$'
+stdout '^example.com/s$'
+stdout '^example.com/t$'
+stdout '^example.com/u$'
+stdout '^example.com/w$'
+stdout '^example.com/a.test$'
+stdout '^example.com/a_test \[example.com/a.test\]$'
+stdout '^example.com/b.test$'
+stdout '^example.com/b_test \[example.com/b.test\]$'
+stdout '^example.com/main.test$'
+stdout '^example.com/main \[example.com/main.test\]$'
+stdout '^example.com/main_test \[example.com/main.test\]$'
+stdout '^example.com/main/testonly.test$'
+stdout '^example.com/main/testonly_test \[example.com/main/testonly.test\]$'
+stdout '^example.com/q.test$'
+stdout '^example.com/q_test \[example.com/q.test\]$'
+stdout '^example.com/r.test$'
+stdout '^example.com/r_test \[example.com/r.test\]$'
+stdout '^example.com/t.test$'
+stdout '^example.com/t_test \[example.com/t.test\]$'
+stdout '^example.com/u.test$'
+stdout '^example.com/u_test \[example.com/u.test\]$'
+
+# 'go list -m all' should cover all of the modules providing packages in
+# 'go list -test -deps all', but should exclude modules d and x,
+# which are not relevant to the main module and are outside of the
+# lazy-loading horizon.
+
+go list -m -f $MODFMT all
+stdout -count=10 '^.'
+stdout '^example.com/a$'
+stdout '^example.com/b$'
+stdout '^example.com/c$'
+! stdout '^example.com/d$'
+stdout '^example.com/main$'
+stdout '^example.com/q$'
+stdout '^example.com/r$'
+stdout '^example.com/s$'
+stdout '^example.com/t$'
+stdout '^example.com/u$'
+stdout '^example.com/w$'
+! stdout '^example.com/x$'
+
+-- go.mod --
+module example.com/main
+
+// Note: this go.mod file initially specifies go 1.15,
+// but includes some redundant roots so that it
+// also already obeys the 1.17 lazy loading invariants.
+go 1.15
+
+require (
+ example.com/a v0.1.0
+ example.com/b v0.1.0 // indirect
+ example.com/q v0.1.0
+ example.com/r v0.1.0 // indirect
+ example.com/t v0.1.0
+ example.com/u v0.1.0 // indirect
+)
+
+replace (
+ example.com/a v0.1.0 => ./a
+ example.com/b v0.1.0 => ./b
+ example.com/c v0.1.0 => ./c
+ example.com/d v0.1.0 => ./d
+ example.com/q v0.1.0 => ./q
+ example.com/r v0.1.0 => ./r
+ example.com/s v0.1.0 => ./s
+ example.com/t v0.1.0 => ./t
+ example.com/u v0.1.0 => ./u
+ example.com/w v0.1.0 => ./w
+ example.com/x v0.1.0 => ./x
+)
+-- main.go --
+package main
+
+import _ "example.com/a"
+
+func main() {}
+-- main_test.go --
+package main_test
+
+import _ "example.com/t"
+-- testonly/testonly_test.go --
+package testonly_test
+
+import _ "example.com/q"
+-- a/go.mod --
+module example.com/a
+
+go 1.15
+
+require (
+ example.com/b v0.1.0
+ example.com/c v0.1.0
+)
+-- a/a.go --
+package a
+
+import _ "example.com/b"
+-- a/a_test.go --
+package a_test
+
+import _ "example.com/c"
+-- b/go.mod --
+module example.com/b
+
+go 1.15
+-- b/b.go --
+package b
+-- b/b_test.go --
+package b_test
+-- c/go.mod --
+module example.com/c
+
+go 1.15
+
+require example.com/d v0.1.0
+-- c/c.go --
+package c
+-- c/c_test.go --
+package c_test
+
+import _ "example.com/d"
+-- d/go.mod --
+module example.com/d
+
+go 1.15
+-- d/d.go --
+package d
+-- q/go.mod --
+module example.com/q
+
+go 1.15
+
+require (
+ example.com/r v0.1.0
+ example.com/s v0.1.0
+)
+-- q/q.go --
+package q
+import _ "example.com/r"
+-- q/q_test.go --
+package q_test
+import _ "example.com/s"
+-- r/go.mod --
+module example.com/r
+
+go 1.15
+-- r/r.go --
+package r
+-- r/r_test.go --
+package r_test
+-- s/go.mod --
+module example.com/s
+
+go 1.15
+-- s/s.go --
+package s
+-- s/s_test.go --
+package s_test
+-- t/go.mod --
+module example.com/t
+
+go 1.15
+
+require (
+ example.com/u v0.1.0
+ example.com/w v0.1.0
+)
+-- t/t.go --
+package t
+
+import _ "example.com/u"
+-- t/t_test.go --
+package t_test
+
+import _ "example.com/w"
+-- u/go.mod --
+module example.com/u
+
+go 1.15
+-- u/u.go --
+package u
+-- u/u_test.go --
+package u_test
+-- w/go.mod --
+module example.com/w
+
+go 1.15
+
+require example.com/x v0.1.0
+-- w/w.go --
+package w
+-- w/w_test.go --
+package w_test
+
+import _ "example.com/x"
+-- x/go.mod --
+module example.com/x
+
+go 1.15
+-- x/x.go --
+package x
+-- go.mod.beforetidy --
+module example.com/main
+
+// Note: this go.mod file initially specifies go 1.15,
+// but includes some redundant roots so that it
+// also already obeys the 1.17 lazy loading invariants.
+go 1.17
+
+require (
+ example.com/a v0.1.0
+ example.com/b v0.1.0 // indirect
+ example.com/q v0.1.0
+ example.com/r v0.1.0 // indirect
+ example.com/t v0.1.0
+ example.com/u v0.1.0 // indirect
+)
+
+replace (
+ example.com/a v0.1.0 => ./a
+ example.com/b v0.1.0 => ./b
+ example.com/c v0.1.0 => ./c
+ example.com/d v0.1.0 => ./d
+ example.com/q v0.1.0 => ./q
+ example.com/r v0.1.0 => ./r
+ example.com/s v0.1.0 => ./s
+ example.com/t v0.1.0 => ./t
+ example.com/u v0.1.0 => ./u
+ example.com/w v0.1.0 => ./w
+ example.com/x v0.1.0 => ./x
+)
+-- go.mod.aftertidy --
+module example.com/main
+
+// Note: this go.mod file initially specifies go 1.15,
+// but includes some redundant roots so that it
+// also already obeys the 1.17 lazy loading invariants.
+go 1.17
+
+require (
+ example.com/a v0.1.0
+ example.com/q v0.1.0
+ example.com/t v0.1.0
+)
+
+require (
+ example.com/b v0.1.0 // indirect
+ example.com/r v0.1.0 // indirect
+ example.com/u v0.1.0 // indirect
+)
+
+replace (
+ example.com/a v0.1.0 => ./a
+ example.com/b v0.1.0 => ./b
+ example.com/c v0.1.0 => ./c
+ example.com/d v0.1.0 => ./d
+ example.com/q v0.1.0 => ./q
+ example.com/r v0.1.0 => ./r
+ example.com/s v0.1.0 => ./s
+ example.com/t v0.1.0 => ./t
+ example.com/u v0.1.0 => ./u
+ example.com/w v0.1.0 => ./w
+ example.com/x v0.1.0 => ./x
+)
diff --git a/src/cmd/go/testdata/script/mod_alt_goroot.txt b/src/cmd/go/testdata/script/mod_alt_goroot.txt
new file mode 100644
index 0000000..32f94c5
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_alt_goroot.txt
@@ -0,0 +1,20 @@
+env GO111MODULE=on
+
+# If the working directory is a different GOROOT, then the 'std' module should be
+# treated as an ordinary module (with an ordinary module prefix).
+# It should not override packages in GOROOT, but should not fail the command.
+# See golang.org/issue/30756.
+go list -e -deps -f '{{.ImportPath}} {{.Dir}}' ./bytes
+stdout ^std/bytes.*$PWD[/\\]bytes
+stdout '^bytes/modified'
+
+-- go.mod --
+module std
+
+go 1.12
+-- bytes/bytes.go --
+package bytes
+
+import _"bytes/modified"
+-- bytes/modified/modified.go --
+package modified
diff --git a/src/cmd/go/testdata/script/mod_ambiguous_import.txt b/src/cmd/go/testdata/script/mod_ambiguous_import.txt
new file mode 100644
index 0000000..feaf5d2
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_ambiguous_import.txt
@@ -0,0 +1,48 @@
+env GO111MODULE=on
+
+cd $WORK
+
+# An import provided by two different modules should be flagged as an error.
+! go build ./importx
+stderr '^importx[/\\]importx.go:2:8: ambiguous import: found package example.com/a/x in multiple modules:\n\texample.com/a v0.1.0 \('$WORK'[/\\]a[/\\]x\)\n\texample.com/a/x v0.1.0 \('$WORK'[/\\]ax\)$'
+
+# However, it should not be an error if that import is unused.
+go build ./importy
+
+# An import provided by both the main module and the vendor directory
+# should be flagged as an error only when -mod=vendor is set.
+mkdir vendor/example.com/m/importy
+cp $WORK/importy/importy.go vendor/example.com/m/importy/importy.go
+go build example.com/m/importy
+! go build -mod=vendor example.com/m/importy
+stderr '^ambiguous import: found package example.com/m/importy in multiple directories:\n\t'$WORK'[/\\]importy\n\t'$WORK'[/\\]vendor[/\\]example.com[/\\]m[/\\]importy$'
+
+-- $WORK/go.mod --
+module example.com/m
+go 1.13
+require (
+ example.com/a v0.1.0
+ example.com/a/x v0.1.0
+)
+replace (
+ example.com/a v0.1.0 => ./a
+ example.com/a/x v0.1.0 => ./ax
+)
+-- $WORK/importx/importx.go --
+package importx
+import _ "example.com/a/x"
+-- $WORK/importy/importy.go --
+package importy
+import _ "example.com/a/y"
+-- $WORK/a/go.mod --
+module example.com/a
+go 1.14
+-- $WORK/a/x/x.go --
+package x
+-- $WORK/a/y/y.go --
+package y
+-- $WORK/ax/go.mod --
+module example.com/a/x
+go 1.14
+-- $WORK/ax/x.go --
+package x
diff --git a/src/cmd/go/testdata/script/mod_auth.txt b/src/cmd/go/testdata/script/mod_auth.txt
new file mode 100644
index 0000000..5e2b7a9
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_auth.txt
@@ -0,0 +1,35 @@
+[short] skip
+
+env GO111MODULE=on
+env GOPROXY=direct
+env GOSUMDB=off
+env GOVCS='*:off'
+
+# Without credentials, downloading a module from a path that requires HTTPS
+# basic auth should fail.
+env NETRC=$WORK/empty
+! go mod tidy
+stderr '^\tserver response: ACCESS DENIED, buddy$'
+stderr '^\tserver response: File\? What file\?$'
+
+# With credentials from a netrc file, it should succeed.
+env NETRC=$WORK/netrc
+go mod tidy
+go list all
+stdout vcs-test.golang.org/auth/or401
+stdout vcs-test.golang.org/auth/or404
+
+-- go.mod --
+module private.example.com
+-- main.go --
+package useprivate
+
+import (
+ _ "vcs-test.golang.org/auth/or401"
+ _ "vcs-test.golang.org/auth/or404"
+)
+-- $WORK/empty --
+-- $WORK/netrc --
+machine vcs-test.golang.org
+ login aladdin
+ password opensesame
diff --git a/src/cmd/go/testdata/script/mod_bad_domain.txt b/src/cmd/go/testdata/script/mod_bad_domain.txt
new file mode 100644
index 0000000..86aa96e
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_bad_domain.txt
@@ -0,0 +1,47 @@
+env GO111MODULE=on
+
+# explicit get should report errors about bad names
+! go get appengine
+stderr '^go: malformed module path "appengine": missing dot in first path element$'
+! go get x/y.z
+stderr 'malformed module path "x/y.z": missing dot in first path element'
+
+
+# 'go list -m' should report errors about module names, never GOROOT.
+! go list -m -versions appengine
+stderr 'malformed module path "appengine": missing dot in first path element'
+! go list -m -versions x/y.z
+stderr 'malformed module path "x/y.z": missing dot in first path element'
+
+
+# build should report all unsatisfied imports,
+# but should be more definitive about non-module import paths
+! go build ./useappengine
+stderr '^useappengine[/\\]x.go:2:8: cannot find package$'
+! go build ./usenonexistent
+stderr '^usenonexistent[/\\]x.go:2:8: no required module provides package nonexistent.rsc.io; to add it:\n\tgo get nonexistent.rsc.io$'
+
+
+# 'get -d' should be similarly definitive
+
+go get ./useappengine # TODO(#41315): This should fail.
+ # stderr '^useappengine[/\\]x.go:2:8: cannot find package$'
+
+! go get ./usenonexistent
+stderr '^go: x/usenonexistent imports\n\tnonexistent.rsc.io: cannot find module providing package nonexistent.rsc.io$'
+
+
+# go mod vendor and go mod tidy should ignore appengine imports.
+rm usenonexistent/x.go
+go mod tidy
+go mod vendor
+
+-- go.mod --
+module x
+
+-- useappengine/x.go --
+package useappengine
+import _ "appengine" // package does not exist
+-- usenonexistent/x.go --
+package usenonexistent
+import _ "nonexistent.rsc.io" // domain does not exist
diff --git a/src/cmd/go/testdata/script/mod_bad_filenames.txt b/src/cmd/go/testdata/script/mod_bad_filenames.txt
new file mode 100644
index 0000000..eb556f4
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_bad_filenames.txt
@@ -0,0 +1,11 @@
+env GO111MODULE=on
+
+! go get rsc.io/badfile1 rsc.io/badfile2 rsc.io/badfile3 rsc.io/badfile4 rsc.io/badfile5
+! stderr 'unzip.*badfile1'
+stderr 'unzip.*badfile2[\\/]@v[\\/]v1.0.0.zip:.*malformed file path "☺.go": invalid char ''☺'''
+stderr 'unzip.*badfile3[\\/]@v[\\/]v1.0.0.zip: rsc.io[\\/]badfile3@v1.0.0[\\/]x\?y.go: malformed file path "x\?y.go": invalid char ''\?'''
+stderr 'unzip.*badfile4[\\/]@v[\\/]v1.0.0.zip: rsc.io[\\/]badfile4@v1.0.0[\\/]x[\\/]y.go: case-insensitive file name collision: "x/Y.go" and "x/y.go"'
+stderr 'unzip.*badfile5[\\/]@v[\\/]v1.0.0.zip: rsc.io[\\/]badfile5@v1.0.0[\\/]x[\\/]Y[\\/]zz[\\/]ww.go: case-insensitive file name collision: "x/y" and "x/Y"'
+
+-- go.mod --
+module x
diff --git a/src/cmd/go/testdata/script/mod_build_info_err.txt b/src/cmd/go/testdata/script/mod_build_info_err.txt
new file mode 100644
index 0000000..8d7bd0c
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_build_info_err.txt
@@ -0,0 +1,33 @@
+# This test verifies that line numbers are included in module import errors.
+# Verifies golang.org/issue/34393.
+
+go list -e -mod=mod -deps -f '{{with .Error}}{{.Pos}}: {{.Err}}{{end}}' ./main
+stdout '^bad[/\\]bad.go:3:8: malformed import path "🐧.example.com/string": invalid char ''🐧''$'
+
+# TODO(#26909): This should include an import stack.
+# (Today it includes only a file and line.)
+! go build ./main
+stderr '^bad[/\\]bad.go:3:8: malformed import path "🐧.example.com/string": invalid char ''🐧''$'
+
+# TODO(#41688): This should include a file and line, and report the reason for the error..
+# (Today it includes only an import stack.)
+! go get ./main
+stderr '^go: m/main imports\n\tm/bad imports\n\t🐧.example.com/string: malformed import path "🐧.example.com/string": invalid char ''🐧''$'
+
+
+-- go.mod --
+module m
+
+go 1.13
+
+-- main/main.go --
+package main
+
+import _ "m/bad"
+
+func main() {}
+
+-- bad/bad.go --
+package bad
+
+import _ "🐧.example.com/string"
diff --git a/src/cmd/go/testdata/script/mod_build_tags.txt b/src/cmd/go/testdata/script/mod_build_tags.txt
new file mode 100644
index 0000000..ae1d605
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_build_tags.txt
@@ -0,0 +1,33 @@
+# Test that build tags are used.
+# golang.org/issue/24053.
+
+env GO111MODULE=on
+
+cd x
+! go list -f {{.GoFiles}}
+stderr 'build constraints exclude all Go files'
+
+go list -f {{.GoFiles}} -tags tag1
+stdout '\[x.go\]'
+
+go list -f {{.GoFiles}} -tags tag2
+stdout '\[y\.go\]'
+
+go list -f {{.GoFiles}} -tags 'tag1 tag2'
+stdout '\[x\.go y\.go\]'
+
+go list -f {{.GoFiles}} -tags tag1,tag2 # commas allowed as of Go 1.13
+stdout '\[x\.go y\.go\]'
+
+-- x/go.mod --
+module x
+
+-- x/x.go --
+// +build tag1
+
+package y
+
+-- x/y.go --
+// +build tag2
+
+package y
diff --git a/src/cmd/go/testdata/script/mod_build_trimpath_issue48557.txt b/src/cmd/go/testdata/script/mod_build_trimpath_issue48557.txt
new file mode 100644
index 0000000..859eafc
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_build_trimpath_issue48557.txt
@@ -0,0 +1,52 @@
+# Regression test for issue #48557.
+# Since builds in module mode do not support relative imports at all, the build
+# ID for (and other contents of) a binary built with -trimpath in module mode
+# should not depend on its working directory, even if the binary is specified as
+# a list of relative source files.
+
+[short] skip # links and runs binaries
+
+env GOFLAGS=-trimpath
+env GOCACHE=$WORK/gocache
+
+
+# When we build a binary in module mode with -trimpath, the -D flag (for the
+# "local import prefix") should not be passed to it.
+
+cd $WORK/tmp/foo
+go build -x -o a.exe main.go
+stderr ${/}compile$GOEXE.*' -nolocalimports'
+! stderr ${/}compile$GOEXE.*' -D[ =]'
+
+go tool buildid a.exe
+cp stdout ../foo-buildid.txt
+go version a.exe
+cp stdout ../foo-version.txt
+cd ..
+
+
+# On the second build — in a different directory but with -trimpath — the
+# compiler should not be invoked, since the cache key should be identical.
+# Only the linker and buildid tool should be needed.
+
+mkdir bar
+cp foo/main.go bar/main.go
+cd bar
+go build -x -o a.exe main.go
+! stderr ${/}compile$GOEXE
+
+go tool buildid a.exe
+cp stdout ../bar-buildid.txt
+go version a.exe
+cp stdout ../bar-version.txt
+cd ..
+
+cmp bar-buildid.txt foo-buildid.txt
+cmp bar-version.txt foo-version.txt
+cmp bar/a.exe foo/a.exe
+
+
+-- $WORK/tmp/foo/main.go --
+package main
+
+func main() {}
diff --git a/src/cmd/go/testdata/script/mod_build_versioned.txt b/src/cmd/go/testdata/script/mod_build_versioned.txt
new file mode 100644
index 0000000..f550418
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_build_versioned.txt
@@ -0,0 +1,17 @@
+env GO111MODULE=on
+[short] skip
+
+go get rsc.io/fortune/v2
+
+# The default executable name shouldn't be v2$GOEXE
+go build rsc.io/fortune/v2
+! exists v2$GOEXE
+exists fortune$GOEXE
+
+# The default test binary name shouldn't be v2.test$GOEXE
+go test -c rsc.io/fortune/v2
+! exists v2.test$GOEXE
+exists fortune.test$GOEXE
+
+-- go.mod --
+module scratch
diff --git a/src/cmd/go/testdata/script/mod_cache_dir.txt b/src/cmd/go/testdata/script/mod_cache_dir.txt
new file mode 100644
index 0000000..4045928
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_cache_dir.txt
@@ -0,0 +1,11 @@
+env GO111MODULE=on
+
+# Go should reject relative paths in GOMODCACHE environment.
+
+env GOMODCACHE="~/test"
+! go install example.com/tools/cmd/hello@latest
+stderr 'must be absolute path'
+
+env GOMODCACHE="./test"
+! go install example.com/tools/cmd/hello@latest
+stderr 'must be absolute path'
diff --git a/src/cmd/go/testdata/script/mod_cache_rw.txt b/src/cmd/go/testdata/script/mod_cache_rw.txt
new file mode 100644
index 0000000..87f27e8
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_cache_rw.txt
@@ -0,0 +1,49 @@
+# Regression test for golang.org/issue/31481.
+
+env GO111MODULE=on
+
+# golang.org/issue/31481: an explicit flag should make directories in the module
+# cache writable in order to work around the historical inability of 'rm -rf' to
+# forcibly remove files in unwritable directories.
+go get -modcacherw rsc.io/quote@v1.5.2
+cp $WORK/extraneous.txt $GOPATH/pkg/mod/rsc.io/quote@v1.5.2/extraneous_file.go
+
+# After adding an extraneous file, 'go mod verify' should fail.
+! go mod verify
+
+# However, files within those directories should still be read-only to avoid
+# accidental mutations.
+[!root] ! cp $WORK/extraneous.txt $GOPATH/pkg/mod/rsc.io/quote@v1.5.2/go.mod
+
+# If all 'go' commands ran with the flag, the system's 'rm' binary
+# should be able to remove the module cache if the '-rf' flags are set.
+[!GOOS:windows] [exec:rm] exec rm -rf $GOPATH/pkg/mod
+[!GOOS:windows] [!exec:rm] go clean -modcache
+[GOOS:windows] [exec:cmd.exe] exec cmd.exe /c rmdir /s /q $GOPATH\pkg\mod
+[GOOS:windows] [!exec:cmd.exe] go clean -modcache
+! exists $GOPATH/pkg/mod
+
+# The directories in the module cache should by default be unwritable,
+# so that tests and tools will not accidentally add extraneous files to them.
+# Windows does not respect FILE_ATTRIBUTE_READONLY on directories, according
+# to MSDN, so there we disable testing whether the directory itself is
+# unwritable.
+go get rsc.io/quote@latest
+[!root] ! cp $WORK/extraneous.txt $GOPATH/pkg/mod/rsc.io/quote@v1.5.2/go.mod
+[!GOOS:windows] [!root] ! cp $WORK/extraneous.txt $GOPATH/pkg/mod/rsc.io/quote@v1.5.2/extraneous_file.go
+! exists $GOPATH/pkg/mod/rsc.io/quote@v1.5.2/extraneous_file.go
+
+
+# Repeat part of the test with 'go mod download' instead of 'go get' to verify
+# -modcacherw is supported on 'go mod' subcommands.
+go clean -modcache
+go mod download -modcacherw rsc.io/quote
+cp $WORK/extraneous.txt $GOPATH/pkg/mod/rsc.io/quote@v1.5.2/extraneous_file.go
+! go mod verify
+[!root] ! cp $WORK/extraneous.txt $GOPATH/pkg/mod/rsc.io/quote@v1.5.2/go.mod
+
+
+-- $WORK/extraneous.txt --
+module oops
+-- go.mod --
+module golang.org/issue/31481
diff --git a/src/cmd/go/testdata/script/mod_case.txt b/src/cmd/go/testdata/script/mod_case.txt
new file mode 100644
index 0000000..d3fb11d
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_case.txt
@@ -0,0 +1,25 @@
+env GO111MODULE=on
+
+go get
+go list -m all
+stdout '^rsc.io/quote v1.5.2'
+stdout '^rsc.io/QUOTE v1.5.2'
+
+go list -f 'DIR {{.Dir}} DEPS {{.Deps}}' rsc.io/QUOTE/QUOTE
+stdout 'DEPS.*rsc.io/quote'
+stdout 'DIR.*!q!u!o!t!e'
+
+go get rsc.io/QUOTE@v1.5.3-PRE
+go list -m all
+stdout '^rsc.io/QUOTE v1.5.3-PRE'
+
+go list -f '{{.Dir}}' rsc.io/QUOTE/QUOTE
+stdout '!q!u!o!t!e@v1.5.3-!p!r!e'
+
+-- go.mod --
+module x
+
+-- use.go --
+package use
+
+import _ "rsc.io/QUOTE/QUOTE"
diff --git a/src/cmd/go/testdata/script/mod_case_cgo.txt b/src/cmd/go/testdata/script/mod_case_cgo.txt
new file mode 100644
index 0000000..7c768a0
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_case_cgo.txt
@@ -0,0 +1,11 @@
+[!cgo] skip
+
+env GO111MODULE=on
+
+go get rsc.io/CGO
+[short] stop
+
+go build rsc.io/CGO
+
+-- go.mod --
+module x
diff --git a/src/cmd/go/testdata/script/mod_clean_cache.txt b/src/cmd/go/testdata/script/mod_clean_cache.txt
new file mode 100644
index 0000000..2b8e820
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_clean_cache.txt
@@ -0,0 +1,61 @@
+env GO111MODULE=on
+
+# 'mod download' should download the module to the cache.
+go mod download rsc.io/quote@v1.5.0
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.info
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.mod
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.zip
+
+# '-n' should print commands but not actually execute them.
+go clean -modcache -n
+stdout '^rm -rf .*pkg.mod$'
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.info
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.mod
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.zip
+
+# 'go clean -modcache' should actually delete the files.
+go clean -modcache
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.info
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.mod
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.zip
+
+# 'go clean -r -modcache' should clean only the dependencies that are within the
+# main module.
+# BUG(golang.org/issue/28680): Today, it cleans across module boundaries.
+cd r
+exists ./test.out
+exists ../replaced/test.out
+go clean -r -modcache
+! exists ./test.out
+! exists ../replaced/test.out # BUG: should still exist
+
+# 'go clean -modcache' should not download anything before cleaning.
+go mod edit -require rsc.io/quote@v1.99999999.0-not-a-real-version
+go clean -modcache
+! stderr 'finding rsc.io'
+go mod edit -droprequire rsc.io/quote
+
+! go clean -modcache m
+stderr 'go: clean -modcache cannot be used with package arguments'
+
+-- go.mod --
+module m
+-- m.go --
+package m
+
+-- r/go.mod --
+module example.com/r
+require example.com/r/replaced v0.0.0
+replace example.com/r/replaced => ../replaced
+-- r/r.go --
+package r
+import _ "example.com/r/replaced"
+-- r/test.out --
+DELETE ME
+
+-- replaced/go.mod --
+module example.com/r/replaced
+-- replaced/replaced.go --
+package replaced
+-- replaced/test.out --
+DO NOT DELETE
diff --git a/src/cmd/go/testdata/script/mod_concurrent.txt b/src/cmd/go/testdata/script/mod_concurrent.txt
new file mode 100644
index 0000000..e2224d6
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_concurrent.txt
@@ -0,0 +1,32 @@
+env GO111MODULE=on
+
+# Concurrent builds should succeed, even if they need to download modules.
+go get ./x ./y
+go build ./x &
+go build ./y
+wait
+
+# Concurrent builds should update go.sum to the union of the hashes for the
+# modules they read.
+cmp go.sum go.sum.want
+
+-- go.mod --
+module golang.org/issue/26794
+
+require (
+ golang.org/x/text v0.3.0
+ rsc.io/sampler v1.0.0
+)
+-- x/x.go --
+package x
+
+import _ "golang.org/x/text/language"
+-- y/y.go --
+package y
+
+import _ "rsc.io/sampler"
+-- go.sum.want --
+golang.org/x/text v0.3.0 h1:ivTorhoiROmZ1mcs15mO2czVF0uy0tnezXpBVNzgrmA=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+rsc.io/sampler v1.0.0 h1:SRJnjyQ07sAtq6G4RcfJEmz8JxqLyj3PoGXG2VhbDWo=
+rsc.io/sampler v1.0.0/go.mod h1:cqxpM3ZVz9VtirqxZPmrWzkQ+UkiNiGtkrN+B+i8kx8=
diff --git a/src/cmd/go/testdata/script/mod_convert_git.txt b/src/cmd/go/testdata/script/mod_convert_git.txt
new file mode 100644
index 0000000..6ff1eb5
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_convert_git.txt
@@ -0,0 +1,40 @@
+env GO111MODULE=on
+
+# We should not create a go.mod file unless the user ran 'go mod init' explicitly.
+# However, we should suggest 'go mod init' if we can find an alternate config file.
+cd $WORK/test/x
+! go list .
+stderr 'found .git/config in .*[/\\]test'
+stderr '\s*cd \.\. && go mod init'
+
+# The command we suggested should succeed.
+cd ..
+go mod init
+go list -m all
+stdout '^m$'
+
+# We should not suggest creating a go.mod file in $GOROOT, even though there may be a .git/config there.
+cd $GOROOT
+! go list .
+! stderr 'go mod init'
+
+# We should also not suggest creating a go.mod file in $GOROOT if its own
+# .git/config has been stripped away and we find one in a parent directory.
+# (https://golang.org/issue/34191)
+env GOROOT=$WORK/parent/goroot
+cd $GOROOT
+! go list .
+! stderr 'go mod init'
+
+cd $GOROOT/doc
+! go list .
+! stderr 'go mod init'
+
+-- $WORK/test/.git/config --
+-- $WORK/test/x/x.go --
+package x // import "m/x"
+-- $WORK/parent/.git/config --
+-- $WORK/parent/goroot/README --
+This directory isn't really a GOROOT, but let's pretend that it is.
+-- $WORK/parent/goroot/doc/README --
+This is a subdirectory of our fake GOROOT.
diff --git a/src/cmd/go/testdata/script/mod_deprecate_message.txt b/src/cmd/go/testdata/script/mod_deprecate_message.txt
new file mode 100644
index 0000000..1fb1246
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_deprecate_message.txt
@@ -0,0 +1,73 @@
+# When there is a short single-line message, 'go get' should print it all.
+go get short
+stderr '^go: module short is deprecated: short$'
+go list -m -u -f '{{.Deprecated}}' short
+stdout '^short$'
+
+# When there is a multi-line message, 'go get' should print the first line.
+go get multiline
+stderr '^go: module multiline is deprecated: first line$'
+! stderr 'second line'
+go list -m -u -f '{{.Deprecated}}' multiline
+stdout '^first line\nsecond line.$'
+
+# When there is a long message, 'go get' should print a placeholder.
+go get long
+stderr '^go: module long is deprecated: \(message omitted: too long\)$'
+go list -m -u -f '{{.Deprecated}}' long
+stdout '^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$'
+
+# When a message contains unprintable characters, 'go get' should say that
+# without printing the message.
+go get unprintable
+stderr '^go: module unprintable is deprecated: \(message omitted: contains non-printable characters\)$'
+go list -m -u -f '{{.Deprecated}}' unprintable
+stdout '^message contains ASCII BEL\x07$'
+
+-- go.mod --
+module use
+
+go 1.16
+
+require (
+ short v0.0.0
+ multiline v0.0.0
+ long v0.0.0
+ unprintable v0.0.0
+)
+
+replace (
+ short v0.0.0 => ./short
+ multiline v0.0.0 => ./multiline
+ long v0.0.0 => ./long
+ unprintable v0.0.0 => ./unprintable
+)
+-- short/go.mod --
+// Deprecated: short
+module short
+
+go 1.16
+-- short/short.go --
+package short
+-- multiline/go.mod --
+// Deprecated: first line
+// second line.
+module multiline
+
+go 1.16
+-- multiline/multiline.go --
+package multiline
+-- long/go.mod --
+// Deprecated: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+module long
+
+go 1.16
+-- long/long.go --
+package long
+-- unprintable/go.mod --
+// Deprecated: message contains ASCII BEL
+module unprintable
+
+go 1.16
+-- unprintable/unprintable.go --
+package unprintable
diff --git a/src/cmd/go/testdata/script/mod_dir.txt b/src/cmd/go/testdata/script/mod_dir.txt
new file mode 100644
index 0000000..05548f6
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_dir.txt
@@ -0,0 +1,20 @@
+# The directory named go.mod should be ignored
+
+env GO111MODULE=on
+
+cd $WORK/sub
+
+go list .
+stdout 'x/sub'
+
+mkdir go.mod
+exists go.mod
+
+go list .
+stdout 'x/sub'
+
+-- $WORK/go.mod --
+module x
+
+-- $WORK/sub/x.go --
+package x \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/mod_doc.txt b/src/cmd/go/testdata/script/mod_doc.txt
new file mode 100644
index 0000000..bf0a19d
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_doc.txt
@@ -0,0 +1,90 @@
+# go doc should find module documentation
+
+env GO111MODULE=on
+env GOFLAGS=-mod=mod
+[short] skip
+
+# Check when module x is inside GOPATH/src.
+go doc y
+stdout 'Package y is.*alphabet'
+stdout 'import "x/y"'
+go doc x/y
+stdout 'Package y is.*alphabet'
+! go doc quote.Hello
+stderr 'doc: symbol quote is not a type' # because quote is not in local cache
+go list rsc.io/quote # now it is
+go doc quote.Hello
+stdout 'Hello returns a greeting'
+go doc quote
+stdout 'Package quote collects pithy sayings.'
+
+# Double-check when module x is outside GOPATH/src.
+env GOPATH=$WORK/emptygopath
+go doc x/y
+stdout 'Package y is.*alphabet'
+go doc y
+stdout 'Package y is.*alphabet'
+
+# Triple-check when module x is outside GOPATH/src,
+# but other packages with same import paths are in GOPATH/src.
+# Since go doc is running in module mode here, packages in active module
+# should be preferred over packages in GOPATH. See golang.org/issue/28992.
+env GOPATH=$WORK/gopath2
+go doc x/y
+! stdout 'Package y is.*GOPATH'
+stdout 'Package y is.*alphabet'
+go doc rsc.io/quote
+! stdout 'Package quote is located in a GOPATH workspace.'
+stdout 'Package quote collects pithy sayings.'
+
+# Check that a sensible error message is printed when a package is not found.
+env GOPROXY=off
+! go doc example.com/hello
+stderr '^doc: cannot find module providing package example.com/hello: module lookup disabled by GOPROXY=off$'
+
+# When in a module with a vendor directory, doc should use the vendored copies
+# of the packages. 'std' and 'cmd' are convenient examples of such modules.
+#
+# When in those modules, the "// import" comment should refer to the same import
+# path used in source code, not to the absolute path relative to GOROOT.
+
+cd $GOROOT/src
+env GOFLAGS=
+env GOWORK=off
+go doc cryptobyte
+stdout '// import "golang.org/x/crypto/cryptobyte"'
+
+cd $GOROOT/src/cmd/go
+go doc modfile
+stdout '// import "golang.org/x/mod/modfile"'
+
+# When outside of the 'std' module, its vendored packages
+# remain accessible using the 'vendor/' prefix, but report
+# the correct "// import" comment as used within std.
+cd $GOPATH
+go doc vendor/golang.org/x/crypto/cryptobyte
+stdout '// import "vendor/golang.org/x/crypto/cryptobyte"'
+
+go doc cmd/vendor/golang.org/x/mod/modfile
+stdout '// import "cmd/vendor/golang.org/x/mod/modfile"'
+
+-- go.mod --
+module x
+require rsc.io/quote v1.5.2
+
+-- y/y.go --
+// Package y is the next to last package of the alphabet.
+package y
+
+-- x.go --
+package x
+
+-- $WORK/gopath2/src/x/y/y.go --
+// Package y is located in a GOPATH workspace.
+package y
+-- $WORK/gopath2/src/rsc.io/quote/quote.go --
+// Package quote is located in a GOPATH workspace.
+package quote
+
+// Hello is located in a GOPATH workspace.
+func Hello() string { return "" }
diff --git a/src/cmd/go/testdata/script/mod_doc_path.txt b/src/cmd/go/testdata/script/mod_doc_path.txt
new file mode 100644
index 0000000..83d5392
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_doc_path.txt
@@ -0,0 +1,30 @@
+# cmd/doc should use GOROOT to locate the 'go' command,
+# not use whatever is in $PATH.
+
+# Remove 'go' from $PATH. (It can still be located via $GOROOT/bin/go, and the
+# test script's built-in 'go' command still knows where to find it.)
+env PATH=''
+[GOOS:plan9] env path=''
+
+go doc p.X
+
+-- go.mod --
+module example
+
+go 1.19
+
+require example.com/p v0.1.0
+
+replace example.com/p => ./pfork
+-- example.go --
+package example
+
+import _ "example.com/p"
+-- pfork/go.mod --
+module example.com/p
+
+go 1.19
+-- pfork/p.go --
+package p
+
+const X = 42
diff --git a/src/cmd/go/testdata/script/mod_domain_root.txt b/src/cmd/go/testdata/script/mod_domain_root.txt
new file mode 100644
index 0000000..c13029d
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_domain_root.txt
@@ -0,0 +1,12 @@
+# Module paths that are domain roots should resolve.
+# (example.com not example.com/something)
+
+env GO111MODULE=on
+go get
+
+-- go.mod --
+module x
+
+-- x.go --
+package x
+import _ "example.com"
diff --git a/src/cmd/go/testdata/script/mod_dot.txt b/src/cmd/go/testdata/script/mod_dot.txt
new file mode 100644
index 0000000..aa24986
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_dot.txt
@@ -0,0 +1,132 @@
+env GOWORK=off
+env GO111MODULE=on
+
+# golang.org/issue/32917 and golang.org/issue/28459: 'go build' and 'go test'
+# in an empty directory should refer to the path '.' and should not attempt
+# to resolve an external module.
+cd dir
+! go get
+stderr '^go: no package to get in current directory$'
+! go get .
+stderr '^go: .: no package to get in current directory$'
+! go get ./subdir
+stderr '^go: \.[/\\]subdir \('$WORK'[/\\]gopath[/\\]src[/\\]dir[/\\]subdir\) is not a package in module rooted at '$WORK'[/\\]gopath[/\\]src[/\\]dir$'
+! go list
+! stderr 'cannot find module providing package'
+stderr '^no Go files in '$WORK'[/\\]gopath[/\\]src[/\\]dir$'
+
+cd subdir
+! go list
+! stderr 'cannot find module providing package'
+stderr '^no Go files in '$WORK'[/\\]gopath[/\\]src[/\\]dir[/\\]subdir$'
+cd ..
+
+# golang.org/issue/30590: if a package is found in the filesystem
+# but is not in the main module, the error message should not say
+# "cannot find module providing package", and we shouldn't try
+# to find a module providing the package.
+! go list ./othermodule
+! stderr 'cannot find module providing package'
+stderr '^main module \(example\.com\) does not contain package example.com/othermodule$'
+
+# golang.org/issue/27122: 'go build' of a nonexistent directory should produce
+# a helpful "no Go files" error message, not a generic "unknown import path".
+! go list ./subdir
+stderr '^no Go files in '$WORK'[/\\]gopath[/\\]src[/\\]dir[/\\]subdir$'
+
+# golang.org/issue/29280: 'go list -e' for a nonexistent directory should
+# report a nonexistent package with an error.
+go list -e -json ./subdir
+stdout '"Incomplete": true'
+
+# golang.org/issue/28155: 'go list ./testdata' should not synthesize underscores.
+go list ./testdata
+stdout '^example.com/testdata'
+
+# golang.org/issue/32921: vendor directories should only be accepted as directories
+# if the directory would actually be used to load the package.
+! go list ./vendor/nonexist
+stderr '^no Go files in '$WORK'[/\\]gopath[/\\]src[/\\]dir[/\\]vendor[/\\]nonexist$'
+
+! go list ./vendor/pkg
+stderr '^without -mod=vendor, directory '$WORK'[/\\]gopath[/\\]src[/\\]dir[/\\]vendor[/\\]pkg has no package path$'
+
+! go list -mod=vendor ./vendor/nonexist
+stderr '^no Go files in '$WORK'[/\\]gopath[/\\]src[/\\]dir[/\\]vendor[/\\]nonexist$'
+
+! go list -mod=vendor ./vendor/unlisted
+stderr '^directory '$WORK'[/\\]gopath[/\\]src[/\\]dir[/\\]vendor[/\\]unlisted is not a package listed in vendor/modules.txt$'
+
+go list -mod=vendor ./vendor/pkg
+stdout '^pkg$'
+
+# Packages within GOROOT should resolve as in any other module,
+# except that -mod=vendor is implied by default.
+cd $GOROOT/src
+! go list .
+stderr '^no Go files in '$GOROOT'[/\\]src$'
+
+! go list ./builtin
+stderr '^"builtin" is a pseudo-package, not an importable package$'
+
+! go list ./debug
+! stderr 'cannot find module providing package'
+stderr '^no Go files in '$GOROOT'[/\\]src[/\\]debug$'
+
+! go list ./golang.org/x/tools/cmd/goimports
+! stderr 'cannot find module providing package'
+stderr '^stat '$GOROOT'[/\\]src[/\\]golang.org[/\\]x[/\\]tools[/\\]cmd[/\\]goimports: directory not found'
+
+go list ./vendor/golang.org/x/net/http2/hpack
+stdout '^golang.org/x/net/http2/hpack$'
+
+# golang.org/issue/30756: packages in other GOROOTs should not get the special
+# prefixless treatment of GOROOT itself.
+cd $WORK/othergoroot/src
+! go list .
+stderr '^no Go files in '$WORK'[/\\]othergoroot[/\\]src$'
+
+go list ./builtin
+stdout '^std/builtin$' # Only the "std" in actual $GOROOT is special, and only its "builtin" is special.
+
+! go list ./bytes
+! stderr 'cannot find module providing package'
+stderr '^no Go files in '$WORK'[/\\]othergoroot[/\\]src[/\\]bytes$'
+
+! go list ./vendor/golang.org/x/net/http2/hpack
+stderr '^without -mod=vendor, directory '$WORK'[/\\]othergoroot[/\\]src[/\\]vendor[/\\]golang.org[/\\]x[/\\]net[/\\]http2[/\\]hpack has no package path$'
+
+-- dir/go.mod --
+module example.com
+go 1.13
+-- dir/subdir/README --
+There are no Go source files in this directory.
+-- dir/othermodule/go.mod --
+module example.com/othermodule
+go 1.13
+-- dir/othermodule/om.go --
+package othermodule
+-- dir/testdata/td.go --
+package testdata
+-- dir/vendor/modules.txt --
+# pkg v0.0.0
+pkg
+-- dir/vendor/nonexist/README --
+There are no Go source files here either.
+-- dir/vendor/pkg/pkg.go --
+package pkg
+-- dir/vendor/unlisted/unlisted.go --
+package unlisted
+-- emptyroot/go.mod --
+module example.com/emptyroot
+-- emptyroot/pkg/pkg.go --
+package pkg
+-- $WORK/othergoroot/src/go.mod --
+module std
+go 1.13
+-- $WORK/othergoroot/src/builtin/builtin.go --
+package builtin
+-- $WORK/othergoroot/src/bytes/README --
+There are no Go source files in this directory.
+-- $WORK/othergoroot/src/vendor/golang.org/x/net/http2/hpack --
+package hpack
diff --git a/src/cmd/go/testdata/script/mod_download.txt b/src/cmd/go/testdata/script/mod_download.txt
new file mode 100644
index 0000000..154e683
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_download.txt
@@ -0,0 +1,214 @@
+env GO111MODULE=on
+
+# download with version should print nothing.
+# It should not load retractions from the .mod file from the latest version.
+go mod download rsc.io/quote@v1.5.0
+! stdout .
+! stderr .
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.info
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.mod
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.zip
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.info
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.mod
+
+# download of an invalid path should report the error
+[short] skip
+! go mod download this.domain.is.invalid/somemodule@v1.0.0
+stderr 'this.domain.is.invalid'
+! go mod download -json this.domain.is.invalid/somemodule@v1.0.0
+stdout '"Error": ".*this.domain.is.invalid.*"'
+
+# download -json with version should print JSON
+go mod download -json 'rsc.io/quote@<=v1.5.0'
+stdout '^\t"Path": "rsc.io/quote"'
+stdout '^\t"Version": "v1.5.0"'
+stdout '^\t"Info": ".*(\\\\|/)pkg(\\\\|/)mod(\\\\|/)cache(\\\\|/)download(\\\\|/)rsc.io(\\\\|/)quote(\\\\|/)@v(\\\\|/)v1.5.0.info"'
+stdout '^\t"GoMod": ".*(\\\\|/)pkg(\\\\|/)mod(\\\\|/)cache(\\\\|/)download(\\\\|/)rsc.io(\\\\|/)quote(\\\\|/)@v(\\\\|/)v1.5.0.mod"'
+stdout '^\t"Zip": ".*(\\\\|/)pkg(\\\\|/)mod(\\\\|/)cache(\\\\|/)download(\\\\|/)rsc.io(\\\\|/)quote(\\\\|/)@v(\\\\|/)v1.5.0.zip"'
+stdout '^\t"Sum": "h1:6fJa6E\+wGadANKkUMlZ0DhXFpoKlslOQDCo259XtdIE="' # hash of testdata/mod version, not real version!
+stdout '^\t"GoModSum": "h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe\+TKr0="'
+! stdout '"Error"'
+
+# download queries above should not have added to go.mod.
+go list -m all
+! stdout rsc.io
+
+# download query should have downloaded go.mod for the highest release version
+# in order to find retractions when resolving the query '@<=v1.5.0'.
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.info
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.mod
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip
+
+# add to go.mod so we can test non-query downloads
+go mod edit -require rsc.io/quote@v1.5.3-pre1
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-pre1.info
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-pre1.mod
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-pre1.zip
+
+# module loading will page in the info and mod files
+go list -m -mod=mod all
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-pre1.info
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-pre1.mod
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-pre1.zip
+
+# download will fetch and unpack the zip file
+go mod download
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-pre1.info
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-pre1.mod
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-pre1.zip
+exists $GOPATH/pkg/mod/rsc.io/quote@v1.5.3-pre1
+
+# download repopulates deleted files and directories independently.
+rm $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-pre1.info
+go mod download
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-pre1.info
+rm $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-pre1.mod
+go mod download
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-pre1.mod
+rm $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-pre1.zip
+go mod download
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-pre1.zip
+rm -r $GOPATH/pkg/mod/rsc.io/quote@v1.5.3-pre1
+go mod download
+exists $GOPATH/pkg/mod/rsc.io/quote@v1.5.3-pre1
+
+# download reports the locations of downloaded files
+go mod download -json
+stdout '^\t"Path": "rsc.io/quote"'
+stdout '^\t"Version": "v1.5.3-pre1"'
+stdout '^\t"Info": ".*(\\\\|/)pkg(\\\\|/)mod(\\\\|/)cache(\\\\|/)download(\\\\|/)rsc.io(\\\\|/)quote(\\\\|/)@v(\\\\|/)v1.5.3-pre1.info"'
+stdout '^\t"GoMod": ".*(\\\\|/)pkg(\\\\|/)mod(\\\\|/)cache(\\\\|/)download(\\\\|/)rsc.io(\\\\|/)quote(\\\\|/)@v(\\\\|/)v1.5.3-pre1.mod"'
+stdout '^\t"Zip": ".*(\\\\|/)pkg(\\\\|/)mod(\\\\|/)cache(\\\\|/)download(\\\\|/)rsc.io(\\\\|/)quote(\\\\|/)@v(\\\\|/)v1.5.3-pre1.zip"'
+stdout '^\t"Dir": ".*(\\\\|/)pkg(\\\\|/)mod(\\\\|/)rsc.io(\\\\|/)quote@v1.5.3-pre1"'
+
+# download will follow replacements
+go mod edit -require rsc.io/quote@v1.5.1 -replace rsc.io/quote@v1.5.1=rsc.io/quote@v1.5.2
+go mod download
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.1.zip
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip
+
+# download will not follow replacements for explicit module queries
+go mod download -json rsc.io/quote@v1.5.1
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.1.zip
+
+# download reports errors encountered when locating modules
+! go mod download bad/path
+stderr '^go: module bad/path: not a known dependency$'
+! go mod download bad/path@latest
+stderr '^go: bad/path@latest: malformed module path "bad/path": missing dot in first path element$'
+! go mod download rsc.io/quote@v1.999.999
+stderr '^go: rsc.io/quote@v1.999.999: reading .*/v1.999.999.info: 404 Not Found$'
+! go mod download -json bad/path
+stdout '^\t"Error": "module bad/path: not a known dependency"'
+
+# download main module produces a warning or error
+go mod download m
+stderr '^go: skipping download of m that resolves to the main module\n'
+! go mod download m@latest
+stderr '^go: m@latest: malformed module path "m": missing dot in first path element$'
+
+# download without arguments updates go.mod and go.sum after loading the
+# build list, but does not save sums for downloaded zips.
+cd update
+cp go.mod.orig go.mod
+! exists go.sum
+go mod download
+cmp go.mod.update go.mod
+cmp go.sum.update go.sum
+cp go.mod.orig go.mod
+rm go.sum
+
+# download with arguments (even "all") does update go.mod and go.sum.
+go mod download rsc.io/sampler
+cmp go.mod.update go.mod
+grep '^rsc.io/sampler v1.3.0 ' go.sum
+cp go.mod.orig go.mod
+rm go.sum
+
+go mod download all
+cmp go.mod.update go.mod
+grep '^rsc.io/sampler v1.3.0 ' go.sum
+
+# https://golang.org/issue/44435: At go 1.17 or higher, 'go mod download'
+# (without arguments) should only download the modules explicitly required in
+# the go.mod file, not (presumed-irrelevant) transitive dependencies.
+#
+# (If the go.mod file is inconsistent, the version downloaded should be the
+# selected version from the broader graph, but the go.mod file will also be
+# updated to list the correct versions. If at some point we change 'go mod
+# download' to stop updating for consistency, then it should fail if the
+# requirements are inconsistent.)
+
+rm go.sum
+cp go.mod.orig go.mod
+go mod edit -go=1.17
+cp go.mod.update go.mod.go117
+go mod edit -go=1.17 go.mod.go117
+
+go clean -modcache
+go mod download
+cmp go.mod go.mod.go117
+
+go list -e -m all
+stdout '^rsc.io/quote v1.5.2$'
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip
+stdout '^rsc.io/sampler v1.3.0$'
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/sampler/@v/v1.2.1.zip
+exists $GOPATH/pkg/mod/cache/download/rsc.io/sampler/@v/v1.3.0.zip
+stdout '^golang\.org/x/text v0.0.0-20170915032832-14c0d48ead0c$'
+! exists $GOPATH/pkg/mod/cache/download/golang.org/x/text/@v/v0.0.0-20170915032832-14c0d48ead0c.zip
+cmp go.mod go.mod.go117
+
+# However, 'go mod download all' continues to download the selected version
+# of every module reported by 'go list -m all'.
+
+cp go.mod.orig go.mod
+go mod edit -go=1.17
+go clean -modcache
+go mod download all
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/sampler/@v/v1.2.1.zip
+exists $GOPATH/pkg/mod/cache/download/rsc.io/sampler/@v/v1.3.0.zip
+exists $GOPATH/pkg/mod/cache/download/golang.org/x/text/@v/v0.0.0-20170915032832-14c0d48ead0c.zip
+cmp go.mod go.mod.go117
+
+cd ..
+
+# allow go mod download without go.mod
+env GO111MODULE=auto
+rm go.mod
+rm $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.2.1.zip
+go mod download rsc.io/quote@v1.2.1
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.2.1.zip
+
+# download -x with version should print
+# the underlying commands such as contacting GOPROXY.
+go mod download -x rsc.io/quote@v1.0.0
+! stdout .
+stderr 'get '$GOPROXY
+
+-- go.mod --
+module m
+
+-- update/go.mod.orig --
+module m
+
+go 1.16
+
+require (
+ rsc.io/quote v1.5.2
+ rsc.io/sampler v1.2.1 // older version than in build list
+)
+-- update/go.mod.update --
+module m
+
+go 1.16
+
+require (
+ rsc.io/quote v1.5.2
+ rsc.io/sampler v1.3.0 // older version than in build list
+)
+-- update/go.sum.update --
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
diff --git a/src/cmd/go/testdata/script/mod_download_concurrent_read.txt b/src/cmd/go/testdata/script/mod_download_concurrent_read.txt
new file mode 100644
index 0000000..c2c8b18
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_download_concurrent_read.txt
@@ -0,0 +1,110 @@
+# This test simulates a process watching for changes and reading files in
+# module cache as a module is extracted.
+#
+# Before Go 1.16, we extracted each module zip to a temporary directory with
+# a random name, then renamed that into place with os.Rename. On Windows,
+# this failed with ERROR_ACCESS_DENIED when another process (usually an
+# anti-virus scanner) opened files in the temporary directory. This test
+# simulates that behavior, verifying golang.org/issue/36568.
+#
+# Since 1.16, we extract to the final directory, but we create a .partial file
+# so that if we crash, other processes know the directory is incomplete.
+
+[!GOOS:windows] skip
+[short] skip
+
+go run downloader.go
+
+-- go.mod --
+module example.com/m
+
+go 1.14
+
+-- downloader.go --
+package main
+
+import (
+ "fmt"
+ "log"
+ "os"
+ "os/exec"
+ "path/filepath"
+)
+
+func main() {
+ if err := run(); err != nil {
+ log.Fatal(err)
+ }
+}
+
+// run repeatedly downloads a module while opening files in the module cache
+// in a background goroutine.
+//
+// run uses a different temporary module cache in each iteration so that we
+// don't need to clean the cache or synchronize closing files after each
+// iteration.
+func run() (err error) {
+ tmpDir, err := os.MkdirTemp("", "")
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if rmErr := os.RemoveAll(tmpDir); err == nil && rmErr != nil {
+ err = rmErr
+ }
+ }()
+ for i := 0; i < 10; i++ {
+ gopath := filepath.Join(tmpDir, fmt.Sprintf("gopath%d", i))
+ var err error
+ done := make(chan struct{})
+ go func() {
+ err = download(gopath)
+ close(done)
+ }()
+ readCache(gopath, done)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// download downloads a module into the given cache using 'go mod download'.
+func download(gopath string) error {
+ cmd := exec.Command("go", "mod", "download", "-modcacherw", "rsc.io/quote@v1.5.2")
+ cmd.Stderr = os.Stderr
+ cmd.Env = append(os.Environ(), "GOPATH="+gopath)
+ return cmd.Run()
+}
+
+// readCache repeatedly globs for go.mod files in the given cache, then opens
+// those files for reading. When the done chan is closed, readCache closes
+// files and returns.
+func readCache(gopath string, done <-chan struct{}) {
+ files := make(map[string]*os.File)
+ defer func() {
+ for _, f := range files {
+ f.Close()
+ }
+ }()
+
+ pattern := filepath.Join(gopath, "pkg/mod/rsc.io/quote@v1.5.2*/go.mod")
+ for {
+ select {
+ case <-done:
+ return
+ default:
+ }
+
+ names, _ := filepath.Glob(pattern)
+ for _, name := range names {
+ if files[name] != nil {
+ continue
+ }
+ f, _ := os.Open(name)
+ if f != nil {
+ files[name] = f
+ }
+ }
+ }
+}
diff --git a/src/cmd/go/testdata/script/mod_download_exec_toolchain.txt b/src/cmd/go/testdata/script/mod_download_exec_toolchain.txt
new file mode 100644
index 0000000..6cf863b
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_download_exec_toolchain.txt
@@ -0,0 +1,107 @@
+env TESTGO_VERSION=go1.21
+env TESTGO_VERSION_SWITCH=switch
+
+# First, test 'go mod download' outside of a module.
+#
+# There is no go.mod file into which we can record the selected toolchain,
+# so unfortunately these version switches won't be as reproducible as other
+# go commands, but that's still preferable to failing entirely or downloading
+# a module zip that we don't understand.
+
+# GOTOOLCHAIN=auto should run the newer toolchain
+env GOTOOLCHAIN=auto
+go mod download rsc.io/needgo121@latest rsc.io/needgo122@latest rsc.io/needgo123@latest rsc.io/needall@latest
+stderr '^go: rsc.io/needall@v0.0.1 requires go >= 1.23; switching to go1.23.9$'
+! stderr '\(running'
+
+# GOTOOLCHAIN=min+auto should run the newer toolchain
+env GOTOOLCHAIN=go1.21+auto
+go mod download rsc.io/needgo121@latest rsc.io/needgo122@latest rsc.io/needgo123@latest rsc.io/needall@latest
+stderr '^go: rsc.io/needall@v0.0.1 requires go >= 1.23; switching to go1.23.9$'
+! stderr '\(running'
+
+# GOTOOLCHAIN=go1.21 should NOT run the newer toolchain
+env GOTOOLCHAIN=go1.21
+! go mod download rsc.io/needgo121@latest rsc.io/needgo122@latest rsc.io/needgo123@latest rsc.io/needall@latest
+! stderr switching
+stderr 'rsc.io/needgo122@v0.0.1 requires go >= 1.22'
+stderr 'rsc.io/needgo123@v0.0.1 requires go >= 1.23'
+stderr 'rsc.io/needall@v0.0.1 requires go >= 1.23'
+stderr 'requires go >= 1.23'
+! stderr 'requires go >= 1.21' # that's us!
+
+
+# JSON output should be emitted exactly once,
+# and non-JSON output should go to stderr instead of stdout.
+env GOTOOLCHAIN=auto
+go mod download -json rsc.io/needgo121@latest rsc.io/needgo122@latest rsc.io/needgo123@latest rsc.io/needall@latest
+stderr '^go: rsc.io/needall@v0.0.1 requires go >= 1.23; switching to go1.23.9$'
+! stderr '\(running'
+stdout -count=1 '"Path": "rsc.io/needgo121",'
+stdout -count=1 '"Path": "rsc.io/needgo122",'
+stdout -count=1 '"Path": "rsc.io/needgo123",'
+stdout -count=1 '"Path": "rsc.io/needall",'
+
+# GOTOOLCHAIN=go1.21 should write the errors in the JSON Error fields, not to stderr.
+env GOTOOLCHAIN=go1.21
+! go mod download -json rsc.io/needgo121@latest rsc.io/needgo122@latest rsc.io/needgo123@latest rsc.io/needall@latest
+! stderr switching
+stdout -count=1 '"Error": "rsc.io/needgo122@v0.0.1 requires go .*= 1.22 \(running go 1.21; GOTOOLCHAIN=go1.21\)"'
+stdout -count=1 '"Error": "rsc.io/needgo123@v0.0.1 requires go .*= 1.23 \(running go 1.21; GOTOOLCHAIN=go1.21\)"'
+stdout -count=1 '"Error": "rsc.io/needall@v0.0.1 requires go .*= 1.23 \(running go 1.21; GOTOOLCHAIN=go1.21\)"'
+! stdout '"Error": "rsc.io/needgo121' # We can handle this one.
+! stderr .
+
+
+# Within a module, 'go mod download' of explicit versions should upgrade if
+# needed to perform the download, but should not change the main module's
+# toolchain version (because the downloaded modules are still not required by
+# the main module).
+
+cd example
+cp go.mod go.mod.orig
+
+env GOTOOLCHAIN=auto
+go mod download rsc.io/needgo121@latest rsc.io/needgo122@latest rsc.io/needgo123@latest rsc.io/needall@latest
+stderr '^go: rsc.io/needall@v0.0.1 requires go >= 1.23; switching to go1.23.9$'
+! stderr '\(running'
+cmp go.mod go.mod.orig
+
+
+# However, 'go mod download' without arguments should fix up the
+# 'go' and 'toolchain' lines to be consistent with the existing
+# requirements in the module graph.
+
+go mod edit -require=rsc.io/needall@v0.0.1
+cp go.mod go.mod.121
+
+# If an upgrade is needed, GOTOOLCHAIN=go1.21 should cause
+# the command to fail without changing go.mod.
+
+env GOTOOLCHAIN=go1.21
+! go mod download
+stderr 'rsc.io/needall@v0.0.1 requires go >= 1.23'
+! stderr switching
+cmp go.mod go.mod.121
+
+# If an upgrade is needed, GOTOOLCHAIN=auto should perform
+# the upgrade and record the resulting toolchain version.
+
+env GOTOOLCHAIN=auto
+go mod download
+stderr '^go: module rsc.io/needall@v0.0.1 requires go >= 1.23; switching to go1.23.9$'
+cmp go.mod go.mod.final
+
+
+-- example/go.mod --
+module example
+
+go 1.21
+-- example/go.mod.final --
+module example
+
+go 1.23
+
+toolchain go1.23.9
+
+require rsc.io/needall v0.0.1
diff --git a/src/cmd/go/testdata/script/mod_download_git_bareRepository.txt b/src/cmd/go/testdata/script/mod_download_git_bareRepository.txt
new file mode 100644
index 0000000..a61283c
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_download_git_bareRepository.txt
@@ -0,0 +1,28 @@
+[short] skip
+[!git] skip
+
+# Redirect git to a test-specific .gitconfig.
+# GIT_CONFIG_GLOBAL suffices for git 2.32.0 and newer.
+# For older git versions we also set $HOME.
+env GIT_CONFIG_GLOBAL=$WORK${/}home${/}gopher${/}.gitconfig
+env HOME=$WORK${/}home${/}gopher
+exec git config --global --show-origin user.name
+stdout 'Go Gopher'
+
+env GOPRIVATE=vcs-test.golang.org
+
+go mod download -x
+
+-- go.mod --
+module test
+
+go 1.18
+
+require vcs-test.golang.org/git/gitrepo1.git v1.2.3
+
+-- $WORK/home/gopher/.gitconfig --
+[user]
+ name = Go Gopher
+ email = gopher@golang.org
+[safe]
+ bareRepository = explicit
diff --git a/src/cmd/go/testdata/script/mod_download_git_decorate_full.txt b/src/cmd/go/testdata/script/mod_download_git_decorate_full.txt
new file mode 100644
index 0000000..9afd347
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_download_git_decorate_full.txt
@@ -0,0 +1,34 @@
+env GO111MODULE=on
+
+[short] skip
+[!git] skip
+
+# Redirect git to a test-specific .gitconfig.
+# GIT_CONFIG_GLOBAL suffices for git 2.32.0 and newer.
+# For older git versions we also set $HOME.
+env GIT_CONFIG_GLOBAL=$WORK${/}home${/}gopher${/}.gitconfig
+env HOME=$WORK${/}home${/}gopher
+exec git config --global --show-origin user.name
+stdout 'Go Gopher'
+
+env GOPROXY=direct
+
+exec git config --get log.decorate
+stdout 'full'
+
+# Test that Git log with user's global config '~/gitconfig' has log.decorate=full
+# go mod download has an error 'v1.x.y is not a tag'
+# with go1.16.14:
+# `go1.16.14 list -m vcs-test.golang.org/git/gitrepo1.git@v1.2.3`
+# will output with error:
+# go list -m: vcs-test.golang.org/git/gitrepo1.git@v1.2.3: invalid version: unknown revision v1.2.3
+# See golang/go#51312.
+go list -m vcs-test.golang.org/git/gitrepo1.git@v1.2.3
+stdout 'vcs-test.golang.org/git/gitrepo1.git v1.2.3'
+
+-- $WORK/home/gopher/.gitconfig --
+[user]
+ name = Go Gopher
+ email = gopher@golang.org
+[log]
+ decorate = full
diff --git a/src/cmd/go/testdata/script/mod_download_hash.txt b/src/cmd/go/testdata/script/mod_download_hash.txt
new file mode 100644
index 0000000..5677e69
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_download_hash.txt
@@ -0,0 +1,24 @@
+env GO111MODULE=on
+
+# Testing mod download with non semantic versions; turn off proxy.
+[!net:rsc.io] skip
+[!git] skip
+env GOPROXY=direct
+env GOSUMDB=off
+
+go mod download rsc.io/quote@a91498bed0a73d4bb9c1fb2597925f7883bc40a7
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-0.20180709162918-a91498bed0a7.info
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-0.20180709162918-a91498bed0a7.mod
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-0.20180709162918-a91498bed0a7.zip
+
+go mod download rsc.io/quote@master
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-0.20180709162918-a91498bed0a7.info
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-0.20180709162918-a91498bed0a7.mod
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-0.20180709162918-a91498bed0a7.zip
+
+
+-- go.mod --
+module m
+
+-- m.go --
+package m
diff --git a/src/cmd/go/testdata/script/mod_download_insecure_redirect.txt b/src/cmd/go/testdata/script/mod_download_insecure_redirect.txt
new file mode 100644
index 0000000..20a6ac2
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_download_insecure_redirect.txt
@@ -0,0 +1,32 @@
+# golang.org/issue/29591: 'go get' was following plain-HTTP redirects even without -insecure (now replaced by GOINSECURE).
+
+[short] skip
+[!git] skip
+
+env GO111MODULE=on
+env GOPROXY=direct
+env GOSUMDB=off
+
+! go mod download vcs-test.golang.org/insecure/go/insecure@latest
+stderr 'redirected .* to insecure URL'
+
+# insecure host
+env GOINSECURE=vcs-test.golang.org
+go clean -modcache
+go mod download vcs-test.golang.org/insecure/go/insecure@latest
+
+# insecure glob host
+env GOINSECURE=*.golang.org
+go clean -modcache
+go mod download vcs-test.golang.org/insecure/go/insecure@latest
+
+# insecure multiple host
+env GOINSECURE=somewhere-else.com,*.golang.org
+go clean -modcache
+go mod download vcs-test.golang.org/insecure/go/insecure@latest
+
+# different insecure host does not fetch
+env GOINSECURE=somewhere-else.com
+go clean -modcache
+! go mod download vcs-test.golang.org/insecure/go/insecure@latest
+stderr 'redirected .* to insecure URL'
diff --git a/src/cmd/go/testdata/script/mod_download_issue51114.txt b/src/cmd/go/testdata/script/mod_download_issue51114.txt
new file mode 100644
index 0000000..a28d467
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_download_issue51114.txt
@@ -0,0 +1,29 @@
+[!net:github.com] skip
+[!git] skip
+
+# Redirect git to a test-specific .gitconfig.
+# GIT_CONFIG_GLOBAL suffices for git 2.32.0 and newer.
+# For older git versions we also set $HOME.
+env GIT_CONFIG_GLOBAL=$WORK${/}home${/}gopher${/}.gitconfig
+env HOME=$WORK${/}home${/}gopher
+exec git config --global --show-origin user.name
+stdout 'Go Gopher'
+
+env GOPROXY=direct
+
+! go mod download
+stderr '^go: github\.com/golang/notexist/subdir@v0.1.0: reading github\.com/golang/notexist/subdir/go\.mod at revision subdir/v0\.1\.0: '
+
+-- go.mod --
+module test
+
+go 1.18
+
+require github.com/golang/notexist/subdir v0.1.0
+
+-- $WORK/home/gopher/.gitconfig --
+[user]
+ name = Go Gopher
+ email = gopher@golang.org
+[url "git@github.com:"]
+ insteadOf = https://github.com/
diff --git a/src/cmd/go/testdata/script/mod_download_json.txt b/src/cmd/go/testdata/script/mod_download_json.txt
new file mode 100644
index 0000000..9555adf
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_download_json.txt
@@ -0,0 +1,9 @@
+env GO111MODULE=on
+env GOSUMDB=$sumdb' '$proxy/sumdb-wrong
+
+# download -json with version should print JSON on sumdb failure
+! go mod download -json 'rsc.io/quote@<=v1.5.0'
+stdout '"Error": ".*verifying (module|go.mod)'
+
+-- go.mod --
+module m
diff --git a/src/cmd/go/testdata/script/mod_download_partial.txt b/src/cmd/go/testdata/script/mod_download_partial.txt
new file mode 100644
index 0000000..617b1fd
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_download_partial.txt
@@ -0,0 +1,69 @@
+# Download modules and populate go.sum.
+go get -modcacherw
+exists $GOPATH/pkg/mod/rsc.io/quote@v1.5.2/go.mod
+
+# 'go mod verify' should fail if we delete a file.
+go mod verify
+rm $GOPATH/pkg/mod/rsc.io/quote@v1.5.2/go.mod
+! go mod verify
+
+# Create a .partial file to simulate an failure extracting the zip file.
+cp empty $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.partial
+
+# 'go mod verify' should not fail, since the module hasn't been completely
+# ingested into the cache.
+go mod verify
+
+# 'go list' should not load packages from the directory.
+# NOTE: the message "directory $dir outside main module or its selected dependencies"
+# is reported for directories not in the main module, active modules in the
+# module cache, or local replacements. In this case, the directory is in the
+# right place, but it's incomplete, so 'go list' acts as if it's not an
+# active module.
+! go list $GOPATH/pkg/mod/rsc.io/quote@v1.5.2
+stderr 'outside main module or its selected dependencies'
+
+# 'go list -m' should not print the directory.
+go list -m -f '{{.Dir}}' rsc.io/quote
+! stdout .
+
+# 'go mod download' should re-extract the module and remove the .partial file.
+go mod download -modcacherw rsc.io/quote
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.partial
+exists $GOPATH/pkg/mod/rsc.io/quote@v1.5.2/go.mod
+
+# 'go list' should succeed.
+go list $GOPATH/pkg/mod/rsc.io/quote@v1.5.2
+stdout '^rsc.io/quote$'
+
+# 'go list -m' should print the directory.
+go list -m -f '{{.Dir}}' rsc.io/quote
+stdout 'pkg[/\\]mod[/\\]rsc.io[/\\]quote@v1.5.2'
+
+# go mod verify should fail if we delete a file.
+go mod verify
+rm $GOPATH/pkg/mod/rsc.io/quote@v1.5.2/go.mod
+! go mod verify
+
+# 'go mod download' should not leave behind a directory or a .partial file
+# if there is an error extracting the zip file.
+rm $GOPATH/pkg/mod/rsc.io/quote@v1.5.2
+cp empty $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip
+! go mod download
+stderr 'not a valid zip file'
+! exists $GOPATH/pkg/mod/rsc.io/quote@v1.5.2
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.partial
+
+-- go.mod --
+module m
+
+go 1.14
+
+require rsc.io/quote v1.5.2
+
+-- use.go --
+package use
+
+import _ "rsc.io/quote"
+
+-- empty --
diff --git a/src/cmd/go/testdata/script/mod_download_private_vcs.txt b/src/cmd/go/testdata/script/mod_download_private_vcs.txt
new file mode 100644
index 0000000..5c8d93a
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_download_private_vcs.txt
@@ -0,0 +1,48 @@
+env GO111MODULE=on
+
+# Testing stderr for git ls-remote; turn off proxy.
+[!net:github.com] skip
+[!git] skip
+env GOPROXY=direct
+
+# Redirect git to a test-specific .gitconfig.
+# GIT_CONFIG_GLOBAL suffices for git 2.32.0 and newer.
+# For older git versions we also set $HOME.
+env GIT_CONFIG_GLOBAL=$WORK${/}home${/}gopher${/}.gitconfig
+env HOME=$WORK${/}home${/}gopher
+exec git config --global --show-origin user.name
+stdout 'Go Gopher'
+
+! go mod download github.com/golang/nonexist@latest
+stderr 'Confirm the import path was entered correctly.'
+stderr 'If this is a private repository, see https://golang.org/doc/faq#git_https for additional information.'
+! stdout .
+
+# Fetching a nonexistent commit should return an "unknown revision"
+# error message.
+! go mod download github.com/golang/term@86186f3aba07ed0212cfb944f3398997d2d07c6b
+stderr '^go: github.com/golang/term@86186f3aba07ed0212cfb944f3398997d2d07c6b: invalid version: unknown revision 86186f3aba07ed0212cfb944f3398997d2d07c6b$'
+! stdout .
+
+! go mod download github.com/golang/nonexist@master
+stderr '^Confirm the import path was entered correctly.$'
+stderr '^If this is a private repository, see https://golang.org/doc/faq#git_https for additional information.$'
+! stderr 'unknown revision'
+! stdout .
+
+[!exec:false] stop
+
+# Test that Git clone errors will be shown to the user instead of a generic
+# "unknown revision" error. To do this we want to force git ls-remote to return
+# an error we don't already have special handling for. See golang/go#42751.
+exec git config --global url.git@github.com.insteadOf https://github.com/
+env GIT_SSH_COMMAND=false
+! go install github.com/golang/nonexist@master
+stderr 'fatal: Could not read from remote repository.'
+! stderr 'unknown revision'
+! stdout .
+
+-- $WORK/home/gopher/.gitconfig --
+[user]
+ name = Go Gopher
+ email = gopher@golang.org
diff --git a/src/cmd/go/testdata/script/mod_download_replace_file.txt b/src/cmd/go/testdata/script/mod_download_replace_file.txt
new file mode 100644
index 0000000..f6ab4fe
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_download_replace_file.txt
@@ -0,0 +1,16 @@
+# This test checks that 'go mod download' produces no output for
+# the main module (when specified implicitly) and for a module replaced
+# with a file path.
+# Verifies golang.org/issue/35505.
+go mod download -json all
+cmp stdout no-output
+
+-- go.mod --
+module example.com/a
+
+require example.com/b v1.0.0
+
+replace example.com/b => ./local/b
+-- local/b/go.mod --
+module example.com/b
+-- no-output --
diff --git a/src/cmd/go/testdata/script/mod_download_svn.txt b/src/cmd/go/testdata/script/mod_download_svn.txt
new file mode 100644
index 0000000..c11b4f9
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_download_svn.txt
@@ -0,0 +1,29 @@
+[short] skip
+[!exec:svn] skip
+
+# 'go mod download' will fall back to svn+ssh once svn fails over protocols like https.
+# If vcs-test.golang.org isn't in the user's known_hosts file, this will result
+# in an ssh prompt, which will stop 'go test' entirely
+#
+# Unfortunately, there isn't a way to globally disable host checking for ssh,
+# without modifying the real system's or user's configs. Changing $HOME won't
+# affect ssh either, as it ignores the environment variable entirely.
+#
+# However, a useful trick is pointing SVN_SSH to a program that doesn't exist,
+# resulting in svn skipping ssh entirely. Alternatives like
+# SVN_SSH="ssh -o StrictHostKeyChecking=no" didn't avoid the prompt.
+env SVN_SSH="svn_do_not_use_ssh"
+
+env GO111MODULE=on
+env GOPROXY=direct
+env GOSUMDB=off
+
+# Attempting to get a module zip using svn should succeed.
+go mod download vcs-test.golang.org/svn/hello.svn@000000000001
+exists $GOPATH/pkg/mod/cache/download/vcs-test.golang.org/svn/hello.svn/@v/v0.0.0-20170922011245-000000000001.zip
+
+# Attempting to get a nonexistent module using svn should fail with a
+# reasonable message instead of a panic.
+! go mod download vcs-test.golang.org/svn/nonexistent.svn@latest
+! stderr panic
+stderr 'go: module vcs-test.golang.org/svn/nonexistent.svn: no matching versions for query "latest"$'
diff --git a/src/cmd/go/testdata/script/mod_download_too_many_redirects.txt b/src/cmd/go/testdata/script/mod_download_too_many_redirects.txt
new file mode 100644
index 0000000..a6b5a59
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_download_too_many_redirects.txt
@@ -0,0 +1,10 @@
+env GO111MODULE=on
+env GOPROXYBASE=$GOPROXY
+env GOPROXY=$GOPROXYBASE/redirect/11
+env GOSUMDB=off
+
+! go mod download rsc.io/quote@v1.2.0
+stderr 'stopped after 10 redirects'
+
+env GOPROXY=$GOPROXYBASE/redirect/9
+go mod download rsc.io/quote@v1.2.0
diff --git a/src/cmd/go/testdata/script/mod_e.txt b/src/cmd/go/testdata/script/mod_e.txt
new file mode 100644
index 0000000..6497e6c
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_e.txt
@@ -0,0 +1,96 @@
+cp go.mod go.mod.orig
+
+
+# If a dependency cannot be resolved, 'go mod tidy' fails with an error message
+# explaining the problem and does not update the go.mod file.
+# TODO(bcmills): Ideally, with less redundancy than these error messages!
+
+! go mod tidy
+
+stderr '^go: example.com/untidy imports\n\texample.net/directnotfound: cannot find module providing package example.net/directnotfound: module example.net/directnotfound: reading http://.*: 404 Not Found$'
+
+stderr '^go: example.com/untidy imports\n\texample.net/m imports\n\texample.net/indirectnotfound: cannot find module providing package example.net/indirectnotfound: module example.net/indirectnotfound: reading http://.*: 404 Not Found$'
+
+stderr '^go: example.com/untidy tested by\n\texample.com/untidy.test imports\n\texample.net/directtestnotfound: cannot find module providing package example.net/directtestnotfound: module example.net/directtestnotfound: reading http://.*: 404 Not Found$'
+
+stderr '^go: example.com/untidy imports\n\texample.net/m tested by\n\texample.net/m.test imports\n\texample.net/indirecttestnotfound: cannot find module providing package example.net/indirecttestnotfound: module example.net/indirecttestnotfound: reading http://.*: 404 Not Found$'
+
+cmp go.mod.orig go.mod
+
+
+# If a dependency cannot be resolved, 'go mod vendor' fails with an error message
+# explaining the problem, does not update the go.mod file, and does not create
+# the vendor directory.
+
+! go mod vendor
+
+stderr '^go: example.com/untidy imports\n\texample.net/directnotfound: no required module provides package example.net/directnotfound; to add it:\n\tgo get example.net/directnotfound$'
+
+stderr '^go: example.com/untidy imports\n\texample.net/m: module example.net/m provides package example.net/m and is replaced but not required; to add it:\n\tgo get example.net/m@v0.1.0$'
+
+stderr '^go: example.com/untidy tested by\n\texample.com/untidy.test imports\n\texample.net/directtestnotfound: no required module provides package example.net/directtestnotfound; to add it:\n\tgo get example.net/directtestnotfound$'
+
+! stderr 'indirecttestnotfound' # Vendor prunes test dependencies.
+
+cmp go.mod.orig go.mod
+! exists vendor
+
+
+# 'go mod tidy' still logs the errors, but succeeds and updates go.mod.
+
+go mod tidy -e
+stderr -count=4 'cannot find module providing package'
+cmp go.mod.final go.mod
+
+
+# 'go mod vendor -e' still logs the errors, but creates a vendor directory
+# and exits with status 0.
+# 'go mod vendor -e' does not update go.mod and will not vendor packages that
+# would require changing go.mod, for example, by adding a requirement.
+cp go.mod.orig go.mod
+go mod vendor -e
+stderr -count=2 'no required module provides package'
+stderr '^go: example.com/untidy imports\n\texample.net/m: module example.net/m provides package example.net/m and is replaced but not required; to add it:\n\tgo get example.net/m@v0.1.0$'
+exists vendor/modules.txt
+! exists vendor/example.net
+
+go mod edit -require example.net/m@v0.1.0
+go mod vendor -e
+stderr -count=3 'no required module provides package'
+exists vendor/modules.txt
+exists vendor/example.net/m/m.go
+
+-- go.mod --
+module example.com/untidy
+go 1.16
+replace example.net/m v0.1.0 => ./m
+-- go.mod.final --
+module example.com/untidy
+
+go 1.16
+
+replace example.net/m v0.1.0 => ./m
+
+require example.net/m v0.1.0
+-- untidy.go --
+package untidy
+
+import (
+ _ "example.net/m"
+ _ "example.net/directnotfound"
+)
+-- untidy_test.go --
+package untidy_test
+
+import _ "example.net/directtestnotfound"
+-- m/go.mod --
+module example.net/m
+go 1.16
+-- m/m.go --
+package m
+
+import _ "example.net/indirectnotfound"
+-- m/m_test.go --
+package m_test
+
+import _ "example.net/indirecttestnotfound"
diff --git a/src/cmd/go/testdata/script/mod_edit.txt b/src/cmd/go/testdata/script/mod_edit.txt
new file mode 100644
index 0000000..2d09b06
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_edit.txt
@@ -0,0 +1,340 @@
+env GO111MODULE=on
+
+# Test that go mod edits and related mod flags work.
+# Also test that they can use a dummy name that isn't resolvable. golang.org/issue/24100
+
+# go mod init
+! go mod init
+stderr 'cannot determine module path'
+! exists go.mod
+
+go mod init x.x/y/z
+stderr 'creating new go.mod: module x.x/y/z'
+cmpenv go.mod $WORK/go.mod.init
+
+! go mod init
+cmpenv go.mod $WORK/go.mod.init
+
+# go mod edits
+go mod edit -droprequire=x.1 -require=x.1@v1.0.0 -require=x.2@v1.1.0 -droprequire=x.2 -exclude='x.1 @ v1.2.0' -exclude=x.1@v1.2.1 -exclude=x.1@v2.0.0+incompatible -replace=x.1@v1.3.0=y.1@v1.4.0 -replace='x.1@v1.4.0 = ../z' -retract=v1.6.0 -retract=[v1.1.0,v1.2.0] -retract=[v1.3.0,v1.4.0] -retract=v1.0.0
+cmpenv go.mod $WORK/go.mod.edit1
+go mod edit -droprequire=x.1 -dropexclude=x.1@v1.2.1 -dropexclude=x.1@v2.0.0+incompatible -dropreplace=x.1@v1.3.0 -require=x.3@v1.99.0 -dropretract=v1.0.0 -dropretract=[v1.1.0,v1.2.0]
+cmpenv go.mod $WORK/go.mod.edit2
+
+# -exclude and -retract reject invalid versions.
+! go mod edit -exclude=example.com/m@bad
+stderr '^go: -exclude=example.com/m@bad: version "bad" invalid: must be of the form v1.2.3$'
+! go mod edit -retract=bad
+stderr '^go: -retract=bad: version "bad" invalid: must be of the form v1.2.3$'
+
+! go mod edit -exclude=example.com/m@v2.0.0
+stderr '^go: -exclude=example.com/m@v2\.0\.0: version "v2\.0\.0" invalid: should be v2\.0\.0\+incompatible \(or module example\.com/m/v2\)$'
+
+! go mod edit -exclude=example.com/m/v2@v1.0.0
+stderr '^go: -exclude=example.com/m/v2@v1\.0\.0: version "v1\.0\.0" invalid: should be v2, not v1$'
+
+! go mod edit -exclude=gopkg.in/example.v1@v2.0.0
+stderr '^go: -exclude=gopkg\.in/example\.v1@v2\.0\.0: version "v2\.0\.0" invalid: should be v1, not v2$'
+
+cmpenv go.mod $WORK/go.mod.edit2
+
+# go mod edit -json
+go mod edit -json
+cmpenv stdout $WORK/go.mod.json
+
+# go mod edit -json (retractions with rationales)
+go mod edit -json $WORK/go.mod.retractrationale
+cmp stdout $WORK/go.mod.retractrationale.json
+
+# go mod edit -json (deprecation)
+go mod edit -json $WORK/go.mod.deprecation
+cmp stdout $WORK/go.mod.deprecation.json
+
+# go mod edit -json (empty mod file)
+go mod edit -json $WORK/go.mod.empty
+cmp stdout $WORK/go.mod.empty.json
+
+# go mod edit -replace
+go mod edit -replace=x.1@v1.3.0=y.1/v2@v2.3.5 -replace=x.1@v1.4.0=y.1/v2@v2.3.5
+cmpenv go.mod $WORK/go.mod.edit3
+go mod edit -replace=x.1=y.1/v2@v2.3.6
+cmpenv go.mod $WORK/go.mod.edit4
+go mod edit -dropreplace=x.1
+cmpenv go.mod $WORK/go.mod.edit5
+go mod edit -replace=x.1=../y.1/@v2
+cmpenv go.mod $WORK/go.mod.edit6
+! go mod edit -replace=x.1=y.1/@v2
+stderr '^go: -replace=x.1=y.1/@v2: invalid new path: malformed import path "y.1/": trailing slash$'
+
+# go mod edit -fmt
+cp $WORK/go.mod.badfmt go.mod
+go mod edit -fmt -print # -print should avoid writing file
+cmpenv stdout $WORK/go.mod.goodfmt
+cmp go.mod $WORK/go.mod.badfmt
+go mod edit -fmt # without -print, should write file (and nothing to stdout)
+! stdout .
+cmpenv go.mod $WORK/go.mod.goodfmt
+
+# go mod edit -module
+cd $WORK/m
+go mod init a.a/b/c
+go mod edit -module x.x/y/z
+cmpenv go.mod go.mod.edit
+
+# golang.org/issue/30513: don't require go-gettable module paths.
+cd $WORK/local
+go mod init foo
+go mod edit -module local-only -require=other-local@v1.0.0 -replace other-local@v1.0.0=./other
+cmpenv go.mod go.mod.edit
+
+-- x.go --
+package x
+
+-- w/w.go --
+package w
+
+-- $WORK/go.mod.init --
+module x.x/y/z
+
+go $goversion
+-- $WORK/go.mod.edit1 --
+module x.x/y/z
+
+go $goversion
+
+require x.1 v1.0.0
+
+exclude (
+ x.1 v1.2.0
+ x.1 v1.2.1
+ x.1 v2.0.0+incompatible
+)
+
+replace (
+ x.1 v1.3.0 => y.1 v1.4.0
+ x.1 v1.4.0 => ../z
+)
+
+retract (
+ v1.6.0
+ [v1.3.0, v1.4.0]
+ [v1.1.0, v1.2.0]
+ v1.0.0
+)
+-- $WORK/go.mod.edit2 --
+module x.x/y/z
+
+go $goversion
+
+exclude x.1 v1.2.0
+
+replace x.1 v1.4.0 => ../z
+
+retract (
+ v1.6.0
+ [v1.3.0, v1.4.0]
+)
+
+require x.3 v1.99.0
+-- $WORK/go.mod.json --
+{
+ "Module": {
+ "Path": "x.x/y/z"
+ },
+ "Go": "$goversion",
+ "Require": [
+ {
+ "Path": "x.3",
+ "Version": "v1.99.0"
+ }
+ ],
+ "Exclude": [
+ {
+ "Path": "x.1",
+ "Version": "v1.2.0"
+ }
+ ],
+ "Replace": [
+ {
+ "Old": {
+ "Path": "x.1",
+ "Version": "v1.4.0"
+ },
+ "New": {
+ "Path": "../z"
+ }
+ }
+ ],
+ "Retract": [
+ {
+ "Low": "v1.6.0",
+ "High": "v1.6.0"
+ },
+ {
+ "Low": "v1.3.0",
+ "High": "v1.4.0"
+ }
+ ]
+}
+-- $WORK/go.mod.edit3 --
+module x.x/y/z
+
+go $goversion
+
+exclude x.1 v1.2.0
+
+replace (
+ x.1 v1.3.0 => y.1/v2 v2.3.5
+ x.1 v1.4.0 => y.1/v2 v2.3.5
+)
+
+retract (
+ v1.6.0
+ [v1.3.0, v1.4.0]
+)
+
+require x.3 v1.99.0
+-- $WORK/go.mod.edit4 --
+module x.x/y/z
+
+go $goversion
+
+exclude x.1 v1.2.0
+
+replace x.1 => y.1/v2 v2.3.6
+
+retract (
+ v1.6.0
+ [v1.3.0, v1.4.0]
+)
+
+require x.3 v1.99.0
+-- $WORK/go.mod.edit5 --
+module x.x/y/z
+
+go $goversion
+
+exclude x.1 v1.2.0
+
+retract (
+ v1.6.0
+ [v1.3.0, v1.4.0]
+)
+
+require x.3 v1.99.0
+-- $WORK/go.mod.edit6 --
+module x.x/y/z
+
+go $goversion
+
+exclude x.1 v1.2.0
+
+retract (
+ v1.6.0
+ [v1.3.0, v1.4.0]
+)
+
+require x.3 v1.99.0
+
+replace x.1 => ../y.1/@v2
+-- $WORK/local/go.mod.edit --
+module local-only
+
+go $goversion
+
+require other-local v1.0.0
+
+replace other-local v1.0.0 => ./other
+-- $WORK/go.mod.badfmt --
+module x.x/y/z
+
+go 1.10
+
+exclude x.1 v1.2.0
+
+replace x.1 => y.1/v2 v2.3.6
+
+require x.3 v1.99.0
+
+retract [ "v1.8.1" , "v1.8.2" ]
+-- $WORK/go.mod.goodfmt --
+module x.x/y/z
+
+go 1.10
+
+exclude x.1 v1.2.0
+
+replace x.1 => y.1/v2 v2.3.6
+
+require x.3 v1.99.0
+
+retract [v1.8.1, v1.8.2]
+-- $WORK/m/go.mod.edit --
+module x.x/y/z
+
+go $goversion
+-- $WORK/go.mod.retractrationale --
+module x.x/y/z
+
+go 1.15
+
+// a
+retract v1.0.0
+
+// b
+retract (
+ v1.0.1
+ v1.0.2 // c
+)
+-- $WORK/go.mod.retractrationale.json --
+{
+ "Module": {
+ "Path": "x.x/y/z"
+ },
+ "Go": "1.15",
+ "Require": null,
+ "Exclude": null,
+ "Replace": null,
+ "Retract": [
+ {
+ "Low": "v1.0.0",
+ "High": "v1.0.0",
+ "Rationale": "a"
+ },
+ {
+ "Low": "v1.0.1",
+ "High": "v1.0.1",
+ "Rationale": "b"
+ },
+ {
+ "Low": "v1.0.2",
+ "High": "v1.0.2",
+ "Rationale": "c"
+ }
+ ]
+}
+-- $WORK/go.mod.deprecation --
+// Deprecated: and the new one is not ready yet
+module m
+-- $WORK/go.mod.deprecation.json --
+{
+ "Module": {
+ "Path": "m",
+ "Deprecated": "and the new one is not ready yet"
+ },
+ "Require": null,
+ "Exclude": null,
+ "Replace": null,
+ "Retract": null
+}
+-- $WORK/go.mod.empty --
+-- $WORK/go.mod.empty.json --
+{
+ "Module": {
+ "Path": ""
+ },
+ "Require": null,
+ "Exclude": null,
+ "Replace": null,
+ "Retract": null
+}
diff --git a/src/cmd/go/testdata/script/mod_edit_go.txt b/src/cmd/go/testdata/script/mod_edit_go.txt
new file mode 100644
index 0000000..ec04f40
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_edit_go.txt
@@ -0,0 +1,26 @@
+# Test support for go mod edit -go to set language version.
+
+env GO111MODULE=on
+! go build
+stderr ' type aliases requires'
+go mod edit -go=1.9
+grep 'go 1.9' go.mod
+go build
+
+# Reverting the version should force a rebuild and error instead of using
+# the cached 1.9 build. (https://golang.org/issue/37804)
+go mod edit -go=1.8
+! go build
+stderr 'type aliases requires'
+
+# go=none should drop the line
+go mod edit -go=none
+! grep go go.mod
+
+-- go.mod --
+module m
+go 1.8
+
+-- alias.go --
+package alias
+type T = int
diff --git a/src/cmd/go/testdata/script/mod_edit_no_modcache.txt b/src/cmd/go/testdata/script/mod_edit_no_modcache.txt
new file mode 100644
index 0000000..ced15bb
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_edit_no_modcache.txt
@@ -0,0 +1,15 @@
+# 'go mod edit' opportunistically locks the side-lock file in the module cache,
+# for compatibility with older versions of the 'go' command.
+# It does not otherwise depend on the module cache, so it should not
+# fail if the module cache directory cannot be created.
+
+[root] skip
+
+mkdir $WORK/readonly
+chmod 0555 $WORK/readonly
+env GOPATH=$WORK/readonly/nonexist
+
+go mod edit -go=1.17
+
+-- go.mod --
+module example.com/m
diff --git a/src/cmd/go/testdata/script/mod_edit_toolchain.txt b/src/cmd/go/testdata/script/mod_edit_toolchain.txt
new file mode 100644
index 0000000..bb544be
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_edit_toolchain.txt
@@ -0,0 +1,18 @@
+# Test support for go mod edit -toolchain to set toolchain to use
+
+env GOTOOLCHAIN=local
+env GO111MODULE=on
+
+! grep toolchain go.mod
+go mod edit -toolchain=go1.9
+grep 'toolchain go1.9' go.mod
+
+go mod edit -toolchain=default
+grep 'toolchain default' go.mod
+
+go mod edit -toolchain=none
+! grep toolchain go.mod
+
+-- go.mod --
+module m
+go 1.8
diff --git a/src/cmd/go/testdata/script/mod_empty_err.txt b/src/cmd/go/testdata/script/mod_empty_err.txt
new file mode 100644
index 0000000..4b4a007
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_empty_err.txt
@@ -0,0 +1,36 @@
+# This test checks error messages for non-existent packages in module mode.
+# Veries golang.org/issue/35414
+env GO111MODULE=on
+cd $WORK
+
+go list -e -f {{.Error}} .
+stdout 'no Go files in '$WORK
+
+go list -e -f {{.Error}} ./empty
+stdout 'no Go files in '$WORK${/}'empty'
+
+go list -e -f {{.Error}} ./exclude
+stdout 'build constraints exclude all Go files in '$WORK${/}'exclude'
+
+go list -e -f {{.Error}} ./missing
+stdout 'stat '$WORK'[/\\]missing: directory not found'
+
+# use 'go build -n' because 'go list' reports no error.
+! go build -n ./testonly
+stderr 'example.com/m/testonly: no non-test Go files in '$WORK${/}'testonly'
+
+-- $WORK/go.mod --
+module example.com/m
+
+go 1.14
+
+-- $WORK/empty/empty.txt --
+-- $WORK/exclude/exclude.go --
+// +build exclude
+
+package exclude
+-- $WORK/testonly/testonly_test.go --
+package testonly_test
+-- $WORK/excluded-stdout --
+package ./excluded: cannot find package "." in:
+ $WORK/excluded
diff --git a/src/cmd/go/testdata/script/mod_enabled.txt b/src/cmd/go/testdata/script/mod_enabled.txt
new file mode 100644
index 0000000..39f1ece
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_enabled.txt
@@ -0,0 +1,93 @@
+# GO111MODULE=auto should trigger any time a go.mod exists in a parent directory.
+env GO111MODULE=auto
+
+cd $GOPATH/src/x/y/z
+go env GOMOD
+stdout $GOPATH[/\\]src[/\\]x[/\\]y[/\\]z[/\\]go.mod
+go list -m -f {{.GoMod}}
+stdout $GOPATH[/\\]src[/\\]x[/\\]y[/\\]z[/\\]go.mod
+
+cd $GOPATH/src/x/y/z/w
+go env GOMOD
+stdout $GOPATH[/\\]src[/\\]x[/\\]y[/\\]z[/\\]go.mod
+
+cd $GOPATH/src/x/y
+go env GOMOD
+! stdout .
+
+cd $GOPATH/foo
+go env GOMOD
+stdout foo[/\\]go.mod
+go list -m -f {{.GoMod}}
+stdout foo[/\\]go.mod
+
+cd $GOPATH/foo/bar/baz
+go env GOMOD
+stdout foo[/\\]go.mod
+
+# GO111MODULE unset should be equivalent to on.
+env GO111MODULE=
+
+cd $GOPATH/src/x/y/z
+go env GOMOD
+stdout $GOPATH[/\\]src[/\\]x[/\\]y[/\\]z[/\\]go.mod
+
+cd $GOPATH/src/x/y
+go env GOMOD
+stdout 'NUL|/dev/null'
+
+# GO111MODULE=on should trigger everywhere
+env GO111MODULE=on
+
+cd $GOPATH/src/x/y/z
+go env GOMOD
+stdout z[/\\]go.mod
+
+cd $GOPATH/src/x/y/z/w
+go env GOMOD
+stdout z[/\\]go.mod
+
+cd $GOPATH/src/x/y
+go env GOMOD
+stdout 'NUL|/dev/null'
+go list -m
+stdout '^command-line-arguments$'
+
+cd $GOPATH/foo
+go env GOMOD
+stdout foo[/\\]go.mod
+
+cd $GOPATH/foo/bar/baz
+go env GOMOD
+stdout foo[/\\]go.mod
+
+# GO111MODULE=off should trigger nowhere
+env GO111MODULE=off
+
+cd $GOPATH/src/x/y/z
+go env GOMOD
+! stdout .+
+
+cd $GOPATH/foo
+go env GOMOD
+! stdout .+
+
+cd $GOPATH/foo/bar/baz
+go env GOMOD
+! stdout .+
+
+# GO111MODULE=auto should ignore and warn about /tmp/go.mod
+env GO111MODULE=auto
+cp $GOPATH/src/x/y/z/go.mod $WORK/tmp/go.mod
+mkdir $WORK/tmp/mydir
+cd $WORK/tmp/mydir
+go env GOMOD
+! stdout .+
+stderr '^go: warning: ignoring go.mod in system temp root '
+
+-- $GOPATH/src/x/y/z/go.mod --
+module x/y/z
+-- $GOPATH/src/x/y/z/w/w.txt --
+-- $GOPATH/foo/go.mod --
+module example.com/mod
+-- $GOPATH/foo/bar/baz/quux.txt --
diff --git a/src/cmd/go/testdata/script/mod_exclude_go121.txt b/src/cmd/go/testdata/script/mod_exclude_go121.txt
new file mode 100644
index 0000000..51c8a00
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_exclude_go121.txt
@@ -0,0 +1,34 @@
+# go.dev/issue/60028: use semver sort in exclude block in 1.21
+cp $WORK/go.mod.badfmtexclude go.mod
+go mod edit -go=1.20
+cmp go.mod $WORK/go.mod.goodfmtexclude120
+go mod edit -go=1.21
+cmp go.mod $WORK/go.mod.goodfmtexclude121
+
+-- $WORK/go.mod.badfmtexclude --
+module x.x/y/z
+exclude (
+ x.1 v1.11.0
+ x.1 v1.10.0
+ x.1 v1.9.0
+)
+-- $WORK/go.mod.goodfmtexclude120 --
+module x.x/y/z
+
+go 1.20
+
+exclude (
+ x.1 v1.10.0
+ x.1 v1.11.0
+ x.1 v1.9.0
+)
+-- $WORK/go.mod.goodfmtexclude121 --
+module x.x/y/z
+
+go 1.21
+
+exclude (
+ x.1 v1.9.0
+ x.1 v1.10.0
+ x.1 v1.11.0
+)
diff --git a/src/cmd/go/testdata/script/mod_file_proxy.txt b/src/cmd/go/testdata/script/mod_file_proxy.txt
new file mode 100644
index 0000000..ebc28a0
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_file_proxy.txt
@@ -0,0 +1,36 @@
+[short] skip
+
+# Allow (cached) downloads for -mod=readonly.
+env GO111MODULE=on
+env GOPATH=$WORK/gopath1
+cd $WORK/x
+go mod edit -fmt
+go list -mod=readonly
+env GOPROXY=file:///nonexist
+go list
+grep v1.5.1 $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/list
+
+# Use download cache as file:/// proxy.
+env GOPATH=$WORK/gopath2
+[GOOS:windows] env GOPROXY=file:///C:/nonexist
+[!GOOS:windows] env GOPROXY=file:///nonexist
+! go list
+[GOOS:windows] env GOPROXY=file:///$WORK/gopath1/pkg/mod/cache/download
+[!GOOS:windows] env GOPROXY=file://$WORK/gopath1/pkg/mod/cache/download
+go list
+grep v1.5.1 $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/list
+
+-- $WORK/x/go.mod --
+module x
+go 1.13
+require rsc.io/quote v1.5.1
+-- $WORK/x/x.go --
+package x
+import _ "rsc.io/quote"
+-- $WORK/x/go.sum --
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw=
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+rsc.io/quote v1.5.1 h1:ZE3OgnVGrhXtFkGw90HwW992ZRqcdli/33DLqEYsoxA=
+rsc.io/quote v1.5.1/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
+rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
diff --git a/src/cmd/go/testdata/script/mod_fileproxy_vcs_missing_issue51589.txt b/src/cmd/go/testdata/script/mod_fileproxy_vcs_missing_issue51589.txt
new file mode 100644
index 0000000..633bd8b
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_fileproxy_vcs_missing_issue51589.txt
@@ -0,0 +1,42 @@
+# This test checks that "go mod tidy -e" do not panic when
+# using a file goproxy that is missing some modules.
+# Verifies golang.org/issue/51589
+
+# download the modules first
+env GO111MODULE=on
+env GOPATH=$WORK/gopath
+cd $WORK/x
+go mod tidy
+
+# Use download cache as file:/// proxy.
+[GOOS:windows] env GOPROXY=file:///$WORK/gopath/pkg/mod/cache/download
+[!GOOS:windows] env GOPROXY=file://$WORK/gopath/pkg/mod/cache/download
+rm $WORK/gopath/pkg/mod/cache/download/golang.org/x/text/
+go mod tidy -e
+stderr '^go: rsc.io/sampler@v1.3.0 requires\n\tgolang.org/x/text@.*: reading file://.*/pkg/mod/cache/download/golang.org/x/text/.*'
+! stderr 'signal SIGSEGV: segmentation violation'
+
+-- $WORK/x/go.mod --
+module example.com/mod
+
+go 1.17
+
+require rsc.io/quote v1.5.2
+
+require (
+ golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c // indirect
+ rsc.io/sampler v1.3.0 // indirect
+)
+
+-- $WORK/x/x.go --
+package mod
+
+import (
+ "fmt"
+
+ "rsc.io/quote"
+)
+
+func Echo() {
+ fmt.Println(quote.Hello())
+}
diff --git a/src/cmd/go/testdata/script/mod_find.txt b/src/cmd/go/testdata/script/mod_find.txt
new file mode 100644
index 0000000..9c2037b
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_find.txt
@@ -0,0 +1,104 @@
+env GO111MODULE=on
+
+# Derive module path from import comment.
+cd $WORK/x
+exists x.go
+go mod init
+stderr 'module x'
+
+# Import comment works even with CRLF line endings.
+rm go.mod
+replace '\n' '\r\n' x.go
+go mod init
+stderr 'module x'
+
+# Derive module path from location inside GOPATH.
+# 'go mod init' should succeed if modules are not explicitly disabled.
+cd $GOPATH/src/example.com/x/y
+go mod init
+stderr 'module example.com/x/y$'
+rm go.mod
+
+# go mod init rejects a zero-length go.mod file
+cp $devnull go.mod # can't use touch to create it because Windows
+! go mod init
+stderr 'go.mod already exists'
+
+# Module path from Godeps/Godeps.json overrides GOPATH.
+cd $GOPATH/src/example.com/x/y/z
+go mod init
+stderr 'unexpected.com/z'
+rm go.mod
+
+# Empty directory outside GOPATH fails.
+mkdir $WORK/empty
+cd $WORK/empty
+! go mod init
+stderr 'cannot determine module path for source directory'
+rm go.mod
+
+# Empty directory inside GOPATH/src uses location inside GOPATH.
+mkdir $GOPATH/src/empty
+cd $GOPATH/src/empty
+go mod init
+stderr 'empty'
+rm go.mod
+
+# In Plan 9, directories are automatically created in /n.
+# For example, /n/go.mod always exist, but it's a directory.
+# Test that we ignore directories when trying to find go.mod.
+cd $WORK/gomoddir
+! go list .
+stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
+
+[!symlink] stop
+
+# gplink1/src/empty where gopathlink -> GOPATH
+symlink $WORK/gopathlink -> gopath
+cd $WORK/gopathlink/src/empty
+go mod init
+rm go.mod
+
+# GOPATH/src/link where link -> out of GOPATH
+symlink $GOPATH/src/link -> $WORK/empty
+cd $WORK/empty
+! go mod init
+cd $GOPATH/src/link
+go mod init
+stderr link
+rm go.mod
+
+# GOPATH/src/empty where GOPATH itself is a symlink
+env GOPATH=$WORK/gopathlink
+cd $GOPATH/src/empty
+go mod init
+rm go.mod
+cd $WORK/gopath/src/empty
+go mod init
+rm go.mod
+
+# GOPATH/src/link where GOPATH and link are both symlinks
+cd $GOPATH/src/link
+go mod init
+stderr link
+rm go.mod
+
+# Too hard: doesn't match unevaluated nor completely evaluated. (Only partially evaluated.)
+# Whether this works depends on which OS we are running on.
+# cd $WORK/gopath/src/link
+# ! go mod init
+
+-- $WORK/x/x.go --
+package x // import "x"
+
+-- $GOPATH/src/example.com/x/y/y.go --
+package y
+-- $GOPATH/src/example.com/x/y/z/z.go --
+package z
+-- $GOPATH/src/example.com/x/y/z/Godeps/Godeps.json --
+{"ImportPath": "unexpected.com/z"}
+
+-- $WORK/gomoddir/go.mod/README.txt --
+../go.mod is a directory, not a file.
+-- $WORK/gomoddir/p.go --
+package p
diff --git a/src/cmd/go/testdata/script/mod_fs_patterns.txt b/src/cmd/go/testdata/script/mod_fs_patterns.txt
new file mode 100644
index 0000000..c834ce8
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_fs_patterns.txt
@@ -0,0 +1,97 @@
+env GO111MODULE=on
+
+# File system pattern searches should skip sub-modules and vendor directories.
+cd x
+
+# all packages
+go list all
+stdout ^m$
+stdout ^m/vendor$
+! stdout vendor/
+stdout ^m/y$
+! stdout ^m/y/z
+
+# path pattern
+go list m/...
+stdout ^m$
+stdout ^m/vendor$
+! stdout vendor/
+stdout ^m/y$
+! stdout ^m/y/z
+
+# directory pattern
+go list ./...
+stdout ^m$
+stdout ^m/vendor$
+! stdout vendor/
+stdout ^m/y$
+! stdout ^m/y/z
+
+# non-existent directory should not prompt lookups
+! go build -mod=readonly example.com/nonexist
+stderr 'import lookup disabled'
+
+! go build -mod=readonly ./nonexist
+! stderr 'import lookup disabled'
+stderr '^stat '$GOPATH'[/\\]src[/\\]x[/\\]nonexist: directory not found'
+
+! go build -mod=readonly ./go.mod
+! stderr 'import lookup disabled'
+stderr 'main module \(m\) does not contain package m/go.mod'
+
+
+# File system paths and patterns should allow the '@' character.
+cd ../@at
+go list $PWD
+stdout '^at$'
+go list $PWD/...
+stdout '^at$'
+
+# The '@' character is not allowed in directory paths that are part of
+# a package path.
+cd ../badat/bad@
+! go list .
+stderr 'current directory outside main module or its selected dependencies'
+! go list $PWD
+stderr 'current directory outside main module or its selected dependencies'
+! go list $PWD/...
+stderr 'current directory outside main module or its selected dependencies'
+
+-- x/go.mod --
+module m
+
+-- x/x.go --
+package x
+
+-- x/vendor/v/v.go --
+package v
+import _ "golang.org/x/crypto"
+
+-- x/vendor/v.go --
+package main
+
+-- x/y/y.go --
+package y
+
+-- x/y/z/go.mod --
+syntax error!
+
+-- x/y/z/z.go --
+package z
+
+-- x/y/z/w/w.go --
+package w
+
+-- @at/go.mod --
+module at
+
+go 1.14
+-- @at/at.go --
+package at
+
+-- badat/go.mod --
+module badat
+
+go 1.14
+-- badat/bad@/bad.go --
+package bad
diff --git a/src/cmd/go/testdata/script/mod_get_ambiguous_arg.txt b/src/cmd/go/testdata/script/mod_get_ambiguous_arg.txt
new file mode 100644
index 0000000..9214993
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_ambiguous_arg.txt
@@ -0,0 +1,107 @@
+go mod tidy
+cp go.mod go.mod.orig
+
+# If there is no sensible *package* meaning for 'm/p', it should refer
+# to *module* m/p.
+
+go get m/p # @latest
+go list -m all
+stdout '^m/p v0.3.0 '
+! stdout '^m '
+
+cp go.mod.orig go.mod
+
+go get m/p@v0.1.0
+go list -m all
+stdout '^m/p v0.1.0 '
+! stdout '^m '
+
+# When feasible, the argument 'm/p' in 'go get m/p' refers to *package* m/p,
+# which is in module m.
+#
+# (It only refers to *module* m/p if there is no such package at the
+# requested version.)
+
+go get m/p@v0.2.0
+go list -m all
+stdout '^m v0.2.0 '
+stdout '^m/p v0.1.0 ' # unchanged from the previous case
+
+# Repeating the above with module m/p already in the module graph does not
+# change its meaning.
+
+go get m/p@v0.2.0
+go list -m all
+stdout '^m v0.2.0 '
+stdout '^m/p v0.1.0 '
+
+-- go.mod --
+module example.com
+
+go 1.16
+
+replace (
+ m v0.1.0 => ./m01
+ m v0.2.0 => ./m02
+ m v0.3.0 => ./m03
+ m/p v0.1.0 => ./mp01
+ m/p v0.2.0 => ./mp02
+ m/p v0.3.0 => ./mp03
+)
+-- m01/go.mod --
+module m
+
+go 1.16
+-- m01/README.txt --
+Module m at v0.1.0 does not yet contain package p.
+
+-- m02/go.mod --
+module m
+
+go 1.16
+
+require m/p v0.1.0
+-- m02/p/p.go --
+// Package p is present in module m, but not module m/p.
+package p
+
+-- m03/go.mod --
+module m
+
+go 1.16
+
+require m/p v0.1.0
+-- m03/README.txt --
+Module m at v0.3.0 no longer contains package p.
+
+-- mv2/go.mod --
+module m/v2
+
+go 1.16
+-- mv2/README.txt --
+This module is m/v2. It doesn't actually need to exist,
+but it explains how module m could plausibly exist
+and still contain package p at 'latest' even when module
+m/p also exists.
+
+-- mp01/go.mod --
+module m/p
+
+go 1.16
+-- mp01/README.txt --
+This module is m/p.
+Package m/p does not exist in this module.
+-- mp02/go.mod --
+module m/p
+
+go 1.16
+-- mp02/README.txt --
+This module is m/p.
+Package m/p does not exist in this module.
+-- mp03/go.mod --
+module m/p
+
+go 1.16
+-- mp03/README.txt --
+This module is m/p.
+Package m/p does not exist in this module.
diff --git a/src/cmd/go/testdata/script/mod_get_ambiguous_import.txt b/src/cmd/go/testdata/script/mod_get_ambiguous_import.txt
new file mode 100644
index 0000000..f08e540
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_ambiguous_import.txt
@@ -0,0 +1,60 @@
+go list -m all
+stdout '^example.net/m v0.1.0 '
+! stdout '^example.net/m/p '
+cp go.mod go.mod.orig
+
+# Upgrading example.net/m/p without also upgrading example.net/m
+# causes the import of package example.net/m/p to be ambiguous.
+#
+# TODO(#27899): Should we automatically upgrade example.net/m to v0.2.0
+# to resolve the conflict?
+! go get example.net/m/p@v1.0.0
+stderr '^go: example.net/m/p: ambiguous import: found package example.net/m/p in multiple modules:\n\texample.net/m v0.1.0 \(.*[/\\]m1[/\\]p\)\n\texample.net/m/p v1.0.0 \(.*[/\\]p0\)\n\z'
+cmp go.mod go.mod.orig
+
+# Upgrading both modules simultaneously resolves the ambiguous upgrade.
+# Note that this command line mixes a module path (example.net/m)
+# and a package path (example.net/m/p) in the same command.
+go get example.net/m@v0.2.0 example.net/m/p@v1.0.0
+
+go list -m all
+stdout '^example.net/m v0.2.0 '
+stdout '^example.net/m/p v1.0.0 '
+
+-- go.mod --
+module example.net/importer
+
+go 1.16
+
+require (
+ example.net/m v0.1.0
+)
+
+replace (
+ example.net/m v0.1.0 => ./m1
+ example.net/m v0.2.0 => ./m2
+ example.net/m/p v1.0.0 => ./p0
+)
+-- importer.go --
+package importer
+import _ "example.net/m/p"
+-- m1/go.mod --
+module example.net/m
+
+go 1.16
+-- m1/p/p.go --
+package p
+-- m2/go.mod --
+module example.net/m
+
+go 1.16
+-- m2/README.txt --
+Package p has been moved to module …/m/p.
+Module …/m/p does not require any version of module …/m.
+
+-- p0/go.mod --
+module example.net/m/p
+
+go 1.16
+-- p0/p.go --
+package p
diff --git a/src/cmd/go/testdata/script/mod_get_ambiguous_pkg.txt b/src/cmd/go/testdata/script/mod_get_ambiguous_pkg.txt
new file mode 100644
index 0000000..1641196
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_ambiguous_pkg.txt
@@ -0,0 +1,87 @@
+# Both example.net/ambiguous v0.1.0 and example.net/ambiguous/pkg v0.1.0 exist.
+# 'go mod tidy' would arbitrarily choose the one with the longer path,
+# but 'go mod tidy' also arbitrarily chooses the latest version.
+
+cp go.mod go.mod.orig
+
+
+# From a clean slate, 'go get' currently does the same thing as 'go mod tidy':
+# it resolves the package from the module with the longest matching prefix.
+
+go get example.net/ambiguous/nested/pkg@v0.1.0
+go list -m all
+stdout '^example.net/ambiguous/nested v0.1.0$'
+! stdout '^example.net/ambiguous '
+
+
+# From an initial state that already depends on the shorter path,
+# the same 'go get' command should (somewhat arbitrarily) keep the
+# existing path, since it is a valid interpretation of the command.
+
+cp go.mod.orig go.mod
+go mod edit -require=example.net/ambiguous@v0.1.0
+
+go get example.net/ambiguous/nested/pkg@v0.1.0
+go list -m all
+stdout '^example.net/ambiguous v0.1.0$'
+! stdout '^example.net/ambiguous/nested '
+
+
+# The user should be able to make the command unambiguous by explicitly
+# upgrading the conflicting module...
+
+go get example.net/ambiguous@v0.2.0 example.net/ambiguous/nested/pkg@v0.1.0
+go list -m all
+stdout '^example.net/ambiguous/nested v0.1.0$'
+stdout '^example.net/ambiguous v0.2.0$'
+
+
+# ...or by explicitly NOT adding the conflicting module.
+
+cp go.mod.orig go.mod
+go mod edit -require=example.net/ambiguous@v0.1.0
+
+go get example.net/ambiguous/nested/pkg@v0.1.0 example.net/ambiguous/nested@none
+go list -m all
+! stdout '^example.net/ambiguous/nested '
+stdout '^example.net/ambiguous v0.1.0$'
+
+
+# The user should also be able to fix it by *downgrading* the conflicting module
+# away.
+
+cp go.mod.orig go.mod
+go mod edit -require=example.net/ambiguous@v0.1.0
+
+go get example.net/ambiguous@none example.net/ambiguous/nested/pkg@v0.1.0
+go list -m all
+stdout '^example.net/ambiguous/nested v0.1.0$'
+! stdout '^example.net/ambiguous '
+
+
+# In contrast, if we do the same thing tacking a wildcard pattern ('/...') on
+# the end of the package path, we get different behaviors depending on the
+# initial state, and no error. (This seems to contradict the “same meaning
+# regardless of the initial state” point above, but maybe that's ok?)
+
+cp go.mod.orig go.mod
+
+go get example.net/ambiguous/nested/pkg/...@v0.1.0
+go list -m all
+stdout '^example.net/ambiguous/nested v0.1.0$'
+! stdout '^example.net/ambiguous '
+
+
+cp go.mod.orig go.mod
+go mod edit -require=example.net/ambiguous@v0.1.0
+
+go get example.net/ambiguous/nested/pkg/...@v0.1.0
+go list -m all
+! stdout '^example.net/ambiguous/nested '
+stdout '^example.net/ambiguous v0.1.0$'
+
+
+-- go.mod --
+module test
+
+go 1.16
diff --git a/src/cmd/go/testdata/script/mod_get_boost.txt b/src/cmd/go/testdata/script/mod_get_boost.txt
new file mode 100644
index 0000000..105dc2e
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_boost.txt
@@ -0,0 +1,96 @@
+# If 'go get -u' finds an upgrade candidate that isn't viable,
+# but some other upgraded module's requirement moves past it
+# (for example, to a higher prerelease), then we should accept
+# the transitive upgrade instead of trying lower roots.
+
+go get -v -u . example.net/b@v0.1.0
+cmp go.mod go.mod.want
+
+-- go.mod --
+module example
+
+go 1.17
+
+require (
+ example.net/a v0.1.0
+ example.net/b v0.1.0
+ example.net/c v0.1.0
+)
+
+replace (
+ example.net/a v0.1.0 => ./a1
+ example.net/a v0.2.0-pre => ./a2p
+ example.net/b v0.1.0 => ./b
+ example.net/b v0.2.0 => ./b
+ example.net/c v0.1.0 => ./c1
+ example.net/c v0.2.0 => ./c2
+)
+-- go.mod.want --
+module example
+
+go 1.17
+
+require (
+ example.net/a v0.2.0-pre
+ example.net/b v0.1.0
+ example.net/c v0.2.0
+)
+
+replace (
+ example.net/a v0.1.0 => ./a1
+ example.net/a v0.2.0-pre => ./a2p
+ example.net/b v0.1.0 => ./b
+ example.net/b v0.2.0 => ./b
+ example.net/c v0.1.0 => ./c1
+ example.net/c v0.2.0 => ./c2
+)
+-- example.go --
+package example
+
+import (
+ _ "example.net/a"
+ _ "example.net/b"
+ _ "example.net/c"
+)
+-- a1/go.mod --
+module example.net/a
+
+go 1.17
+
+require example.net/b v0.2.0
+-- a1/a.go --
+package a
+
+import _ "example.net/b"
+-- a2p/go.mod --
+module example.net/a
+
+go 1.17
+-- a2p/a.go --
+package a
+-- b/go.mod --
+module example.net/b
+
+go 1.17
+-- b/b.go --
+package b
+-- c1/go.mod --
+module example.net/c
+
+go 1.17
+
+require example.net/a v0.1.0
+-- c1/c.go --
+package c
+
+import _ "example.net/a"
+-- c2/go.mod --
+module example.net/c
+
+go 1.17
+
+require example.net/a v0.2.0-pre
+-- c2/c.go --
+package c
+
+import _ "example.net/c"
diff --git a/src/cmd/go/testdata/script/mod_get_changes.txt b/src/cmd/go/testdata/script/mod_get_changes.txt
new file mode 100644
index 0000000..12a112b
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_changes.txt
@@ -0,0 +1,70 @@
+# When adding a requirement, 'go get' prints a message for the requirement
+# and for changed explicit dependencies. 'go get' does not print messages
+# for changed indirect dependencies.
+go list -m all
+! stdout golang.org/x/text
+go get rsc.io/quote@v1.5.2
+stderr '^go: added rsc.io/quote v1.5.2$'
+stderr '^go: upgraded rsc.io/sampler v1.0.0 => v1.3.0$'
+! stderr '^go get.*golang.org/x/text'
+go list -m all
+stdout golang.org/x/text
+cmp go.mod go.mod.upgrade
+
+# When removing a requirement, 'go get' prints a message for the requiremnent
+# and for changed explicit dependencies. 'go get' does not print messages
+# for changed indirect dependencies.
+go get rsc.io/sampler@none
+stderr '^go: downgraded rsc.io/quote v1.5.2 => v1.3.0$'
+stderr '^go: removed rsc.io/sampler v1.3.0$'
+! stderr '^go get.*golang.org/x/text'
+cmp go.mod go.mod.downgrade
+
+# When removing or downgrading a requirement, 'go get' also prints a message
+# for explicit dependencies removed as a consequence.
+cp go.mod.usequote go.mod
+go get rsc.io/quote@v1.5.1
+stderr '^go: downgraded rsc.io/quote v1.5.2 => v1.5.1$'
+stderr '^go: removed usequote v0.0.0$'
+
+-- go.mod --
+module m
+
+go 1.16
+
+require rsc.io/sampler v1.0.0
+-- go.sum --
+rsc.io/sampler v1.0.0 h1:SRJnjyQ07sAtq6G4RcfJEmz8JxqLyj3PoGXG2VhbDWo=
+rsc.io/sampler v1.0.0/go.mod h1:cqxpM3ZVz9VtirqxZPmrWzkQ+UkiNiGtkrN+B+i8kx8=
+-- go.mod.upgrade --
+module m
+
+go 1.16
+
+require (
+ rsc.io/quote v1.5.2 // indirect
+ rsc.io/sampler v1.3.0
+)
+-- go.mod.downgrade --
+module m
+
+go 1.16
+
+require (
+ golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c // indirect
+ rsc.io/quote v1.3.0 // indirect
+)
+-- go.mod.usequote --
+module m
+
+go 1.16
+
+require usequote v0.0.0
+
+replace usequote => ./usequote
+-- usequote/go.mod --
+module usequote
+
+go 1.16
+
+require rsc.io/quote v1.5.2
diff --git a/src/cmd/go/testdata/script/mod_get_commit.txt b/src/cmd/go/testdata/script/mod_get_commit.txt
new file mode 100644
index 0000000..76650f3
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_commit.txt
@@ -0,0 +1,50 @@
+env GO111MODULE=on
+[short] skip
+
+# @commit should resolve
+
+# golang.org/x/text/language@commit should resolve.
+# Because of -d, the compiler should not run.
+go get -x golang.org/x/text/language@14c0d48
+! stderr 'compile|cp|gccgo .*language\.a$'
+
+# go get should skip build with no Go files in root
+go get golang.org/x/text@14c0d48
+
+# dropping -d, we should see a build.
+[short] skip
+
+env GOCACHE=$WORK/gocache # Looking for compile commands, so need a clean cache.
+
+go build -x golang.org/x/text/language
+stderr 'compile|cp|gccgo .*language\.a$'
+
+go list -f '{{.Stale}}' golang.org/x/text/language
+stdout ^false
+
+# install after build should not run the compiler again.
+go install -x golang.org/x/text/language
+! stderr 'compile|cp|gccgo .*language\.a$'
+
+# we should see an error for unknown packages.
+! go get -x golang.org/x/text/foo@14c0d48
+stderr '^go: module golang.org/x/text@14c0d48 found \(v0.3.0\), but does not contain package golang.org/x/text/foo$'
+
+# get pseudo-version should record that version
+go get rsc.io/quote@v0.0.0-20180214005840-23179ee8a569
+grep 'rsc.io/quote v0.0.0-20180214005840-23179ee8a569' go.mod
+
+# but as commit should record as v1.5.1
+go get rsc.io/quote@23179ee8
+grep 'rsc.io/quote v1.5.1' go.mod
+
+# go mod edit -require does not interpret commits
+go mod edit -require rsc.io/quote@23179ee
+grep 'rsc.io/quote 23179ee' go.mod
+
+# but other commands fix them
+go list -m -mod=mod all
+grep 'rsc.io/quote v1.5.1' go.mod
+
+-- go.mod --
+module x
diff --git a/src/cmd/go/testdata/script/mod_get_deprecate_install.txt b/src/cmd/go/testdata/script/mod_get_deprecate_install.txt
new file mode 100644
index 0000000..03258f5
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_deprecate_install.txt
@@ -0,0 +1,42 @@
+[short] skip
+
+env GO111MODULE=on
+
+# 'go get' outside a module prints an error.
+! go get example.com/cmd/a
+stderr '^go: go.mod file not found in current directory or any parent directory.$'
+stderr '^\t''go get'' is no longer supported outside a module.$'
+
+cp go.mod.orig go.mod
+
+# 'go get' inside a module with a non-main package does not print a message.
+# This will stop building in the future, but it's the command we want to use.
+go get rsc.io/quote
+! stderr deprecated
+! stderr 'no longer installs'
+cp go.mod.orig go.mod
+
+# 'go get' inside a module with an executable does not print a message.
+# In 1.16 and 1.17, 'go get' did print a message in this case suggesting the
+# use of -d. In 1.18, -d is a no-op, and we'd like to begin discouraging
+# its use.
+go get example.com/cmd/a
+! stderr deprecated
+! stderr 'no longer installs'
+cp go.mod.orig go.mod
+
+# 'go get' should not print a warning for a main package inside the main module.
+# The intent is most likely to update the dependencies of that package.
+# 'go install' would be used otherwise.
+go get m
+! stderr .
+cp go.mod.orig go.mod
+
+-- go.mod.orig --
+module m
+
+go 1.17
+-- main.go --
+package main
+
+func main() {}
diff --git a/src/cmd/go/testdata/script/mod_get_deprecated.txt b/src/cmd/go/testdata/script/mod_get_deprecated.txt
new file mode 100644
index 0000000..ec7bcfd
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_deprecated.txt
@@ -0,0 +1,66 @@
+# 'go get pkg' should not show a deprecation message for an unrelated module.
+go get ./use/nothing
+! stderr 'module.*is deprecated'
+
+# 'go get pkg' should show a deprecation message for the module providing pkg.
+go get example.com/deprecated/a
+stderr '^go: module example.com/deprecated/a is deprecated: in example.com/deprecated/a@v1.9.0$'
+go get example.com/deprecated/a@v1.0.0
+stderr '^go: module example.com/deprecated/a is deprecated: in example.com/deprecated/a@v1.9.0$'
+
+# 'go get pkg' should show a deprecation message for a module providing
+# packages directly imported by pkg.
+go get ./use/a
+stderr '^go: module example.com/deprecated/a is deprecated: in example.com/deprecated/a@v1.9.0$'
+
+# 'go get pkg' may show a deprecation message for an indirectly required module
+# if it provides a package named on the command line.
+go get ./use/b
+! stderr 'module.*is deprecated'
+go get local/use
+! stderr 'module.*is deprecated'
+go get example.com/deprecated/b
+stderr '^go: module example.com/deprecated/b is deprecated: in example.com/deprecated/b@v1.9.0$'
+
+# 'go get pkg' does not show a deprecation message for a module providing a
+# directly imported package if the module is no longer deprecated in its
+# latest version, even if the module is deprecated in its current version.
+go get ./use/undeprecated
+! stderr 'module.*is deprecated'
+
+-- go.mod --
+module m
+
+go 1.17
+
+require (
+ example.com/deprecated/a v1.0.0
+ example.com/undeprecated v1.0.0
+ local v0.0.0
+)
+
+replace local v0.0.0 => ./local
+-- use/nothing/nothing.go --
+package nothing
+-- use/a/a.go --
+package a
+
+import _ "example.com/deprecated/a"
+-- use/b/b.go --
+package b
+
+import _ "local/use"
+-- use/undeprecated/undeprecated.go --
+package undeprecated
+
+import _ "example.com/undeprecated"
+-- local/go.mod --
+module local
+
+go 1.17
+
+require example.com/deprecated/b v1.0.0
+-- local/use/use.go --
+package use
+
+import _ "example.com/deprecated/b"
diff --git a/src/cmd/go/testdata/script/mod_get_direct.txt b/src/cmd/go/testdata/script/mod_get_direct.txt
new file mode 100644
index 0000000..02b10ab
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_direct.txt
@@ -0,0 +1,19 @@
+# Regression test for golang.org/issue/34092: with an empty module cache,
+# 'GOPROXY=direct go get golang.org/x/tools/gopls@master' did not correctly
+# resolve the pseudo-version for its dependency on golang.org/x/tools.
+
+[!net:cloud.google.com] skip
+[!git] skip
+
+env GO111MODULE=on
+env GOPROXY=direct
+env GOSUMDB=off
+
+go list -m cloud.google.com/go@main
+! stdout 'v0.0.0-'
+
+-- go.mod --
+module example.com
+
+go 1.14
+-- go.sum --
diff --git a/src/cmd/go/testdata/script/mod_get_downadd_indirect.txt b/src/cmd/go/testdata/script/mod_get_downadd_indirect.txt
new file mode 100644
index 0000000..0f5ba99
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_downadd_indirect.txt
@@ -0,0 +1,81 @@
+# This test illustrates a case where downgrading one module may upgrade another.
+# Compare to the downcross2 test case in cmd/go/internal/mvs/mvs_test.go.
+
+# The initial package import graph used in this test looks like:
+#
+# a ---- b ---- d
+#
+# The module dependency graph originally looks like:
+#
+# a ---- b.2 ---- d.2
+#
+# b.1 ---- c.1
+#
+# If we downgrade module d to version 1, we must downgrade b as well.
+# If that downgrade selects b version 1, we will add a new dependency on module c.
+
+cp go.mod go.mod.orig
+go mod tidy
+cmp go.mod.orig go.mod
+
+go get example.com/d@v0.1.0
+go list -m all
+stdout '^example.com/b v0.1.0 '
+stdout '^example.com/c v0.1.0 '
+stdout '^example.com/d v0.1.0 '
+
+-- go.mod --
+module example.com/a
+
+go 1.15
+
+require example.com/b v0.2.0
+
+replace (
+ example.com/b v0.1.0 => ./b1
+ example.com/b v0.2.0 => ./b2
+ example.com/c v0.1.0 => ./c
+ example.com/d v0.1.0 => ./d
+ example.com/d v0.2.0 => ./d
+)
+-- a.go --
+package a
+
+import _ "example.com/b"
+
+-- b1/go.mod --
+module example.com/b
+
+go 1.15
+
+require example.com/c v0.1.0
+-- b1/b.go --
+package b
+
+import _ "example.com/c"
+
+-- b2/go.mod --
+module example.com/b
+
+go 1.15
+
+require example.com/d v0.2.0
+-- b2/b.go --
+package b
+
+import _ "example.com/d"
+
+-- c/go.mod --
+module example.com/c
+
+go 1.15
+
+-- c/c.go --
+package c
+
+-- d/go.mod --
+module example.com/d
+
+go 1.15
+-- d/d.go --
+package d
diff --git a/src/cmd/go/testdata/script/mod_get_downgrade.txt b/src/cmd/go/testdata/script/mod_get_downgrade.txt
new file mode 100644
index 0000000..2eed56d
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_downgrade.txt
@@ -0,0 +1,56 @@
+env GO111MODULE=on
+[short] skip
+
+# downgrade sampler should downgrade quote
+cp go.mod.orig go.mod
+go get rsc.io/sampler@v1.0.0
+go list -m all
+stdout 'rsc.io/quote v1.4.0'
+stdout 'rsc.io/sampler v1.0.0'
+
+# downgrade sampler away should downgrade quote further
+go get rsc.io/sampler@none
+go list -m all
+stdout 'rsc.io/quote v1.3.0'
+
+# downgrade should report inconsistencies and not change go.mod
+go get rsc.io/quote@v1.5.1
+go list -m all
+stdout 'rsc.io/quote v1.5.1'
+stdout 'rsc.io/sampler v1.3.0'
+
+! go get rsc.io/sampler@v1.0.0 rsc.io/quote@v1.5.2 golang.org/x/text@none
+! stderr add|remove|upgrad|downgrad
+stderr '^go: rsc.io/quote@v1.5.2 requires rsc.io/sampler@v1.3.0, not rsc.io/sampler@v1.0.0$'
+
+go list -m all
+stdout 'rsc.io/quote v1.5.1'
+stdout 'rsc.io/sampler v1.3.0'
+
+# go get -u args should limit upgrades
+cp go.mod.empty go.mod
+go get -u rsc.io/quote@v1.4.0 rsc.io/sampler@v1.0.0
+go list -m all
+stdout 'rsc.io/quote v1.4.0'
+stdout 'rsc.io/sampler v1.0.0'
+! stdout golang.org/x/text
+
+# downgrading away quote should also downgrade away latemigrate/v2,
+# since there are no older versions. v2.0.0 is incompatible.
+cp go.mod.orig go.mod
+go list -m -versions example.com/latemigrate/v2
+stdout v2.0.0 # proxy may serve incompatible versions
+go get rsc.io/quote@none
+go list -m all
+! stdout 'example.com/latemigrate/v2'
+
+-- go.mod.orig --
+module x
+require (
+ rsc.io/quote v1.5.1
+ example.com/latemigrate/v2 v2.0.1
+)
+-- go.mod.empty --
+module x
+-- x.go --
+package x
diff --git a/src/cmd/go/testdata/script/mod_get_downgrade_missing.txt b/src/cmd/go/testdata/script/mod_get_downgrade_missing.txt
new file mode 100644
index 0000000..4486a67
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_downgrade_missing.txt
@@ -0,0 +1,43 @@
+cp go.mod go.mod.orig
+
+# getting a specific version of a module along with a pattern
+# not yet present in that module should report the version mismatch
+# rather than a "matched no packages" warning.
+
+! go get example.net/pkgadded@v1.1.0 example.net/pkgadded/subpkg/...
+stderr '^go: example.net/pkgadded@v1.1.0 conflicts with example.net/pkgadded/subpkg/...@upgrade \(v1.2.0\)$'
+! stderr 'matched no packages'
+cmp go.mod.orig go.mod
+
+
+# A wildcard pattern should match the pattern with that path.
+
+go get example.net/pkgadded/...@v1.0.0
+go list -m all
+stdout '^example.net/pkgadded v1.0.0'
+cp go.mod.orig go.mod
+
+
+# If we need to resolve a transitive dependency of a package,
+# and another argument constrains away the version that provides that
+# package, then 'go get' should fail with a useful error message.
+
+! go get example.net/pkgadded@v1.0.0 .
+stderr '^go: example.com/m imports\n\texample.net/pkgadded/subpkg: cannot find module providing package example.net/pkgadded/subpkg$'
+! stderr 'example.net/pkgadded v1\.2\.0'
+cmp go.mod.orig go.mod
+
+go get example.net/pkgadded@v1.0.0
+! go list -deps -mod=readonly .
+stderr '^m.go:3:8: cannot find module providing package example\.net/pkgadded/subpkg: '
+
+-- go.mod --
+module example.com/m
+
+go 1.16
+
+require example.net/pkgadded v1.2.0
+-- m.go --
+package m
+
+import _ "example.net/pkgadded/subpkg"
diff --git a/src/cmd/go/testdata/script/mod_get_downup_artifact.txt b/src/cmd/go/testdata/script/mod_get_downup_artifact.txt
new file mode 100644
index 0000000..111a54f
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_downup_artifact.txt
@@ -0,0 +1,159 @@
+# This test illustrates a case where an upgrade–downgrade–upgrade cycle can
+# result in upgrades of otherwise-irrelevant dependencies.
+#
+# This case has no corresponding test in the mvs package, because it is an
+# artifact that results from the composition of *multiple* MVS operations.
+
+# The initial package import graph used in the test looks like:
+#
+# m ---- a
+# | |
+# +----- b
+# | |
+# +----- c
+# |
+# +----- d
+#
+# b version 2 adds its own import of package d.
+#
+# The module dependency graph initially looks like:
+#
+# m ---- a.1
+# | |
+# +----- b.1
+# | |
+# +----- c.1
+# |
+# +----- d.1
+#
+# b.2 ---- c.2
+# |
+# +------ d.2
+# |
+# +------ e.1
+#
+# If we upgrade module b to version 2, we will upgrade c and d and add a new
+# dependency on e. If b version 2 is disallowed because of any of those
+# dependencies, the other dependencies should not be upgraded as a side-effect.
+
+cp go.mod go.mod.orig
+go mod tidy
+cmp go.mod go.mod.orig
+
+go list -m all
+stdout '^example.com/a v0.1.0 '
+stdout '^example.com/b v0.1.0 '
+stdout '^example.com/c v0.1.0 '
+stdout '^example.com/d v0.1.0 '
+! stdout '^example.com/e '
+
+# b is imported by a, so the -u flag would normally upgrade it to v0.2.0.
+# However, that would conflict with the explicit c@v0.1.0 constraint,
+# so b must remain at v0.1.0.
+#
+# If we're not careful, we might temporarily add b@v0.2.0 and pull in its
+# upgrades of module d and addition of module e, which are not relevant to
+# b@v0.1.0 and should not be added to the main module's dependencies.
+
+go get -u example.com/a@latest example.com/c@v0.1.0
+
+go list -m all
+stdout '^example.com/a v0.1.0 '
+stdout '^example.com/b v0.1.0 '
+stdout '^example.com/c v0.1.0 '
+stdout '^example.com/d v0.1.0 '
+! stdout '^example.com/e '
+
+-- go.mod --
+module example.com/m
+
+go 1.16
+
+require (
+ example.com/a v0.1.0
+ example.com/b v0.1.0
+ example.com/c v0.1.0
+ example.com/d v0.1.0
+)
+
+replace (
+ example.com/a v0.1.0 => ./a1
+ example.com/b v0.1.0 => ./b1
+ example.com/b v0.2.0 => ./b2
+ example.com/c v0.1.0 => ./c
+ example.com/c v0.2.0 => ./c
+ example.com/d v0.1.0 => ./d
+ example.com/d v0.2.0 => ./d
+ example.com/e v0.1.0 => ./e
+)
+-- m.go --
+package m
+
+import (
+ _ "example.com/a"
+ _ "example.com/b"
+ _ "example.com/c"
+ _ "example.com/d"
+)
+
+-- a1/go.mod --
+module example.com/a
+
+go 1.16
+
+require example.com/b v0.1.0
+-- a1/a.go --
+package a
+
+import _ "example.com/b"
+
+-- b1/go.mod --
+module example.com/b
+
+go 1.16
+
+require example.com/c v0.1.0
+-- b1/b.go --
+package b
+
+import _ "example.com/c"
+
+-- b2/go.mod --
+module example.com/b
+
+go 1.16
+
+require (
+ example.com/c v0.2.0
+ example.com/d v0.2.0
+ example.com/e v0.1.0
+)
+-- b2/b.go --
+package b
+
+import (
+ "example.com/c"
+ "example.com/d"
+ "example.com/e"
+)
+
+-- c/go.mod --
+module example.com/c
+
+go 1.16
+-- c/c.go --
+package c
+
+-- d/go.mod --
+module example.com/d
+
+go 1.16
+-- d/d.go --
+package d
+
+-- e/go.mod --
+module example.com/e
+
+go 1.16
+-- e/e.go --
+package e
diff --git a/src/cmd/go/testdata/script/mod_get_downup_indirect.txt b/src/cmd/go/testdata/script/mod_get_downup_indirect.txt
new file mode 100644
index 0000000..432e626
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_downup_indirect.txt
@@ -0,0 +1,149 @@
+# This test illustrates a case where downgrading one module may upgrade another.
+# Compare to the downcross1 test case in cmd/go/internal/mvs/mvs_test.go.
+
+# The package import graph used in this test looks like:
+#
+# a ---- b
+# \ \
+# \ \
+# ----- c ---- d
+#
+# The module dependency graph originally looks like:
+#
+# a ---- b.2
+# \ \
+# \ \
+# ----- c.1 ---- d.2
+#
+# b.1 ---- c.2
+#
+# If we downgrade module d to version 1, we must downgrade b as well.
+# If that downgrade selects b version 1, we will upgrade module c to version 2.
+
+cp go.mod go.mod.orig
+go mod tidy
+cmp go.mod.orig go.mod
+
+# Downgrading d to version 1 downgrades b, which upgrades c.
+go get example.com/d@v0.1.0
+go list -m all
+stdout '^example.com/b v0.1.0 '
+stdout '^example.com/c v0.2.0 '
+stdout '^example.com/d v0.1.0 '
+cmp go.mod go.mod.down1
+
+# Restoring c to version 1 upgrades d to meet c's requirements.
+go get example.com/c@v0.1.0
+go list -m all
+! stdout '^example.com/b '
+stdout '^example.com/c v0.1.0 '
+stdout '^example.com/d v0.2.0 '
+cmp go.mod go.mod.down2
+
+# If a user explicitly requests the incompatible versions together,
+# 'go get' should explain why they are not compatible.
+! go get example.com/c@v0.1.0 example.com/d@v0.1.0
+stderr '^go: example\.com/c@v0\.1\.0 requires example\.com/d@v0\.2\.0, not example\.com/d@v0\.1\.0'
+
+-- go.mod --
+module example.com/a
+
+go 1.15
+
+require (
+ example.com/b v0.2.0
+ example.com/c v0.1.0
+)
+
+replace (
+ example.com/b v0.1.0 => ./b1
+ example.com/b v0.2.0 => ./b2
+ example.com/c v0.1.0 => ./c1
+ example.com/c v0.2.0 => ./c2
+ example.com/d v0.1.0 => ./d
+ example.com/d v0.2.0 => ./d
+)
+-- go.mod.down1 --
+module example.com/a
+
+go 1.15
+
+require (
+ example.com/b v0.1.0
+ example.com/c v0.2.0
+ example.com/d v0.1.0 // indirect
+)
+
+replace (
+ example.com/b v0.1.0 => ./b1
+ example.com/b v0.2.0 => ./b2
+ example.com/c v0.1.0 => ./c1
+ example.com/c v0.2.0 => ./c2
+ example.com/d v0.1.0 => ./d
+ example.com/d v0.2.0 => ./d
+)
+-- go.mod.down2 --
+module example.com/a
+
+go 1.15
+
+require example.com/c v0.1.0
+
+replace (
+ example.com/b v0.1.0 => ./b1
+ example.com/b v0.2.0 => ./b2
+ example.com/c v0.1.0 => ./c1
+ example.com/c v0.2.0 => ./c2
+ example.com/d v0.1.0 => ./d
+ example.com/d v0.2.0 => ./d
+)
+-- a.go --
+package a
+
+import (
+ _ "example.com/b"
+ _ "example.com/c"
+)
+
+-- b1/go.mod --
+module example.com/b
+
+go 1.15
+
+require example.com/c v0.2.0
+-- b1/b.go --
+package b
+
+import _ "example.com/c"
+
+-- b2/go.mod --
+module example.com/b
+
+go 1.15
+
+require example.com/c v0.1.0
+-- b2/b.go --
+package b
+
+import _ "example.com/c"
+
+-- c1/go.mod --
+module example.com/c
+
+go 1.15
+
+require example.com/d v0.2.0
+-- c1/c.go --
+package c
+
+-- c2/go.mod --
+module example.com/c
+
+go 1.15
+-- c2/c.go --
+package c
+
+-- d/go.mod --
+module example.com/d
+
+go 1.15
diff --git a/src/cmd/go/testdata/script/mod_get_downup_indirect_pruned.txt b/src/cmd/go/testdata/script/mod_get_downup_indirect_pruned.txt
new file mode 100644
index 0000000..cac6b96
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_downup_indirect_pruned.txt
@@ -0,0 +1,154 @@
+# This test illustrates a case where downgrading one module may upgrade another.
+# This is the same as mod_get_downup_indirect, but using modules
+# with graph pruning enabled (go ≥ 1.17).
+# Compare to the downcross1 test case in cmd/go/internal/mvs/mvs_test.go.
+
+# The package import graph used in this test looks like:
+#
+# a ---- b
+# \ \
+# \ \
+# ----- c ---- d
+#
+# The module dependency graph originally looks like:
+#
+# a ---- b.2
+# \ \
+# \ \
+# ----- c.1 ---- d.2
+#
+# b.1 ---- c.2
+#
+# If we downgrade module d to version 1, we must downgrade b as well.
+# If that downgrade selects b version 1, we will upgrade module c to version 2.
+
+cp go.mod go.mod.orig
+go mod tidy
+cmp go.mod.orig go.mod
+
+# Downgrading d to version 1 downgrades b, which upgrades c.
+go get -v example.com/d@v0.1.0
+go list -m all
+stdout '^example.com/b v0.1.0 '
+stdout '^example.com/c v0.2.0 '
+stdout '^example.com/d v0.1.0 '
+cmp go.mod go.mod.down1
+
+# Restoring c to version 1 upgrades d to meet c's requirements.
+go get example.com/c@v0.1.0
+go list -m all
+! stdout '^example.com/b '
+stdout '^example.com/c v0.1.0 '
+stdout '^example.com/d v0.2.0 '
+cmp go.mod go.mod.down2
+
+# If a user explicitly requests the incompatible versions together,
+# 'go get' should explain why they are not compatible.
+! go get example.com/c@v0.1.0 example.com/d@v0.1.0
+stderr '^go: example\.com/c@v0\.1\.0 requires example\.com/d@v0\.2\.0, not example\.com/d@v0\.1\.0'
+
+-- go.mod --
+module example.com/a
+
+go 1.17
+
+require (
+ example.com/b v0.2.0
+ example.com/c v0.1.0
+)
+
+replace (
+ example.com/b v0.1.0 => ./b1
+ example.com/b v0.2.0 => ./b2
+ example.com/c v0.1.0 => ./c1
+ example.com/c v0.2.0 => ./c2
+ example.com/d v0.1.0 => ./d
+ example.com/d v0.2.0 => ./d
+)
+-- go.mod.down1 --
+module example.com/a
+
+go 1.17
+
+require (
+ example.com/b v0.1.0
+ example.com/c v0.2.0
+)
+
+require example.com/d v0.1.0 // indirect
+
+replace (
+ example.com/b v0.1.0 => ./b1
+ example.com/b v0.2.0 => ./b2
+ example.com/c v0.1.0 => ./c1
+ example.com/c v0.2.0 => ./c2
+ example.com/d v0.1.0 => ./d
+ example.com/d v0.2.0 => ./d
+)
+-- go.mod.down2 --
+module example.com/a
+
+go 1.17
+
+require example.com/c v0.1.0
+
+require example.com/d v0.2.0 // indirect
+
+replace (
+ example.com/b v0.1.0 => ./b1
+ example.com/b v0.2.0 => ./b2
+ example.com/c v0.1.0 => ./c1
+ example.com/c v0.2.0 => ./c2
+ example.com/d v0.1.0 => ./d
+ example.com/d v0.2.0 => ./d
+)
+-- a.go --
+package a
+
+import (
+ _ "example.com/b"
+ _ "example.com/c"
+)
+
+-- b1/go.mod --
+module example.com/b
+
+go 1.17
+
+require example.com/c v0.2.0
+-- b1/b.go --
+package b
+
+import _ "example.com/c"
+
+-- b2/go.mod --
+module example.com/b
+
+go 1.17
+
+require example.com/c v0.1.0
+-- b2/b.go --
+package b
+
+import _ "example.com/c"
+
+-- c1/go.mod --
+module example.com/c
+
+go 1.17
+
+require example.com/d v0.2.0
+-- c1/c.go --
+package c
+
+-- c2/go.mod --
+module example.com/c
+
+go 1.17
+-- c2/c.go --
+package c
+
+-- d/go.mod --
+module example.com/d
+
+go 1.17
diff --git a/src/cmd/go/testdata/script/mod_get_downup_pseudo_artifact.txt b/src/cmd/go/testdata/script/mod_get_downup_pseudo_artifact.txt
new file mode 100644
index 0000000..b678a17
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_downup_pseudo_artifact.txt
@@ -0,0 +1,129 @@
+# This test illustrates a case where an upgrade–downgrade–upgrade cycle could
+# add extraneous dependencies due to another module depending on an
+# otherwise-unlisted version (such as a pseudo-version).
+#
+# This case corresponds to the "downhiddenartifact" test in the mvs package.
+
+# The initial package import graph used in the test looks like:
+#
+# a --- b
+# \ \
+# \ \
+# c --- d
+#
+# The module dependency graph initially looks like:
+#
+# a --- b.3
+# \ \
+# \ \
+# c.2 --- d.2
+#
+# c.1 --- b.2 (pseudo)
+#
+# b.1 --- e.1
+
+cp go.mod go.mod.orig
+go mod tidy
+cmp go.mod.orig go.mod
+
+# When we downgrade d.2 to d.1, no dependency on e should be added
+# because nothing else in the module or import graph requires it.
+go get example.net/d@v0.1.0
+
+go list -m all
+stdout '^example.net/b v0.2.1-0.20210219000000-000000000000 '
+stdout '^example.net/c v0.1.0 '
+stdout '^example.net/d v0.1.0 '
+! stdout '^example.net/e '
+
+-- go.mod --
+module example.net/a
+
+go 1.16
+
+require (
+ example.net/b v0.3.0
+ example.net/c v0.2.0
+)
+
+replace (
+ example.net/b v0.1.0 => ./b1
+ example.net/b v0.2.1-0.20210219000000-000000000000 => ./b2
+ example.net/b v0.3.0 => ./b3
+ example.net/c v0.1.0 => ./c1
+ example.net/c v0.2.0 => ./c2
+ example.net/d v0.1.0 => ./d
+ example.net/d v0.2.0 => ./d
+ example.net/e v0.1.0 => ./e
+)
+-- a.go --
+package a
+
+import (
+ _ "example.net/b"
+ _ "example.net/c"
+)
+
+-- b1/go.mod --
+module example.net/b
+
+go 1.16
+
+require example.net/e v0.1.0
+-- b1/b.go --
+package b
+
+import _ "example.net/e"
+
+-- b2/go.mod --
+module example.net/b
+
+go 1.16
+-- b2/b.go --
+package b
+
+-- b3/go.mod --
+module example.net/b
+
+go 1.16
+
+require example.net/d v0.2.0
+-- b3/b.go --
+package b
+
+import _ "example.net/d"
+-- c1/go.mod --
+module example.net/c
+
+go 1.16
+
+require example.net/b v0.2.1-0.20210219000000-000000000000
+-- c1/c.go --
+package c
+
+import _ "example.net/b"
+
+-- c2/go.mod --
+module example.net/c
+
+go 1.16
+
+require example.net/d v0.2.0
+-- c2/c.go --
+package c
+
+import _ "example.net/d"
+
+-- d/go.mod --
+module example.net/d
+
+go 1.16
+-- d/d.go --
+package d
+
+-- e/go.mod --
+module example.net/e
+
+go 1.16
+-- e/e.go --
+package e
diff --git a/src/cmd/go/testdata/script/mod_get_errors.txt b/src/cmd/go/testdata/script/mod_get_errors.txt
new file mode 100644
index 0000000..981d6f0
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_errors.txt
@@ -0,0 +1,57 @@
+cp go.mod go.mod.orig
+
+
+# 'go get' should fail, without updating go.mod, if the transitive dependencies
+# of the requested package (by default, the package in the current directory)
+# cannot be resolved.
+
+! go get
+stderr '^go: example.com/m imports\n\texample.com/badimport imports\n\texample.net/oops: cannot find module providing package example.net/oops$'
+cmp go.mod.orig go.mod
+
+cd importsyntax
+
+
+# A syntax error in a dependency prevents the compiler from needing that
+# dependency's imports, so 'go get' should not report an error when those
+# imports cannot be resolved: it has all of the dependencies that the compiler
+# needs, and the user did not request to run the compiler.
+
+go get
+cmp ../go.mod.syntax-d ../go.mod
+
+
+-- go.mod --
+module example.com/m
+
+go 1.16
+
+replace example.com/badimport v0.1.0 => ./badimport
+-- go.mod.syntax-d --
+module example.com/m
+
+go 1.16
+
+replace example.com/badimport v0.1.0 => ./badimport
+
+require example.com/badimport v0.1.0
+-- m.go --
+package m
+
+import _ "example.com/badimport"
+-- importsyntax/importsyntax.go --
+package importsyntax
+
+import _ "example.com/badimport/syntaxerror"
+-- badimport/go.mod --
+module example.com/badimport
+
+go 1.16
+-- badimport/badimport.go --
+package badimport
+
+import "example.net/oops"
+-- badimport/syntaxerror/syntaxerror.go --
+pack-age syntaxerror // sic
+
+import "example.net/oops"
diff --git a/src/cmd/go/testdata/script/mod_get_exec_toolchain.txt b/src/cmd/go/testdata/script/mod_get_exec_toolchain.txt
new file mode 100644
index 0000000..497fe36
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_exec_toolchain.txt
@@ -0,0 +1,145 @@
+env TESTGO_VERSION=go1.21
+env TESTGO_VERSION_SWITCH=switch
+
+# GOTOOLCHAIN=auto should run the newer toolchain
+env GOTOOLCHAIN=auto
+cp go.mod.new go.mod
+go get rsc.io/needgo121 rsc.io/needgo122 rsc.io/needgo123 rsc.io/needall
+stderr '^go: rsc.io/needall@v0.0.1 requires go >= 1.23; switching to go1.23.9$'
+! stderr '\(running'
+stderr '^go: added rsc.io/needall v0.0.1'
+grep 'go 1.23' go.mod
+grep 'toolchain go1.23.9' go.mod
+
+# GOTOOLCHAIN=min+auto should run the newer toolchain
+env GOTOOLCHAIN=go1.21+auto
+cp go.mod.new go.mod
+go get rsc.io/needgo121 rsc.io/needgo122 rsc.io/needgo123 rsc.io/needall
+stderr '^go: rsc.io/needall@v0.0.1 requires go >= 1.23; switching to go1.23.9$'
+! stderr '\(running'
+stderr '^go: added rsc.io/needall v0.0.1'
+grep 'go 1.23' go.mod
+grep 'toolchain go1.23.9' go.mod
+
+# GOTOOLCHAIN=go1.21 should NOT run the newer toolchain
+env GOTOOLCHAIN=go1.21
+cp go.mod.new go.mod
+! go get rsc.io/needgo121 rsc.io/needgo122 rsc.io/needgo123 rsc.io/needall
+! stderr switching
+stderr 'rsc.io/needgo122@v0.0.1 requires go >= 1.22'
+stderr 'rsc.io/needgo123@v0.0.1 requires go >= 1.23'
+stderr 'rsc.io/needall@v0.0.1 requires go >= 1.23'
+stderr 'requires go >= 1.23'
+! stderr 'requires go >= 1.21' # that's us!
+cmp go.mod go.mod.new
+
+# GOTOOLCHAIN=local should NOT run the newer toolchain
+env GOTOOLCHAIN=local
+cp go.mod.new go.mod
+! go get rsc.io/needgo121 rsc.io/needgo122 rsc.io/needgo123 rsc.io/needall
+! stderr switching
+stderr 'rsc.io/needgo122@v0.0.1 requires go >= 1.22'
+stderr 'rsc.io/needgo123@v0.0.1 requires go >= 1.23'
+stderr 'rsc.io/needall@v0.0.1 requires go >= 1.23'
+stderr 'requires go >= 1.23'
+! stderr 'requires go >= 1.21' # that's us!
+cmp go.mod go.mod.new
+
+# go get go@1.22 should resolve to the latest 1.22
+env GOTOOLCHAIN=local
+cp go.mod.new go.mod
+! go get go@1.22
+stderr '^go: updating go.mod requires go >= 1.22.9 \(running go 1.21; GOTOOLCHAIN=local\)'
+
+env GOTOOLCHAIN=auto
+cp go.mod.new go.mod
+go get go@1.22
+stderr '^go: updating go.mod requires go >= 1.22.9; switching to go1.22.9$'
+
+# go get go@1.22rc1 should use 1.22rc1 exactly, not a later release.
+env GOTOOLCHAIN=local
+cp go.mod.new go.mod
+! go get go@1.22rc1
+stderr '^go: updating go.mod requires go >= 1.22rc1 \(running go 1.21; GOTOOLCHAIN=local\)'
+
+env GOTOOLCHAIN=auto
+cp go.mod.new go.mod
+go get go@1.22rc1
+stderr '^go: updating go.mod requires go >= 1.22rc1; switching to go1.22.9$'
+stderr '^go: upgraded go 1.1 => 1.22rc1$'
+stderr '^go: added toolchain go1.22.9$'
+
+# go get go@1.22.1 should use 1.22.1 exactly, not a later release.
+env GOTOOLCHAIN=local
+cp go.mod.new go.mod
+! go get go@1.22.1
+stderr '^go: updating go.mod requires go >= 1.22.1 \(running go 1.21; GOTOOLCHAIN=local\)'
+
+env GOTOOLCHAIN=auto
+cp go.mod.new go.mod
+go get go@1.22.1
+stderr '^go: updating go.mod requires go >= 1.22.1; switching to go1.22.9$'
+stderr '^go: upgraded go 1.1 => 1.22.1$'
+stderr '^go: added toolchain go1.22.9$'
+
+# go get needgo122 (says 'go 1.22') should use 1.22.0, the earliest release we have available
+# (ignoring prereleases).
+env GOTOOLCHAIN=local
+cp go.mod.new go.mod
+! go get rsc.io/needgo122
+stderr '^go: rsc.io/needgo122@v0.0.1 requires go >= 1.22 \(running go 1.21; GOTOOLCHAIN=local\)'
+
+env GOTOOLCHAIN=auto
+cp go.mod.new go.mod
+go get rsc.io/needgo122
+stderr '^go: upgraded go 1.1 => 1.22$'
+stderr '^go: rsc.io/needgo122@v0.0.1 requires go >= 1.22; switching to go1.22.9$'
+stderr '^go: added toolchain go1.22.9$'
+
+# go get needgo1223 (says 'go 1.22.3') should use go 1.22.3
+env GOTOOLCHAIN=local
+cp go.mod.new go.mod
+! go get rsc.io/needgo1223
+stderr '^go: rsc.io/needgo1223@v0.0.1 requires go >= 1.22.3 \(running go 1.21; GOTOOLCHAIN=local\)'
+
+env GOTOOLCHAIN=auto
+cp go.mod.new go.mod
+go get rsc.io/needgo1223
+stderr '^go: upgraded go 1.1 => 1.22.3$'
+stderr '^go: rsc.io/needgo1223@v0.0.1 requires go >= 1.22.3; switching to go1.22.9$'
+stderr '^go: added toolchain go1.22.9$'
+
+# go get needgo124 (says 'go 1.24') should use go 1.24rc1, the only version available
+env GOTOOLCHAIN=local
+cp go.mod.new go.mod
+! go get rsc.io/needgo124
+stderr '^go: rsc.io/needgo124@v0.0.1 requires go >= 1.24 \(running go 1.21; GOTOOLCHAIN=local\)'
+
+env GOTOOLCHAIN=auto
+cp go.mod.new go.mod
+go get rsc.io/needgo124
+stderr '^go: rsc.io/needgo124@v0.0.1 requires go >= 1.24; switching to go1.24rc1$'
+stderr '^go: upgraded go 1.1 => 1.24$'
+stderr '^go: added toolchain go1.24rc1$'
+
+# The -C flag should not happen more than once due to switching.
+mkdir dir dir/dir
+cp go.mod.new go.mod
+cp go.mod.new dir/go.mod
+cp go.mod.new dir/dir/go.mod
+cp p.go dir/p.go
+cp p.go dir/dir/p.go
+go get -C dir rsc.io/needgo124
+stderr '^go: rsc.io/needgo124@v0.0.1 requires go >= 1.24; switching to go1.24rc1$'
+stderr '^go: upgraded go 1.1 => 1.24$'
+stderr '^go: added toolchain go1.24rc1$'
+cmp go.mod.new go.mod
+cmp go.mod.new dir/dir/go.mod
+grep 'go 1.24$' dir/go.mod
+
+-- go.mod.new --
+module m
+go 1.1
+
+-- p.go --
+package p
diff --git a/src/cmd/go/testdata/script/mod_get_extra.txt b/src/cmd/go/testdata/script/mod_get_extra.txt
new file mode 100644
index 0000000..083e036
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_extra.txt
@@ -0,0 +1,69 @@
+cp go.mod go.mod.orig
+
+# The -u flag should not (even temporarily) upgrade modules whose versions are
+# determined by explicit queries to any version other than the explicit one.
+# Otherwise, 'go get -u' could introduce spurious dependencies.
+
+go get -u example.net/a@v0.1.0 example.net/b@v0.1.0
+go list -m all
+stdout '^example.net/a v0.1.0 '
+stdout '^example.net/b v0.1.0 '
+! stdout '^example.net/c '
+
+
+# TODO(bcmills): This property does not yet hold for modules added for
+# missing packages when the newly-added module matches a wildcard.
+
+cp go.mod.orig go.mod
+
+go get -u example.net/a@v0.1.0 example.net/b/...@v0.1.0
+go list -m all
+stdout '^example.net/a v0.1.0 '
+stdout '^example.net/b v0.1.0 '
+stdout '^example.net/c ' # BUG, but a minor and rare one
+
+
+-- go.mod --
+module example
+
+go 1.15
+
+replace (
+ example.net/a v0.1.0 => ./a1
+ example.net/b v0.1.0 => ./b1
+ example.net/b v0.2.0 => ./b2
+ example.net/c v0.1.0 => ./c1
+ example.net/c v0.2.0 => ./c1
+)
+
+-- a1/go.mod --
+module example.net/a
+
+go 1.15
+
+// example.net/a needs a dependency on example.net/b, but lacks a requirement
+// on it (perhaps due to a missed file in a VCS commit).
+-- a1/a.go --
+package a
+import _ "example.net/b"
+
+-- b1/go.mod --
+module example.net/b
+
+go 1.15
+-- b1/b.go --
+package b
+
+-- b2/go.mod --
+module example.net/b
+
+go 1.15
+
+require example.net/c v0.1.0
+-- b2/b.go --
+package b
+
+-- c1/go.mod --
+module example.net/c
+
+go 1.15
diff --git a/src/cmd/go/testdata/script/mod_get_fallback.txt b/src/cmd/go/testdata/script/mod_get_fallback.txt
new file mode 100644
index 0000000..a5119b6
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_fallback.txt
@@ -0,0 +1,16 @@
+env GO111MODULE=on
+
+[!net:golang.org] skip
+[!net:proxy.golang.org] skip
+
+env GOPROXY=https://proxy.golang.org,direct
+env GOSUMDB=off
+
+go get -x -v golang.org/x/tools/cmd/goimports
+stderr '# get https://proxy.golang.org/golang.org/x/tools/@v/list'
+! stderr '# get https://golang.org'
+
+-- go.mod --
+module m
+
+go 1.18
diff --git a/src/cmd/go/testdata/script/mod_get_fossil.txt b/src/cmd/go/testdata/script/mod_get_fossil.txt
new file mode 100644
index 0000000..830e0de
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_fossil.txt
@@ -0,0 +1,28 @@
+[short] skip
+[!exec:fossil] skip
+
+# Regression test for 'go get' to ensure repositories
+# provided by fossil v2.12 and up are able to be fetched
+# and parsed correctly.
+# Verifies golang.org/issue/42323.
+
+
+env GO111MODULE=on
+env GOPROXY=direct
+env GOSUMDB=off
+
+# 'go get' for the fossil repo will fail if fossil
+# is unable to determine your fossil user. Easiest
+# way to set it for use by 'go get' is specifying
+# a any non-empty $USER; the value doesn't otherwise matter.
+env USER=fossiluser
+env FOSSIL_HOME=$WORK/home
+
+# Attempt to get the latest version of a fossil repo.
+go get vcs-test.golang.org/fossil/hello.fossil
+! stderr 'unexpected response from fossil info'
+grep 'vcs-test.golang.org/fossil/hello.fossil' go.mod
+
+-- go.mod --
+module x
+-- $WORK/home/.fossil --
diff --git a/src/cmd/go/testdata/script/mod_get_future.txt b/src/cmd/go/testdata/script/mod_get_future.txt
new file mode 100644
index 0000000..3f1c777
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_future.txt
@@ -0,0 +1,13 @@
+env TESTGO_VERSION=go1.21
+env GOTOOLCHAIN=local
+! go mod download rsc.io/future@v1.0.0
+stderr '^go: rsc.io/future@v1.0.0 requires go >= 1.999 \(running go 1.21; GOTOOLCHAIN=local\)$'
+
+-- go.mod --
+module m
+go 1.21
+
+-- x.go --
+package p
+
+import "rsc.io/future/foo"
diff --git a/src/cmd/go/testdata/script/mod_get_go_file.txt b/src/cmd/go/testdata/script/mod_get_go_file.txt
new file mode 100644
index 0000000..c81e491
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_go_file.txt
@@ -0,0 +1,73 @@
+# Tests Issue #38478
+# Tests that go get in GOMOD mode returns a specific error if the argument
+# ends with '.go', has no version, and either has no slash or refers to an
+# existing file.
+
+env GO111MODULE=on
+
+# argument doesn't have .go suffix and has no version
+! go get test
+! stderr 'arguments must be package or module paths'
+! stderr 'exists as a file, but ''go get'' requires package arguments'
+
+# argument has .go suffix and has version
+! go get test.go@v1.0.0
+! stderr 'arguments must be package or module paths'
+! stderr 'exists as a file, but ''go get'' requires package arguments'
+
+# argument has .go suffix, is a file and exists
+! go get test.go
+stderr 'go: test.go: arguments must be package or module paths'
+
+# argument has .go suffix, doesn't exist and has no slashes
+! go get test_missing.go
+stderr 'arguments must be package or module paths'
+
+# argument has .go suffix, is a file and exists in sub-directory
+! go get test/test.go
+stderr 'go: test/test.go exists as a file, but ''go get'' requires package arguments'
+
+# argument has .go suffix, doesn't exist and has slashes
+! go get test/test_missing.go
+! stderr 'arguments must be package or module paths'
+! stderr 'exists as a file, but ''go get'' requires package arguments'
+
+# argument has .go suffix, is a symlink and exists
+[symlink] symlink test_sym.go -> test.go
+[symlink] ! go get test_sym.go
+[symlink] stderr 'go: test_sym.go: arguments must be package or module paths'
+[symlink] rm test_sym.go
+
+# argument has .go suffix, is a symlink and exists in sub-directory
+[symlink] symlink test/test_sym.go -> test.go
+[symlink] ! go get test/test_sym.go
+[symlink] stderr 'go: test/test_sym.go exists as a file, but ''go get'' requires package arguments'
+[symlink] rm test_sym.go
+
+# argument has .go suffix, is a directory and exists
+mkdir test_dir.go
+! go get test_dir.go
+stderr 'go: test_dir.go: arguments must be package or module paths'
+rm test_dir.go
+
+# argument has .go suffix, is a directory and exists in sub-directory
+mkdir test/test_dir.go
+! go get test/test_dir.go
+! stderr 'arguments must be package or module paths'
+! stderr 'exists as a file, but ''go get'' requires package arguments'
+rm test/test_dir.go
+
+
+-- go.mod --
+module m
+
+go 1.18
+
+-- test.go --
+package main
+func main() {println("test")}
+
+
+-- test/test.go --
+package main
+func main() {println("test")}
diff --git a/src/cmd/go/testdata/script/mod_get_hash.txt b/src/cmd/go/testdata/script/mod_get_hash.txt
new file mode 100644
index 0000000..ec5549d
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_hash.txt
@@ -0,0 +1,19 @@
+env GO111MODULE=on
+env GOPROXY=direct
+env GOSUMDB=off
+[!net:golang.org] skip
+[!git] skip
+
+# fetch commit hash reachable from refs/heads/* and refs/tags/* is OK
+go list -m golang.org/x/time@8be79e1e0910c292df4e79c241bb7e8f7e725959 # on master branch
+
+# fetch other commit hash, even with a non-standard ref, is not OK
+! go list -m golang.org/x/time@334d83c35137ac2b376c1dc3e4c7733791855a3a # refs/changes/24/41624/3
+stderr 'unknown revision'
+! go list -m golang.org/x/time@v0.0.0-20170424233410-334d83c35137
+stderr 'unknown revision'
+! go list -m golang.org/x/time@334d83c35137
+stderr 'unknown revision'
+
+-- go.mod --
+module m
diff --git a/src/cmd/go/testdata/script/mod_get_incompatible.txt b/src/cmd/go/testdata/script/mod_get_incompatible.txt
new file mode 100644
index 0000000..5a7d706
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_incompatible.txt
@@ -0,0 +1,26 @@
+env GO111MODULE=on
+
+go get x
+go list -m all
+stdout 'rsc.io/breaker v2.0.0\+incompatible'
+
+cp go.mod2 go.mod
+go get rsc.io/breaker@7307b30
+go list -m all
+stdout 'rsc.io/breaker v2.0.0\+incompatible'
+
+go get rsc.io/breaker@v2.0.0
+go list -m all
+stdout 'rsc.io/breaker v2.0.0\+incompatible'
+
+-- go.mod --
+module x
+
+-- go.mod2 --
+module x
+require rsc.io/breaker v1.0.0
+
+-- x.go --
+package x
+import "rsc.io/breaker"
+var _ = breaker.XX
diff --git a/src/cmd/go/testdata/script/mod_get_indirect.txt b/src/cmd/go/testdata/script/mod_get_indirect.txt
new file mode 100644
index 0000000..fa7edf2
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_indirect.txt
@@ -0,0 +1,59 @@
+env GO111MODULE=on
+[short] skip
+
+# get -u should not upgrade anything, since the package
+# in the current directory doesn't import anything.
+go get -u
+go list -m all
+stdout 'quote v1.5.1$'
+grep 'rsc.io/quote v1.5.1$' go.mod
+
+# get -u should find quote v1.5.2 once there is a use.
+cp $WORK/tmp/usequote.go x.go
+go get -u
+go list -m all
+stdout 'quote v1.5.2$'
+grep 'rsc.io/quote v1.5.2$' go.mod
+
+# it should also update x/text later than requested by v1.5.2
+go list -m -f '{{.Path}} {{.Version}}{{if .Indirect}} // indirect{{end}}' all
+stdout '^golang.org/x/text [v0-9a-f\.-]+ // indirect'
+grep 'golang.org/x/text [v0-9a-f\.-]+ // indirect' go.mod
+
+# importing an empty module root as a package does not remove indirect tag.
+cp $WORK/tmp/usetext.go x.go
+go list -e
+grep 'golang.org/x/text v0.3.0 // indirect$' go.mod
+
+# indirect tag should be removed upon seeing direct import.
+cp $WORK/tmp/uselang.go x.go
+go get
+grep 'rsc.io/quote v1.5.2$' go.mod
+grep 'golang.org/x/text [v0-9a-f\.-]+$' go.mod
+
+# indirect tag should be added by go mod tidy
+cp $WORK/tmp/usequote.go x.go
+go mod tidy
+grep 'rsc.io/quote v1.5.2$' go.mod
+grep 'golang.org/x/text [v0-9a-f\.-]+ // indirect' go.mod
+
+# requirement should be dropped entirely if not needed
+cp $WORK/tmp/uselang.go x.go
+go mod tidy
+! grep rsc.io/quote go.mod
+grep 'golang.org/x/text [v0-9a-f\.-]+$' go.mod
+
+-- go.mod --
+module x
+require rsc.io/quote v1.5.1
+-- x.go --
+package x
+-- $WORK/tmp/usetext.go --
+package x
+import _ "golang.org/x/text"
+-- $WORK/tmp/uselang.go --
+package x
+import _ "golang.org/x/text/language"
+-- $WORK/tmp/usequote.go --
+package x
+import _ "rsc.io/quote"
diff --git a/src/cmd/go/testdata/script/mod_get_insecure_redirect.txt b/src/cmd/go/testdata/script/mod_get_insecure_redirect.txt
new file mode 100644
index 0000000..a503c91
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_insecure_redirect.txt
@@ -0,0 +1,19 @@
+# golang.org/issue/29591: 'go get' was following plain-HTTP redirects even without -insecure (now replaced by GOINSECURE).
+# golang.org/issue/61877: 'go get' would panic in case of an insecure redirect in module mode
+
+[!git] skip
+
+env GOPRIVATE=vcs-test.golang.org
+
+! go get -d vcs-test.golang.org/insecure/go/insecure
+stderr 'redirected .* to insecure URL'
+
+[short] stop 'builds a git repo'
+
+env GOINSECURE=vcs-test.golang.org/insecure/go/insecure
+go get -d vcs-test.golang.org/insecure/go/insecure
+
+-- go.mod --
+module example
+go 1.21
+
diff --git a/src/cmd/go/testdata/script/mod_get_issue37438.txt b/src/cmd/go/testdata/script/mod_get_issue37438.txt
new file mode 100644
index 0000000..9392e73
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_issue37438.txt
@@ -0,0 +1,37 @@
+# Regression test for https://golang.org/issue/37438.
+#
+# If a path exists at the requested version, but does not exist at the
+# version of the module that is already required and does not exist at
+# the version that would be selected by 'go mod tidy', then
+# 'go get foo@requested' should resolve the requested version,
+# not error out on the (unrelated) latest one.
+
+go get example.net/a/p@v0.2.0
+
+-- go.mod --
+module example
+
+go 1.15
+
+require example.net/a v0.1.0
+
+replace (
+ example.net/a v0.1.0 => ./a1
+ example.net/a v0.2.0 => ./a2
+ example.net/a v0.3.0 => ./a1
+)
+
+-- a1/go.mod --
+module example.net/a
+
+go 1.15
+-- a1/README --
+package example.net/a/p does not exist at this version.
+
+-- a2/go.mod --
+module example.net/a
+
+go 1.15
+-- a2/p/p.go --
+// Package p exists only at v0.2.0.
+package p
diff --git a/src/cmd/go/testdata/script/mod_get_issue47650.txt b/src/cmd/go/testdata/script/mod_get_issue47650.txt
new file mode 100644
index 0000000..8561b21
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_issue47650.txt
@@ -0,0 +1,29 @@
+# Regression test for https://go.dev/issue/47650:
+# 'go get' with a pseudo-version of a non-root package within a module
+# erroneously rejected the pseudo-version as invalid, because it did not fetch
+# enough commit history to validate the pseudo-version base.
+
+[short] skip 'creates and uses a git repository'
+[!git] skip
+
+env GOPRIVATE=vcs-test.golang.org
+
+# If we request a package in a subdirectory of a module by commit hash, we
+# successfully resolve it to a pseudo-version derived from a tag on the parent
+# commit.
+cp go.mod go.mod.orig
+go get -x vcs-test.golang.org/git/issue47650.git/cmd/issue47650@21535ef346c3
+stderr '^go: added vcs-test.golang.org/git/issue47650.git v0.1.1-0.20210811175200-21535ef346c3$'
+
+# Explicitly requesting that same version should succeed, fetching additional
+# history for the requested commit as needed in order to validate the
+# pseudo-version base.
+go clean -modcache
+cp go.mod.orig go.mod
+go get -x vcs-test.golang.org/git/issue47650.git/cmd/issue47650@v0.1.1-0.20210811175200-21535ef346c3
+stderr '^go: added vcs-test.golang.org/git/issue47650.git v0.1.1-0.20210811175200-21535ef346c3$'
+
+-- go.mod --
+module example
+
+go 1.20
diff --git a/src/cmd/go/testdata/script/mod_get_issue47979.txt b/src/cmd/go/testdata/script/mod_get_issue47979.txt
new file mode 100644
index 0000000..848ee3a
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_issue47979.txt
@@ -0,0 +1,117 @@
+# Regression test for https://golang.org/issue/47979:
+#
+# An argument to 'go get' that results in an upgrade to a different existing
+# root should be allowed, and should not panic the 'go' command.
+
+cp go.mod go.mod.orig
+
+
+# Transitive upgrades from upgraded roots should not prevent
+# 'go get -u' from performing upgrades.
+
+cp go.mod.orig go.mod
+go get -u .
+cmp go.mod go.mod.want
+
+
+# 'go get' of a specific version should allow upgrades of
+# every dependency (transitively) required by that version,
+# including dependencies that are pulled into the module
+# graph by upgrading other root requirements
+# (in this case, example.net/indirect).
+
+cp go.mod.orig go.mod
+go get example.net/a@v0.2.0
+cmp go.mod go.mod.want
+
+
+-- go.mod --
+module golang.org/issue47979
+
+go 1.17
+
+replace (
+ example.net/a v0.1.0 => ./a1
+ example.net/a v0.2.0 => ./a2
+ example.net/indirect v0.1.0 => ./indirect1
+ example.net/indirect v0.2.0 => ./indirect2
+ example.net/other v0.1.0 => ./other
+ example.net/other v0.2.0 => ./other
+)
+
+require (
+ example.net/a v0.1.0
+ example.net/other v0.1.0
+)
+
+require example.net/indirect v0.1.0 // indirect
+-- go.mod.want --
+module golang.org/issue47979
+
+go 1.17
+
+replace (
+ example.net/a v0.1.0 => ./a1
+ example.net/a v0.2.0 => ./a2
+ example.net/indirect v0.1.0 => ./indirect1
+ example.net/indirect v0.2.0 => ./indirect2
+ example.net/other v0.1.0 => ./other
+ example.net/other v0.2.0 => ./other
+)
+
+require (
+ example.net/a v0.2.0
+ example.net/other v0.2.0
+)
+
+require example.net/indirect v0.2.0 // indirect
+-- issue.go --
+package issue
+
+import _ "example.net/a"
+-- useother/useother.go --
+package useother
+
+import _ "example.net/other"
+-- a1/go.mod --
+module example.net/a
+
+go 1.17
+
+require example.net/indirect v0.1.0
+-- a1/a.go --
+package a
+-- a2/go.mod --
+module example.net/a
+
+go 1.17
+
+require example.net/indirect v0.2.0
+-- a2/a.go --
+package a
+
+import "example.net/indirect"
+-- indirect1/go.mod --
+module example.net/indirect
+
+go 1.17
+
+require example.net/other v0.1.0
+-- indirect1/indirect.go --
+package indirect
+-- indirect2/go.mod --
+module example.net/indirect
+
+go 1.17
+
+require example.net/other v0.2.0
+-- indirect2/indirect.go --
+package indirect
+
+import "example.net/other"
+-- other/go.mod --
+module example.net/other
+
+go 1.17
+-- other/other.go --
+package other
diff --git a/src/cmd/go/testdata/script/mod_get_issue48511.txt b/src/cmd/go/testdata/script/mod_get_issue48511.txt
new file mode 100644
index 0000000..0ba486d
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_issue48511.txt
@@ -0,0 +1,68 @@
+# Regression test for https://golang.org/issue/48511:
+# requirement minimization was accidentally replacing previous
+# versions of the main module, causing dependencies to be
+# spuriously dropping during requirement minimization and
+# leading to an infinite loop.
+
+cp go.mod go.mod.orig
+go mod tidy
+cmp go.mod go.mod.orig
+
+go get -u=patch ./...
+cmp go.mod go.mod.want
+
+-- go.mod --
+module example.net/m
+
+go 1.16
+
+replace (
+ example.net/a v0.1.0 => ./a
+ example.net/b v0.1.0 => ./b
+ example.net/b v0.1.1 => ./b
+ example.net/m v0.1.0 => ./m1
+)
+
+require example.net/a v0.1.0
+-- go.mod.want --
+module example.net/m
+
+go 1.16
+
+replace (
+ example.net/a v0.1.0 => ./a
+ example.net/b v0.1.0 => ./b
+ example.net/b v0.1.1 => ./b
+ example.net/m v0.1.0 => ./m1
+)
+
+require (
+ example.net/a v0.1.0
+ example.net/b v0.1.1 // indirect
+)
+-- m.go --
+package m
+
+import "example.net/a"
+-- m1/go.mod --
+module example.net/m
+
+go 1.16
+
+require example.net/b v0.1.0
+-- a/go.mod --
+module example.net/a
+
+go 1.16
+
+require example.net/m v0.1.0
+-- a/a.go --
+package a
+
+import "example.net/b"
+-- b/go.mod --
+module example.net/b
+
+go 1.16
+-- b/b.go --
+package b
diff --git a/src/cmd/go/testdata/script/mod_get_issue56494.txt b/src/cmd/go/testdata/script/mod_get_issue56494.txt
new file mode 100644
index 0000000..3e4d4af
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_issue56494.txt
@@ -0,0 +1,134 @@
+# Regression test for https://go.dev/issue/56494:
+# 'go get' in module mode was failing to prune out dependencies
+# through modules whose versions are too low to be selected.
+
+# Initially, modules "a", "b", and "c" are unrelated.
+#
+# The package import graph at v1 of everything looks like:
+#
+# m --- a
+# |
+# + --- b
+# |
+# + --- c
+#
+# At v2, package "a" adds imports of "b" and "c"
+# (and a requirement on "c" v2):
+#
+# a --- b
+# |
+# + --- c
+#
+# And "b" adds an import of "a/sub" (in module "a"):
+#
+# b --- a/sub
+#
+# At v3, "a" no longer imports (nor requires) "c":
+#
+# a --- b
+
+# So upgrading to a3 adds a dependency on b2,
+# b2 adds a dependency on a2 (for "a/sub"),
+# and a2 (but not a3) would add a dependency on c2.
+# Since a2 is lower than a3 it cannot possibly be selected when
+# upgrading to a3: normally a2 is pruned out of a3's module graph,
+# so 'go get' should prune it out too, and c should remain at c1
+# without error.
+
+go get a@v0.3.0
+
+go list -m c
+stdout '^c v0.1.0 '
+
+-- go.mod --
+module m
+
+go 1.19
+
+require (
+ a v0.1.0
+ b v0.1.0
+ c v0.1.0
+)
+
+replace (
+ a v0.1.0 => ./a1
+ a v0.2.0 => ./a2
+ a v0.3.0 => ./a3
+ b v0.1.0 => ./b1
+ b v0.2.0 => ./b2
+ c v0.1.0 => ./c1
+ c v0.2.0 => ./c2
+)
+-- m.go --
+package m
+
+import (
+ _ "a"
+ _ "b"
+ _ "c"
+)
+-- a1/go.mod --
+module a
+
+go 1.19
+-- a1/a.go --
+package a
+-- a2/go.mod --
+module a
+
+go 1.19
+
+require (
+ b v0.1.0
+ c v0.2.0
+)
+-- a2/a.go --
+package a
+
+import (
+ _ "b"
+ _ "c"
+)
+-- a2/sub/sub.go --
+package sub
+-- a3/go.mod --
+module a
+
+go 1.19
+
+require b v0.2.0
+-- a3/a.go --
+package a
+
+import _ "b"
+-- a3/sub/sub.go --
+package sub
+-- b1/go.mod --
+module b
+
+go 1.19
+-- b1/b.go --
+package b
+-- b2/go.mod --
+module b
+
+go 1.19
+
+require a v0.2.0
+-- b2/b.go --
+package b
+
+import "a/sub"
+-- c1/go.mod --
+module c
+
+go 1.19
+-- c1/c.go --
+package c
+-- c2/go.mod --
+module c
+
+go 1.19
+-- c2/c.go --
+package c
diff --git a/src/cmd/go/testdata/script/mod_get_issue60490.txt b/src/cmd/go/testdata/script/mod_get_issue60490.txt
new file mode 100644
index 0000000..e0ac26a
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_issue60490.txt
@@ -0,0 +1,48 @@
+# Regression test for https://go.dev/issue/60490: 'go get' should not cause an
+# infinite loop for cycles introduced in the pruned module graph.
+
+go get example.net/c@v0.1.0
+
+-- go.mod --
+module example
+
+go 1.19
+
+require (
+ example.net/a v0.1.0
+ example.net/b v0.1.0
+)
+
+replace (
+ example.net/a v0.1.0 => ./a1
+ example.net/a v0.2.0 => ./a2
+ example.net/b v0.1.0 => ./b1
+ example.net/b v0.2.0 => ./b2
+ example.net/c v0.1.0 => ./c1
+)
+-- a1/go.mod --
+module example.net/a
+
+go 1.19
+-- a2/go.mod --
+module example.net/a
+
+go 1.19
+
+require example.net/b v0.2.0
+-- b1/go.mod --
+module example.net/b
+
+go 1.19
+-- b2/go.mod --
+module example.net/b
+
+go 1.19
+
+require example.net/a v0.2.0
+-- c1/go.mod --
+module example.net/c
+
+go 1.19
+
+require example.net/a v0.2.0
diff --git a/src/cmd/go/testdata/script/mod_get_latest_pseudo.txt b/src/cmd/go/testdata/script/mod_get_latest_pseudo.txt
new file mode 100644
index 0000000..00da0c3
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_latest_pseudo.txt
@@ -0,0 +1,10 @@
+# Check that we can build a module with no tagged versions by querying
+# "@latest" through a proxy.
+# Verifies golang.org/issue/32636
+
+env GO111MODULE=on
+
+go mod init m
+go get example.com/notags
+go list -m all
+stdout '^example.com/notags v0.0.0-20190507143103-cc8cbe209b64$'
diff --git a/src/cmd/go/testdata/script/mod_get_lazy_indirect.txt b/src/cmd/go/testdata/script/mod_get_lazy_indirect.txt
new file mode 100644
index 0000000..1cef9d1
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_lazy_indirect.txt
@@ -0,0 +1,44 @@
+# https://golang.org/issue/45979: after 'go get' on a package,
+# that package should be importable without error.
+
+
+# We start out with an unresolved dependency.
+# 'go list' suggests that we run 'go get' on that dependency.
+
+! go list -deps .
+stderr '^m.go:3:8: no required module provides package rsc\.io/quote; to add it:\n\tgo get rsc.io/quote$'
+
+
+# When we run the suggested 'go get' command, the new dependency can be used
+# immediately.
+#
+# 'go get' marks the new dependency as 'indirect', because it doesn't scan
+# enough source code to know whether it is direct, and it is easier and less
+# invasive to remove an incorrect indirect mark (e.g. using 'go get') than to
+# add one that is missing ('go mod tidy' or 'go mod vendor').
+
+go get rsc.io/quote
+grep 'rsc.io/quote v\d+\.\d+\.\d+ // indirect$' go.mod
+! grep 'rsc.io/quote v\d+\.\d+\.\d+$' go.mod
+
+go list -deps .
+! stderr .
+[!short] go build .
+[!short] ! stderr .
+
+
+# 'go get .' (or 'go mod tidy') removes the indirect mark.
+
+go get .
+grep 'rsc.io/quote v\d+\.\d+\.\d+$' go.mod
+! grep 'rsc.io/quote v\d+\.\d+\.\d+ // indirect$' go.mod
+
+
+-- go.mod --
+module example.com/m
+
+go 1.17
+-- m.go --
+package m
+
+import _ "rsc.io/quote"
diff --git a/src/cmd/go/testdata/script/mod_get_lazy_upgrade_lazy.txt b/src/cmd/go/testdata/script/mod_get_lazy_upgrade_lazy.txt
new file mode 100644
index 0000000..3dae383
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_lazy_upgrade_lazy.txt
@@ -0,0 +1,68 @@
+# Check that 'go get -u' will upgrade a dependency (direct or indirect)
+# when the main module and the dependency are both lazy.
+# Verifies #47768.
+
+# Check that go.mod is tidy, and an upgrade is available.
+cp go.mod go.mod.orig
+go mod tidy
+cmp go.mod go.mod.orig
+
+go list -m -u example.com/lazyupgrade
+stdout '^example.com/lazyupgrade v0.1.0 \[v0.1.1\] => ./lazyupgrade@v0.1.0$'
+
+# 'go get -u' on a package that directly imports the dependency should upgrade.
+go get -u ./usedirect
+go list -m example.com/lazyupgrade
+stdout '^example.com/lazyupgrade v0.1.1 => ./lazyupgrade@v0.1.1$'
+cp go.mod.orig go.mod
+
+# 'go get -u' on a package that indirectly imports the dependency should upgrade.
+go get -u ./useindirect
+go list -m example.com/lazyupgrade
+stdout '^example.com/lazyupgrade v0.1.1 => ./lazyupgrade@v0.1.1$'
+
+-- go.mod --
+module use
+
+go 1.17
+
+require (
+ direct v0.0.0
+ example.com/lazyupgrade v0.1.0
+)
+
+replace (
+ direct => ./direct
+ example.com/lazyupgrade v0.1.0 => ./lazyupgrade@v0.1.0
+ example.com/lazyupgrade v0.1.1 => ./lazyupgrade@v0.1.1
+)
+-- usedirect/usedirect.go --
+package use
+
+import _ "example.com/lazyupgrade"
+-- useindirect/useindirect.go --
+package use
+
+import _ "direct"
+-- direct/go.mod --
+module direct
+
+go 1.17
+
+require example.com/lazyupgrade v0.1.0
+-- direct/direct.go --
+package direct
+
+import _ "example.com/lazyupgrade"
+-- lazyupgrade@v0.1.0/go.mod --
+module example.com/lazyupgrade
+
+go 1.17
+-- lazyupgrade@v0.1.0/lazyupgrade.go --
+package lazyupgrade
+-- lazyupgrade@v0.1.1/go.mod --
+module example.com/lazyupgrade
+
+go 1.17
+-- lazyupgrade@v0.1.1/lazyupgrade.go --
+package lazyupgrade
diff --git a/src/cmd/go/testdata/script/mod_get_local.txt b/src/cmd/go/testdata/script/mod_get_local.txt
new file mode 100644
index 0000000..4c81d16
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_local.txt
@@ -0,0 +1,62 @@
+# Test 'go get' with a local module with a name that is not valid for network lookup.
+[short] skip
+
+env GO111MODULE=on
+go mod edit -fmt
+cp go.mod go.mod.orig
+
+# 'go get -u' within the main module should work, even if it has a local-only name.
+cp go.mod.orig go.mod
+go get -u ./...
+grep 'rsc.io/quote.*v1.5.2' go.mod
+grep 'golang.org/x/text.*v0.3.0' go.mod
+cp go.mod go.mod.implicitmod
+
+# 'go get -u local/...' should be equivalent to 'go get -u ./...'
+# (assuming no nested modules)
+cp go.mod.orig go.mod
+go get -u local/...
+cmp go.mod go.mod.implicitmod
+
+# For the main module, @patch should be a no-op.
+cp go.mod.orig go.mod
+go get -u local/...@patch
+cmp go.mod go.mod.implicitmod
+
+# 'go get -u' in the empty root of the main module should fail.
+# 'go get -u .' should also fail.
+cp go.mod.orig go.mod
+! go get -u
+! go get -u .
+
+# 'go get -u .' within a package in the main module updates the dependencies
+# of that package.
+cp go.mod.orig go.mod
+cd uselang
+go get -u .
+cd ..
+grep 'rsc.io/quote.*v1.3.0' go.mod
+grep 'golang.org/x/text.*v0.3.0' go.mod
+cp go.mod go.mod.dotpkg
+
+# 'go get -u' with an explicit package in the main module updates the
+# dependencies of that package.
+cp go.mod.orig go.mod
+go get -u local/uselang
+cmp go.mod go.mod.dotpkg
+
+-- go.mod --
+module local
+
+require (
+ golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
+ rsc.io/quote v1.3.0
+)
+
+-- uselang/uselang.go --
+package uselang
+import _ "golang.org/x/text/language"
+
+-- usequote/usequote.go --
+package usequote
+import _ "rsc.io/quote"
diff --git a/src/cmd/go/testdata/script/mod_get_main.txt b/src/cmd/go/testdata/script/mod_get_main.txt
new file mode 100644
index 0000000..cddd5f7
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_main.txt
@@ -0,0 +1,51 @@
+env GO111MODULE=on
+cp go.mod.orig go.mod
+
+# relative and absolute paths must be within the main module.
+! go get ..
+stderr '^go: \.\. \('$WORK'[/\\]gopath\) is not within module rooted at '$WORK'[/\\]gopath[/\\]src$'
+! go get $WORK
+stderr '^go: '$WORK' is not within module rooted at '$WORK'[/\\]gopath[/\\]src$'
+! go get ../...
+stderr '^go: \.\./\.\.\. \('$WORK'[/\\]gopath([/\\]...)?\) is not within module rooted at '$WORK'[/\\]gopath[/\\]src$'
+! go get $WORK/...
+stderr '^go: '$WORK'[/\\]\.\.\. is not within module rooted at '$WORK'[/\\]gopath[/\\]src$'
+
+# @patch and @latest within the main module refer to the current version.
+# The main module won't be upgraded, but missing dependencies will be added.
+go get rsc.io/x
+grep 'rsc.io/quote v1.5.2' go.mod
+go get rsc.io/x@upgrade
+grep 'rsc.io/quote v1.5.2' go.mod
+cp go.mod.orig go.mod
+go get rsc.io/x@patch
+grep 'rsc.io/quote v1.5.2' go.mod
+cp go.mod.orig go.mod
+
+
+# Upgrading a package pattern not contained in the main module should not
+# attempt to upgrade the main module.
+go get rsc.io/quote/...@v1.5.1
+grep 'rsc.io/quote v1.5.1' go.mod
+
+
+# The main module cannot be updated to a specific version.
+! go get rsc.io@v0.1.0
+stderr '^go: can''t request version "v0.1.0" of the main module \(rsc.io\)$'
+
+# A package in the main module can't be upgraded either.
+! go get rsc.io/x@v0.1.0
+stderr '^go: package rsc.io/x is in the main module, so can''t request version v0.1.0$'
+
+# Nor can a pattern matching packages in the main module.
+! go get rsc.io/x/...@latest
+stderr '^go: pattern rsc.io/x/... matches package rsc.io/x in the main module, so can''t request version latest$'
+
+-- go.mod.orig --
+module rsc.io
+
+go 1.13
+-- x/x.go --
+package x
+
+import _ "rsc.io/quote"
diff --git a/src/cmd/go/testdata/script/mod_get_major.txt b/src/cmd/go/testdata/script/mod_get_major.txt
new file mode 100644
index 0000000..4e0febb
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_major.txt
@@ -0,0 +1,23 @@
+[short] skip
+[!git] skip
+
+env GO111MODULE=on
+env GOPROXY=direct
+env GOSUMDB=off
+
+# golang.org/issue/34383: if a module path ends in a major-version suffix,
+# ensure that 'direct' mode can resolve the package to a module.
+
+go get vcs-test.golang.org/git/v3pkg.git/v3@v3.0.0
+
+go list -m vcs-test.golang.org/git/v3pkg.git/v3
+stdout '^vcs-test.golang.org/git/v3pkg.git/v3 v3.0.0$'
+
+go get vcs-test.golang.org/git/empty-v2-without-v1.git/v2@v2.0.0
+
+go list -m vcs-test.golang.org/git/empty-v2-without-v1.git/v2
+stdout '^vcs-test.golang.org/git/empty-v2-without-v1.git/v2 v2.0.0$'
+
+-- go.mod --
+module example.com
+go 1.13
diff --git a/src/cmd/go/testdata/script/mod_get_missing_ziphash.txt b/src/cmd/go/testdata/script/mod_get_missing_ziphash.txt
new file mode 100644
index 0000000..5934251
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_missing_ziphash.txt
@@ -0,0 +1,55 @@
+# Test that if the module cache contains an extracted source directory but not
+# a ziphash, 'go build' complains about a missing sum, and 'go get' adds
+# the sum. Verifies #44749.
+
+# With a tidy go.sum, go build succeeds. This also populates the module cache.
+cp go.sum.tidy go.sum
+go build -n use
+env GOPROXY=off
+env GOSUMDB=off
+
+# Control case: if we delete the hash for rsc.io/quote v1.5.2,
+# 'go build' reports an error. 'go get' adds the sum.
+cp go.sum.bug go.sum
+! go build -n use
+stderr '^use.go:3:8: missing go.sum entry for module providing package rsc.io/quote \(imported by use\); to add:\n\tgo get use$'
+go get use
+cmp go.sum go.sum.tidy
+go build -n use
+
+# If we delete the hash *and* the ziphash file, we should see the same behavior.
+cp go.sum.bug go.sum
+rm $WORK/gopath/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.ziphash
+! go build -n use
+stderr '^use.go:3:8: missing go.sum entry for module providing package rsc.io/quote \(imported by use\); to add:\n\tgo get use$'
+go get use
+cmp go.sum go.sum.tidy
+go build -n use
+
+-- go.mod --
+module use
+
+go 1.16
+
+require rsc.io/quote v1.5.2
+-- go.sum.tidy --
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw=
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0=
+rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
+rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+rsc.io/testonly v1.0.0 h1:K/VWHdO+Jv7woUXG0GzVNx1czBXUt3Ib1deaMn+xk64=
+rsc.io/testonly v1.0.0/go.mod h1:OqmGbIFOcF+XrFReLOGZ6BhMM7uMBiQwZsyNmh74SzY=
+-- go.sum.bug --
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw=
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
+rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+rsc.io/testonly v1.0.0 h1:K/VWHdO+Jv7woUXG0GzVNx1czBXUt3Ib1deaMn+xk64=
+rsc.io/testonly v1.0.0/go.mod h1:OqmGbIFOcF+XrFReLOGZ6BhMM7uMBiQwZsyNmh74SzY=
+-- use.go --
+package use
+
+import _ "rsc.io/quote"
diff --git a/src/cmd/go/testdata/script/mod_get_moved.txt b/src/cmd/go/testdata/script/mod_get_moved.txt
new file mode 100644
index 0000000..cc35b4c
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_moved.txt
@@ -0,0 +1,40 @@
+env GO111MODULE=on
+[short] skip
+
+# A 'go get' that worked at a previous version should continue to work at that version,
+# even if the package was subsequently moved into a submodule.
+go mod init example.com/foo
+go get example.com/split/subpkg@v1.0.0
+go list -m all
+stdout 'example.com/split v1.0.0'
+
+# A 'go get' that simultaneously upgrades away conflicting package definitions is not ambiguous.
+go get example.com/split/subpkg@v1.1.0
+
+# A 'go get' without an upgrade should find the package.
+rm go.mod
+go mod init example.com/foo
+go get example.com/split/subpkg
+go list -m all
+stdout 'example.com/split/subpkg v1.1.0'
+
+
+# A 'go get' that worked at a previous version should continue to work at that version,
+# even if the package was subsequently moved into a parent module.
+rm go.mod
+go mod init example.com/foo
+go get example.com/join/subpkg@v1.0.0
+go list -m all
+stdout 'example.com/join/subpkg v1.0.0'
+
+# A 'go get' that simultaneously upgrades away conflicting package definitions is not ambiguous.
+# (A wildcard pattern applies to both packages and modules,
+# because we define wildcard matching to apply after version resolution.)
+go get example.com/join/subpkg/...@v1.1.0
+
+# A 'go get' without an upgrade should find the package.
+rm go.mod
+go mod init example.com/foo
+go get example.com/join/subpkg@v1.1.0
+go list -m all
+stdout 'example.com/join v1.1.0'
diff --git a/src/cmd/go/testdata/script/mod_get_newcycle.txt b/src/cmd/go/testdata/script/mod_get_newcycle.txt
new file mode 100644
index 0000000..4f5229e
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_newcycle.txt
@@ -0,0 +1,14 @@
+env GO111MODULE=on
+
+# Download modules to avoid stderr chatter
+go mod download example.com@v1.0.0
+go mod download example.com/newcycle/a@v1.0.0
+go mod download example.com/newcycle/a@v1.0.1
+go mod download example.com/newcycle/b@v1.0.0
+
+go mod init m
+! go get example.com/newcycle/a@v1.0.0
+cmp stderr stderr-expected
+
+-- stderr-expected --
+go: example.com/newcycle/a@v1.0.0 indirectly requires example.com/newcycle/a@v1.0.1, not example.com/newcycle/a@v1.0.0
diff --git a/src/cmd/go/testdata/script/mod_get_none.txt b/src/cmd/go/testdata/script/mod_get_none.txt
new file mode 100644
index 0000000..5aec209
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_none.txt
@@ -0,0 +1,12 @@
+env GO111MODULE=on
+
+go mod init example.com/foo
+
+# 'go get bar@none' should be a no-op if module bar is not active.
+go get example.com/bar@none
+go list -m all
+! stdout example.com/bar
+
+go get example.com/bar@none
+go list -m all
+! stdout example.com/bar
diff --git a/src/cmd/go/testdata/script/mod_get_nopkgs.txt b/src/cmd/go/testdata/script/mod_get_nopkgs.txt
new file mode 100644
index 0000000..14176a7
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_nopkgs.txt
@@ -0,0 +1,40 @@
+cd subdir
+
+# 'go get' on empty patterns that are necessarily local to the module
+# should warn that the patterns are empty, exactly once.
+
+go get ./...
+stderr -count=1 'matched no packages'
+
+go get ./...
+stderr -count=1 'matched no packages'
+
+# 'go get' on patterns that could conceivably match nested modules
+# should report a module resolution error.
+
+go get example.net/emptysubdir/... # control case
+
+! go get example.net/emptysubdir/subdir/...
+! stderr 'matched no packages'
+stderr '^go: example\.net/emptysubdir/subdir/\.\.\.: module example\.net/emptysubdir/subdir: reading http://.*: 404 Not Found\n\tserver response: 404 page not found\n\z'
+
+# It doesn't make sense to 'go get' a path in the standard library,
+# since the standard library necessarily can't have unresolved imports.
+#
+# TODO(#30241): Maybe that won't always be the case?
+#
+# For that case, we emit a "malformed module path" error message,
+# which isn't ideal either.
+
+! go get builtin/... # in GOROOT/src, but contains no packages
+stderr '^go: builtin/...: malformed module path "builtin": missing dot in first path element$'
+
+-- go.mod --
+module example.net/emptysubdir
+
+go 1.16
+-- emptysubdir.go --
+// Package emptysubdir has a subdirectory containing no packages.
+package emptysubdir
+-- subdir/README.txt --
+This module intentionally does not contain any p
diff --git a/src/cmd/go/testdata/script/mod_get_patch.txt b/src/cmd/go/testdata/script/mod_get_patch.txt
new file mode 100644
index 0000000..35cc276
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_patch.txt
@@ -0,0 +1,130 @@
+# This test examines the behavior of 'go get …@patch'
+# See also mod_upgrade_patch.txt (focused on "-u=patch" specifically)
+# and mod_get_patchmod.txt (focused on module/package ambiguities).
+
+cp go.mod go.mod.orig
+
+# example.net/b@patch refers to the patch for the version of b that was selected
+# at the start of 'go get', not the version after applying other changes.
+
+! go get example.net/a@v0.2.0 example.net/b@patch
+stderr '^go: example.net/a@v0.2.0 requires example.net/b@v0.2.0, not example.net/b@patch \(v0.1.1\)$'
+cmp go.mod go.mod.orig
+
+
+# -u=patch changes the default version for other arguments to '@patch',
+# but they continue to be resolved against the originally-selected version,
+# not the updated one.
+#
+# TODO(#42360): Reconsider the change in defaults.
+
+! go get -u=patch example.net/a@v0.2.0 example.net/b
+stderr '^go: example.net/a@v0.2.0 requires example.net/b@v0.2.0, not example.net/b@patch \(v0.1.1\)$'
+cmp go.mod go.mod.orig
+
+
+# -u=patch refers to the patches for the selected versions of dependencies *after*
+# applying other version changes, not the versions that were selected at the start.
+# However, it should not patch versions determined by explicit arguments.
+
+go get -u=patch example.net/a@v0.2.0
+go list -m all
+stdout '^example.net/a v0.2.0 '
+stdout '^example.net/b v0.2.1 '
+
+
+# "-u=patch all" should be equivalent to "all@patch", and should fail if the
+# patched versions result in a higher-than-patch upgrade.
+
+cp go.mod.orig go.mod
+! go get -u=patch all
+stderr '^go: example.net/a@v0.1.1 \(matching all@patch\) requires example.net/b@v0.2.0, not example.net/b@v0.1.1 \(matching all@patch\)$'
+cmp go.mod go.mod.orig
+
+
+# On the other hand, "-u=patch ./..." should patch-upgrade dependencies until
+# they reach a fixed point, even if that results in higher-than-patch upgrades.
+
+go get -u=patch ./...
+go list -m all
+stdout '^example.net/a v0.1.1 '
+stdout '^example.net/b v0.2.1 '
+
+
+-- go.mod --
+module example
+
+go 1.16
+
+require (
+ example.net/a v0.1.0
+ example.net/b v0.1.0 // indirect
+)
+
+replace (
+ example.net/a v0.1.0 => ./a10
+ example.net/a v0.1.1 => ./a11
+ example.net/a v0.2.0 => ./a20
+ example.net/a v0.2.1 => ./a21
+ example.net/b v0.1.0 => ./b
+ example.net/b v0.1.1 => ./b
+ example.net/b v0.2.0 => ./b
+ example.net/b v0.2.1 => ./b
+ example.net/b v0.3.0 => ./b
+ example.net/b v0.3.1 => ./b
+)
+-- example.go --
+package example
+
+import _ "example.net/a"
+
+-- a10/go.mod --
+module example.net/a
+
+go 1.16
+
+require example.net/b v0.1.0
+-- a10/a.go --
+package a
+
+import _ "example.net/b"
+
+-- a11/go.mod --
+module example.net/a
+
+go 1.16
+
+require example.net/b v0.2.0 // upgraded
+-- a11/a.go --
+package a
+
+import _ "example.net/b"
+
+-- a20/go.mod --
+module example.net/a
+
+go 1.16
+
+require example.net/b v0.2.0
+-- a20/a.go --
+package a
+
+import _ "example.net/b"
+
+-- a21/go.mod --
+module example.net/a
+
+go 1.16
+
+require example.net/b v0.2.0 // not upgraded
+-- a21/a.go --
+package a
+
+import _ "example.net/b"
+
+-- b/go.mod --
+module example.net/b
+
+go 1.16
+-- b/b.go --
+package b
diff --git a/src/cmd/go/testdata/script/mod_get_patchbound.txt b/src/cmd/go/testdata/script/mod_get_patchbound.txt
new file mode 100644
index 0000000..e4d3c49
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_patchbound.txt
@@ -0,0 +1,84 @@
+# -u=patch will patch dependencies as far as possible, but not so far that they
+# conflict with other command-line arguments.
+
+go list -m all
+stdout '^example.net/a v0.1.0 '
+stdout '^example.net/b v0.1.0 '
+
+go get -u=patch example.net/a@v0.2.0
+go list -m all
+stdout '^example.net/a v0.2.0 '
+stdout '^example.net/b v0.1.1 ' # not v0.1.2, which requires …/a v0.3.0.
+
+-- go.mod --
+module example
+
+go 1.16
+
+require (
+ example.net/a v0.1.0
+ example.net/b v0.1.0 // indirect
+)
+
+replace (
+ example.net/a v0.1.0 => ./a
+ example.net/a v0.2.0 => ./a
+ example.net/a v0.3.0 => ./a
+ example.net/b v0.1.0 => ./b10
+ example.net/b v0.1.1 => ./b11
+ example.net/b v0.1.2 => ./b12
+)
+-- example.go --
+package example
+
+import _ "example.net/a"
+
+-- a/go.mod --
+module example.net/a
+
+go 1.16
+
+require example.net/b v0.1.0
+-- a/a.go --
+package a
+
+import _ "example.net/b"
+
+-- b10/go.mod --
+module example.net/b
+
+go 1.16
+
+require example.net/a v0.1.0
+-- b10/b.go --
+package b
+-- b10/b_test.go --
+package b_test
+
+import _ "example.net/a"
+
+-- b11/go.mod --
+module example.net/b
+
+go 1.16
+
+require example.net/a v0.2.0
+-- b11/b.go --
+package b
+-- b11/b_test.go --
+package b_test
+
+import _ "example.net/a"
+
+-- b12/go.mod --
+module example.net/b
+
+go 1.16
+
+require example.net/a v0.3.0
+-- b12/b.go --
+package b
+-- b12/b_test.go --
+package b_test
+
+import _ "example.net/a"
diff --git a/src/cmd/go/testdata/script/mod_get_patchcycle.txt b/src/cmd/go/testdata/script/mod_get_patchcycle.txt
new file mode 100644
index 0000000..9f180d6
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_patchcycle.txt
@@ -0,0 +1,64 @@
+# If a patch of a module requires a higher version of itself,
+# it should be reported as its own conflict.
+#
+# This case is weird and unlikely to occur often at all, but it should not
+# spuriously succeed.
+# (It used to print v0.1.1 but then silently upgrade to v0.2.0.)
+
+! go get example.net/a@patch
+stderr '^go: example.net/a@patch \(v0.1.1\) indirectly requires example.net/a@v0.2.0, not example.net/a@patch \(v0.1.1\)$' # TODO: A mention of b v0.1.0 would be nice.
+
+-- go.mod --
+module example
+
+go 1.16
+
+require example.net/a v0.1.0
+
+replace (
+ example.net/a v0.1.0 => ./a10
+ example.net/a v0.1.1 => ./a11
+ example.net/a v0.2.0 => ./a20
+ example.net/b v0.1.0 => ./b10
+)
+-- example.go --
+package example
+
+import _ "example.net/a"
+
+-- a10/go.mod --
+module example.net/a
+
+go 1.16
+-- a10/a.go --
+package a
+
+-- a11/go.mod --
+module example.net/a
+
+go 1.16
+
+require example.net/b v0.1.0
+-- a11/a.go --
+package a
+
+import _ "example.net/b"
+
+-- a20/go.mod --
+module example.net/a
+
+go 1.16
+-- a20/a.go --
+package a
+
+
+-- b10/go.mod --
+module example.net/b
+
+go 1.16
+
+require example.net/a v0.2.0
+-- b10/b.go --
+package b
+
+import _ "example.net/a"
diff --git a/src/cmd/go/testdata/script/mod_get_patchmod.txt b/src/cmd/go/testdata/script/mod_get_patchmod.txt
new file mode 100644
index 0000000..2827731
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_patchmod.txt
@@ -0,0 +1,82 @@
+# example.net/pkgremoved@v0.1.0 refers to a package.
+go get example.net/pkgremoved@v0.1.0
+
+go list example.net/pkgremoved
+stdout '^example.net/pkgremoved'
+
+cp go.mod go.mod.orig
+
+
+# When we resolve a new dependency on example.net/other,
+# it will change the meaning of the path "example.net/pkgremoved"
+# from a package (at v0.1.0) to only a module (at v0.2.0).
+#
+# If we simultaneously 'get' that module at the query "patch", the module should
+# be constrained to the latest patch of its originally-selected version (v0.1.0),
+# not upgraded to the latest patch of the new transitive dependency.
+
+! go get example.net/pkgremoved@patch example.net/other@v0.1.0
+stderr '^go: example.net/other@v0.1.0 requires example.net/pkgremoved@v0.2.0, not example.net/pkgremoved@patch \(v0.1.1\)$'
+cmp go.mod.orig go.mod
+
+
+# However, we should be able to patch from a package to a module and vice-versa.
+
+# Package to module ...
+
+go get example.net/pkgremoved@v0.3.0
+go list example.net/pkgremoved
+stdout 'example.net/pkgremoved'
+
+go get example.net/pkgremoved@patch
+! go list example.net/pkgremoved
+
+# ... and module to package.
+
+go get example.net/pkgremoved@v0.4.0
+! go list example.net/pkgremoved
+
+go get example.net/pkgremoved@patch
+go list example.net/pkgremoved
+stdout 'example.net/pkgremoved'
+
+
+-- go.mod --
+module example
+
+go 1.16
+
+replace (
+ example.net/other v0.1.0 => ./other
+
+ example.net/pkgremoved v0.1.0 => ./prpkg
+ example.net/pkgremoved v0.1.1 => ./prpkg
+
+ example.net/pkgremoved v0.2.0 => ./prmod
+ example.net/pkgremoved v0.2.1 => ./prmod
+
+ example.net/pkgremoved v0.3.0 => ./prpkg
+ example.net/pkgremoved v0.3.1 => ./prmod
+
+ example.net/pkgremoved v0.4.0 => ./prmod
+ example.net/pkgremoved v0.4.1 => ./prpkg
+)
+-- other/go.mod --
+module example.net/other
+
+go 1.16
+
+require example.net/pkgremoved v0.2.0
+-- other/other.go --
+package other
+-- prpkg/go.mod --
+module example.net/pkgremoved
+
+go 1.16
+-- prpkg/pkgremoved.go --
+package pkgremoved
+-- prmod/go.mod --
+module example.net/pkgremoved
+-- prmod/README.txt --
+Package pkgremoved was removed in v0.2.0 and v0.3.1,
+and added in v0.1.0 and v0.4.1.
diff --git a/src/cmd/go/testdata/script/mod_get_patterns.txt b/src/cmd/go/testdata/script/mod_get_patterns.txt
new file mode 100644
index 0000000..891353f
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_patterns.txt
@@ -0,0 +1,42 @@
+env GO111MODULE=on
+[short] skip
+
+# If a pattern doesn't match any packages provided by modules
+# in the build list, we assume the pattern matches a single module
+# whose path is a prefix of the part of the pattern before "...".
+cp go.mod.orig go.mod
+go get rsc.io/quote/...
+grep 'require rsc.io/quote' go.mod
+
+cp go.mod.orig go.mod
+! go get rsc.io/quote/x...
+stderr 'go: module rsc.io/quote@upgrade found \(v1.5.2\), but does not contain packages matching rsc.io/quote/x...'
+! grep 'require rsc.io/quote' go.mod
+
+! go get rsc.io/quote/x/...
+stderr 'go: module rsc.io/quote@upgrade found \(v1.5.2\), but does not contain packages matching rsc.io/quote/x/...'
+! grep 'require rsc.io/quote' go.mod
+
+# If a pattern matches no packages within a module, the module should not
+# be upgraded, even if the module path is a prefix of the pattern.
+cp go.mod.orig go.mod
+go mod edit -require example.com/nest@v1.0.0
+go get example.com/nest/sub/y...
+grep 'example.com/nest/sub v1.0.0' go.mod
+grep 'example.com/nest v1.0.0' go.mod
+
+# However, if the pattern matches the module path itself, the module
+# should be upgraded even if it contains no matching packages.
+go get example.com/n...t
+grep 'example.com/nest v1.1.0' go.mod
+grep 'example.com/nest/sub v1.0.0' go.mod
+
+-- go.mod.orig --
+module m
+
+go 1.13
+
+-- use/use.go --
+package use
+
+import _ "rsc.io/quote"
diff --git a/src/cmd/go/testdata/script/mod_get_pkgtags.txt b/src/cmd/go/testdata/script/mod_get_pkgtags.txt
new file mode 100644
index 0000000..8cb41ad
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_pkgtags.txt
@@ -0,0 +1,130 @@
+# https://golang.org/issue/44106
+# 'go get' should fetch the transitive dependencies of packages regardless of
+# tags, but shouldn't error out if the package is missing tag-guarded
+# dependencies.
+
+# Control case: just adding the top-level module to the go.mod file does not
+# fetch its dependencies.
+
+go mod edit -require example.net/tools@v0.1.0
+! go list -deps example.net/cmd/tool
+stderr '^module example\.net/cmd provides package example\.net/cmd/tool and is replaced but not required; to add it:\n\tgo get example\.net/cmd@v0\.1\.0$'
+go mod edit -droprequire example.net/tools
+
+
+# 'go get' makes a best effort to fetch those dependencies, but shouldn't
+# error out if dependencies of tag-guarded files are missing.
+
+go get example.net/tools@v0.1.0
+! stderr 'no Go source files'
+
+! go list example.net/tools
+stderr '^package example.net/tools: build constraints exclude all Go files in .*[/\\]tools$'
+
+go list -tags=tools -e -deps example.net/tools
+stdout '^example.net/cmd/tool$'
+stdout '^example.net/missing$'
+
+go list -deps example.net/cmd/tool
+
+! go list example.net/missing
+stderr '^no required module provides package example.net/missing; to add it:\n\tgo get example.net/missing$'
+
+
+# https://golang.org/issue/33526: 'go get' without '-d' should succeed
+# for a module whose root is a constrained-out package.
+#
+# Ideally it should silently succeed, but today it logs the "no Go source files"
+# error and succeeds anyway.
+
+go get example.net/tools@v0.1.0
+! stderr .
+
+! go build example.net/tools
+stderr '^package example.net/tools: build constraints exclude all Go files in .*[/\\]tools$'
+
+
+# https://golang.org/issue/29268
+# 'go get' should fetch modules whose roots contain test-only packages, but
+# without the -t flag shouldn't error out if the test has missing dependencies.
+
+go get example.net/testonly@v0.1.0
+
+# With the -t flag, the test dependencies must resolve successfully.
+! go get -t example.net/testonly@v0.1.0
+stderr '^go: example.net/testonly tested by\n\texample.net/testonly\.test imports\n\texample.net/missing: cannot find module providing package example.net/missing$'
+
+
+# 'go get' should succeed for a module path that does not contain a package,
+# but fail for a non-package subdirectory of a module.
+
+! go get example.net/missing/subdir@v0.1.0
+stderr '^go: module example.net/missing@v0.1.0 found \(replaced by ./missing\), but does not contain package example.net/missing/subdir$'
+
+go get example.net/missing@v0.1.0
+
+
+# Getting the subdirectory should continue to fail even if the corresponding
+# module is already present in the build list.
+
+! go get example.net/missing/subdir@v0.1.0
+stderr '^go: module example.net/missing@v0.1.0 found \(replaced by ./missing\), but does not contain package example.net/missing/subdir$'
+
+
+-- go.mod --
+module example.net/m
+
+go 1.15
+
+replace (
+ example.net/tools v0.1.0 => ./tools
+ example.net/cmd v0.1.0 => ./cmd
+ example.net/testonly v0.1.0 => ./testonly
+ example.net/missing v0.1.0 => ./missing
+)
+
+-- tools/go.mod --
+module example.net/tools
+
+go 1.15
+
+// Requirements intentionally omitted.
+
+-- tools/tools.go --
+// +build tools
+
+package tools
+
+import (
+ _ "example.net/cmd/tool"
+ _ "example.net/missing"
+)
+
+-- cmd/go.mod --
+module example.net/cmd
+
+go 1.16
+-- cmd/tool/tool.go --
+package main
+
+func main() {}
+
+-- testonly/go.mod --
+module example.net/testonly
+
+go 1.15
+-- testonly/testonly_test.go --
+package testonly_test
+
+import _ "example.net/missing"
+
+func Test(t *testing.T) {}
+
+-- missing/go.mod --
+module example.net/missing
+
+go 1.15
+-- missing/README.txt --
+There are no Go source files here.
+-- missing/subdir/README.txt --
+There are no Go source files here either.
diff --git a/src/cmd/go/testdata/script/mod_get_prefer_incompatible.txt b/src/cmd/go/testdata/script/mod_get_prefer_incompatible.txt
new file mode 100644
index 0000000..06e2fc6
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_prefer_incompatible.txt
@@ -0,0 +1,29 @@
+# Verifies golang.org/issue/37574.
+
+# If we are already using an +incompatible version, we shouldn't look up
+# a lower compatible version when upgrading.
+cp go.mod go.mod.orig
+go mod tidy
+cmp go.mod.orig go.mod
+grep '^example.com/incompatiblewithsub v2\.0\.0\+incompatible' go.sum
+! grep '^example.com/incompatiblewithsub v1.0.0' go.sum
+
+go get example.com/incompatiblewithsub/sub
+cmp go.mod.orig go.mod
+! grep '^example.com/incompatiblewithsub v1.0.0' go.sum
+
+# TODO(golang.org/issue/31580): the 'go get' command above should not change
+# go.sum. However, as part of the query above, we download example.com@v1.0.0,
+# an unrelated module, since it's a possible prefix. The sum for that module
+# should not be written to go.sum.
+
+-- go.mod --
+module m
+
+go 1.15
+
+require example.com/incompatiblewithsub v2.0.0+incompatible
+-- use.go --
+package use
+
+import _ "example.com/incompatiblewithsub/sub"
diff --git a/src/cmd/go/testdata/script/mod_get_promote_implicit.txt b/src/cmd/go/testdata/script/mod_get_promote_implicit.txt
new file mode 100644
index 0000000..03f6810
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_promote_implicit.txt
@@ -0,0 +1,92 @@
+cp go.mod.orig go.mod
+
+# If we list a package in an implicit dependency imported from the main module,
+# we should get an error because the dependency should have an explicit
+# requirement.
+go list -m indirect-with-pkg
+stdout '^indirect-with-pkg v1.0.0 => ./indirect-with-pkg$'
+! go list ./use-indirect
+stderr '^package m/use-indirect imports indirect-with-pkg from implicitly required module; to add missing requirements, run:\n\tgo get indirect-with-pkg@v1.0.0$'
+
+# We can promote the implicit requirement by getting the importing package.
+# NOTE: the hint recommends getting the imported package (tested below) since
+# it's more obvious and doesn't require -d. However, that adds an '// indirect'
+# comment on the requirement.
+go get m/use-indirect
+cmp go.mod go.mod.use
+cp go.mod.orig go.mod
+
+# We can also promote implicit requirements using 'go get' on them, or their
+# packages. This gives us "// indirect" requirements, since 'go get' doesn't
+# know they're needed by the main module. See #43131 for the rationale.
+# The hint above recommends this because it's more obvious usage and doesn't
+# require the -d flag.
+go get indirect-with-pkg indirect-without-pkg
+cmp go.mod go.mod.indirect
+
+-- go.mod.orig --
+module m
+
+go 1.16
+
+require direct v1.0.0
+
+replace (
+ direct v1.0.0 => ./direct
+ indirect-with-pkg v1.0.0 => ./indirect-with-pkg
+ indirect-without-pkg v1.0.0 => ./indirect-without-pkg
+)
+-- go.mod.use --
+module m
+
+go 1.16
+
+require (
+ direct v1.0.0
+ indirect-with-pkg v1.0.0
+)
+
+replace (
+ direct v1.0.0 => ./direct
+ indirect-with-pkg v1.0.0 => ./indirect-with-pkg
+ indirect-without-pkg v1.0.0 => ./indirect-without-pkg
+)
+-- go.mod.indirect --
+module m
+
+go 1.16
+
+require (
+ direct v1.0.0
+ indirect-with-pkg v1.0.0 // indirect
+ indirect-without-pkg v1.0.0 // indirect
+)
+
+replace (
+ direct v1.0.0 => ./direct
+ indirect-with-pkg v1.0.0 => ./indirect-with-pkg
+ indirect-without-pkg v1.0.0 => ./indirect-without-pkg
+)
+-- use-indirect/use-indirect.go --
+package use
+
+import _ "indirect-with-pkg"
+-- direct/go.mod --
+module direct
+
+go 1.16
+
+require (
+ indirect-with-pkg v1.0.0
+ indirect-without-pkg v1.0.0
+)
+-- indirect-with-pkg/go.mod --
+module indirect-with-pkg
+
+go 1.16
+-- indirect-with-pkg/p.go --
+package p
+-- indirect-without-pkg/go.mod --
+module indirect-without-pkg
+
+go 1.16
diff --git a/src/cmd/go/testdata/script/mod_get_pseudo.txt b/src/cmd/go/testdata/script/mod_get_pseudo.txt
new file mode 100644
index 0000000..47ad54e
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_pseudo.txt
@@ -0,0 +1,82 @@
+env GO111MODULE=on
+
+# Testing git->module converter's generation of +incompatible tags; turn off proxy.
+[!net:github.com] skip
+[!git] skip
+env GOPROXY=direct
+env GOSUMDB=off
+
+# We can resolve the @master branch without unshallowing the local repository
+# (even with older gits), so try that before we do anything else.
+# (This replicates https://golang.org/issue/26713 with git 2.7.4.)
+go get github.com/rsc/legacytest@master
+go list -m all
+stdout '^github.com/rsc/legacytest v2\.0\.1-0\.\d{14}-7303f7796364\+incompatible$'
+
+# get should include incompatible tags in "latest" calculation.
+go mod edit -droprequire github.com/rsc/legacytest
+go get github.com/rsc/legacytest@latest
+go list
+go list -m all
+stdout '^github.com/rsc/legacytest v2\.0\.0\+incompatible$'
+
+# v2.0.1-0.pseudo+incompatible
+go get ...test@7303f77
+go list -m all
+stdout '^github.com/rsc/legacytest v2\.0\.1-0\.\d{14}-7303f7796364\+incompatible$'
+
+# v2.0.0+incompatible by tag+incompatible
+go get ...test@v2.0.0+incompatible
+go list -m all
+stdout '^github.com/rsc/legacytest v2\.0\.0\+incompatible$'
+
+# v2.0.0+incompatible by tag
+go get ...test@v2.0.0
+go list -m all
+stdout '^github.com/rsc/legacytest v2\.0\.0\+incompatible$'
+
+# v2.0.0+incompatible by hash (back on master)
+go get ...test@d7ae1e4
+go list -m all
+stdout '^github.com/rsc/legacytest v2\.0\.0\+incompatible$'
+
+# v1.2.1-0.pseudo
+go get ...test@d2d4c3e
+go list -m all
+stdout '^github.com/rsc/legacytest v1\.2\.1-0\.\d{14}-d2d4c3ea6623$'
+
+# v1.2.0
+go get ...test@9f6f860
+go list -m all
+stdout '^github.com/rsc/legacytest v1\.2\.0$'
+
+# v1.1.0-pre.0.pseudo
+go get ...test@fb3c628
+go list -m all
+stdout '^github.com/rsc/legacytest v1\.1\.0-pre\.0\.\d{14}-fb3c628075e3$'
+
+# v1.1.0-pre (no longer on master)
+go get ...test@731e3b1
+go list -m all
+stdout '^github.com/rsc/legacytest v1\.1\.0-pre$'
+
+# v1.0.1-0.pseudo
+go get ...test@fa4f5d6
+go list -m all
+stdout '^github.com/rsc/legacytest v1\.0\.1-0\.\d{14}-fa4f5d6a71c6$'
+
+# v1.0.0
+go get ...test@7fff7f3
+go list -m all
+stdout '^github.com/rsc/legacytest v1\.0\.0$'
+
+# v0.0.0-pseudo
+go get ...test@52853eb
+go list -m all
+stdout '^github.com/rsc/legacytest v0\.0\.0-\d{14}-52853eb7b552$'
+
+-- go.mod --
+module x
+-- x.go --
+package x
+import "github.com/rsc/legacytest"
diff --git a/src/cmd/go/testdata/script/mod_get_pseudo_other_branch.txt b/src/cmd/go/testdata/script/mod_get_pseudo_other_branch.txt
new file mode 100644
index 0000000..6019b45
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_pseudo_other_branch.txt
@@ -0,0 +1,67 @@
+env GO111MODULE=on
+env GOPROXY=direct
+env GOSUMDB=off
+
+# Testing that a pseudo-version is based on the semantically-latest
+# tag that appears in any commit that is a (transitive) parent of the commit
+# supplied to 'go get', regardless of branches
+
+[short] skip
+[!git] skip
+
+# For this test repository:
+# tag v0.2.1 is most recent tag on master itself
+# tag v0.2.2 is on branch2, which was then merged to master
+# master is a merge commit with both tags as parents
+#
+# The pseudo-version hence sorts immediately after v0.2.2 rather
+# than v0.2.1, even though the v0.2.2 tag is not on master.
+
+go get vcs-test.golang.org/git/tagtests.git@master
+go list -m all
+stdout '^vcs-test.golang.org/git/tagtests.git v0.2.3-0\.'
+
+-- go.mod --
+module x
+
+go 1.12
+-- x.go --
+package x
+
+import _ "vcs-test.golang.org/git/tagtests.git"
+-- gen_testtags.sh --
+#!/bin/bash
+
+# This is not part of the test.
+# Run this to generate and update the repository on vcs-test.golang.org.
+
+set -euo pipefail
+cd "$(dirname "$0")"
+rm -rf tagtests
+mkdir tagtests
+cd tagtests
+
+git init
+echo module vcs-test.golang.org/git/tagtests.git >go.mod
+echo package tagtests >tagtests.go
+git add go.mod tagtests.go
+git commit -m 'create module tagtests'
+
+git branch b
+
+echo v0.2.1 >v0.2.1
+git add v0.2.1
+git commit -m v0.2.1
+git tag v0.2.1
+
+git checkout b
+echo v0.2.2 >v0.2.2
+git add v0.2.2
+git commit -m v0.2.2
+git tag v0.2.2
+
+git checkout master
+git merge b -m merge
+
+zip -r ../tagtests.zip .
+gsutil cp ../tagtests.zip gs://vcs-test/git/tagtests.zip
diff --git a/src/cmd/go/testdata/script/mod_get_pseudo_prefix.txt b/src/cmd/go/testdata/script/mod_get_pseudo_prefix.txt
new file mode 100644
index 0000000..ac3233e
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_pseudo_prefix.txt
@@ -0,0 +1,64 @@
+env GO111MODULE=on
+env GOPROXY=direct
+env GOSUMDB=off
+
+# Testing that a pseudo-version is based on the semantically-latest
+# prefixed tag in any commit that is a parent of the commit supplied
+# to 'go get', when using a repo with go.mod in a sub directory.
+
+[short] skip
+[!git] skip
+
+# For this test repository go.mod resides in sub/ (only):
+# master is not tagged
+# tag v0.2.0 is most recent tag before master
+# tag sub/v0.0.10 is most recent tag before v0.2.0
+#
+# The pseudo-version is based on sub/v0.0.10, since v0.2.0 doesn't
+# contain the prefix.
+go get vcs-test.golang.org/git/prefixtagtests.git/sub
+go list -m all
+stdout '^vcs-test.golang.org/git/prefixtagtests.git/sub v0.0.10$'
+
+go get -u vcs-test.golang.org/git/prefixtagtests.git/sub@master
+go list -m all
+stdout '^vcs-test.golang.org/git/prefixtagtests.git/sub v0.0.11-0\.'
+
+-- go.mod --
+module x
+
+go 1.12
+-- x.go --
+package x
+
+import _ "vcs-test.golang.org/prefixtagtests.git/sub"
+-- gen_prefixtagtests.sh --
+#!/bin/bash
+
+# This is not part of the test.
+# Run this to generate and update the repository on vcs-test.golang.org.
+
+set -euo pipefail
+cd "$(dirname "$0")"
+rm -rf prefixtagtests
+mkdir prefixtagtests
+cd prefixtagtests
+
+git init
+mkdir sub
+echo module vcs-test.golang.org/git/prefixtagtests.git/sub >sub/go.mod
+echo package sub >sub/sub.go
+git add sub
+git commit -m 'create module sub'
+for i in v0.1.0 sub/v0.0.9 sub/v0.0.10 v0.2.0; do
+ echo $i >status
+ git add status
+ git commit -m $i
+ git tag $i
+done
+echo 'after last tag' >status
+git add status
+git commit -m 'after last tag'
+
+zip -r ../prefixtagtests.zip .
+gsutil cp ../prefixtagtests.zip gs://vcs-test/git/prefixtagtests.zip
diff --git a/src/cmd/go/testdata/script/mod_get_replaced.txt b/src/cmd/go/testdata/script/mod_get_replaced.txt
new file mode 100644
index 0000000..c31d5be
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_replaced.txt
@@ -0,0 +1,111 @@
+cp go.mod go.mod.orig
+
+env oldGOPROXY=$GOPROXY
+
+# If a wildcard replacement exists for an otherwise-nonexistent module,
+# 'go get' should resolve it to the minimum valid pseudo-version.
+
+go mod edit -replace=example.com/x=./x
+go get example.com/x
+
+go list -m example.com/x
+stdout '^example.com/x v0.0.0-00010101000000-000000000000 '
+
+# If specific-version replacements exist, the highest matching version should be used.
+go mod edit -replace=example.com/x@v0.1.0=./x
+go mod edit -replace=example.com/x@v0.2.0=./x
+
+go get example.com/x
+go list -m example.com/x
+stdout '^example.com/x v0.2.0 '
+
+go get example.com/x@<v0.2.0
+go list -m example.com/x
+stdout '^example.com/x v0.1.0 '
+
+
+# The same should work with GOPROXY=off.
+
+env GOPROXY=off
+cp go.mod.orig go.mod
+
+go mod edit -replace=example.com/x=./x
+go get example.com/x
+
+go list -m example.com/x
+stdout '^example.com/x v0.0.0-00010101000000-000000000000 '
+
+# If specific-version replacements exist, the highest matching version should be used.
+go mod edit -replace=example.com/x@v0.1.0=./x
+go mod edit -replace=example.com/x@v0.2.0=./x
+
+go get example.com/x
+go list -m example.com/x
+stdout '^example.com/x v0.2.0 '
+
+go get example.com/x@<v0.2.0
+go list -m example.com/x
+stdout '^example.com/x v0.1.0 '
+
+
+# Replacements should also be listed as known versions, and 'go get' should sort
+# them in with ordinary versions.
+
+env GOPROXY=$oldGOPROXY
+
+cp go.mod.orig go.mod
+go list -versions -m rsc.io/quote
+stdout 'v1.3.0 v1.4.0'
+
+go get rsc.io/quote@v1.3
+go list -m rsc.io/quote
+stdout '^rsc.io/quote v1.3.0'
+
+go mod edit -replace rsc.io/quote@v1.3.1=rsc.io/quote@v1.4.0
+
+go list -versions -m rsc.io/quote
+stdout 'v1.3.0 v1.3.1 v1.4.0'
+
+go get rsc.io/quote@v1.3
+go list -m rsc.io/quote
+stdout '^rsc.io/quote v1.3.1 '
+
+go get rsc.io/quote@>v1.3.1
+go list -m rsc.io/quote
+stdout '^rsc.io/quote v1.4.0'
+
+
+# Replacements should allow 'go get' to work even with dotless module paths.
+
+cp go.mod.orig go.mod
+
+! go list example
+stderr '^package example is not in std \(.*\)$'
+! go get example
+stderr '^go: malformed module path "example": missing dot in first path element$'
+
+go mod edit -replace example@v0.1.0=./example
+
+! go list example
+stderr '^module example provides package example and is replaced but not required; to add it:\n\tgo get example@v0.1.0$'
+
+go get example
+go list -m example
+stdout '^example v0.1.0 '
+
+
+-- go.mod --
+module example.com
+
+go 1.16
+-- x/go.mod --
+module example.com/x
+
+go 1.16
+-- x/x.go --
+package x
+-- example/go.mod --
+module example
+go 1.16
+-- example/example.go --
+package example
diff --git a/src/cmd/go/testdata/script/mod_get_retract.txt b/src/cmd/go/testdata/script/mod_get_retract.txt
new file mode 100644
index 0000000..9757989
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_retract.txt
@@ -0,0 +1,59 @@
+# 'go get pkg' should not upgrade to a retracted version.
+cp go.mod.orig go.mod
+go mod edit -require example.com/retract/self/prev@v1.1.0
+go get example.com/retract/self/prev
+go list -m example.com/retract/self/prev
+stdout '^example.com/retract/self/prev v1.1.0$'
+
+# 'go get pkg' should not downgrade from a retracted version when no higher
+# version is available.
+cp go.mod.orig go.mod
+go mod edit -require example.com/retract/self/prev@v1.9.0
+go get example.com/retract/self/prev
+stderr '^go: warning: example.com/retract/self/prev@v1.9.0: retracted by module author: self$'
+stderr '^go: to switch to the latest unretracted version, run:\n\tgo get example.com/retract/self/prev@latest\n$'
+go list -m example.com/retract/self/prev
+stdout '^example.com/retract/self/prev v1.9.0$'
+
+# 'go get pkg@latest' should downgrade from a retracted version.
+cp go.mod.orig go.mod
+go mod edit -require example.com/retract/self/prev@v1.9.0
+go get example.com/retract/self/prev@latest
+go list -m example.com/retract/self/prev
+stdout '^example.com/retract/self/prev v1.1.0$'
+
+# 'go get pkg@version' should update to a specific version, even if that
+# version is retracted.
+cp go.mod.orig go.mod
+go get example.com/retract@v1.0.0-bad
+stderr '^go: warning: example.com/retract@v1.0.0-bad: retracted by module author: bad$'
+go list -m example.com/retract
+stdout '^example.com/retract v1.0.0-bad$'
+
+# 'go get -u' should not downgrade from a retracted version when no higher
+# version is available.
+cp go.mod.orig go.mod
+go mod edit -require example.com/retract/self/prev@v1.9.0
+go get -u ./use
+stderr '^go: warning: example.com/retract/self/prev@v1.9.0: retracted by module author: self$'
+go list -m example.com/retract/self/prev
+stdout '^example.com/retract/self/prev v1.9.0$'
+
+# 'go get' should warn if a module needed to build named packages is retracted.
+# 'go get' should not warn about unrelated modules.
+go get ./empty
+! stderr retracted
+go get ./use
+stderr '^go: warning: example.com/retract/self/prev@v1.9.0: retracted by module author: self$'
+
+-- go.mod.orig --
+module example.com/use
+
+go 1.15
+
+-- use/use.go --
+package use
+
+import _ "example.com/retract/self/prev"
+-- empty/empty.go --
+package empty
diff --git a/src/cmd/go/testdata/script/mod_get_retract_ambiguous.txt b/src/cmd/go/testdata/script/mod_get_retract_ambiguous.txt
new file mode 100644
index 0000000..4b4f5da
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_retract_ambiguous.txt
@@ -0,0 +1,10 @@
+! go get example.com/retract/ambiguous/other
+stderr 'ambiguous import: found package example.com/retract/ambiguous/nested in multiple modules:'
+stderr '^go: warning: example.com/retract/ambiguous/nested@v1.9.0-bad: retracted by module author: nested modules are bad$'
+
+-- go.mod --
+module example.com/use
+
+go 1.16
+
+require example.com/retract/ambiguous/nested v1.9.0-bad
diff --git a/src/cmd/go/testdata/script/mod_get_split.txt b/src/cmd/go/testdata/script/mod_get_split.txt
new file mode 100644
index 0000000..6c2f00d
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_split.txt
@@ -0,0 +1,157 @@
+cp go.mod go.mod.orig
+
+
+# 'go get' on a package already provided by the build list should update
+# the module already in the build list, not fail with an ambiguous import error.
+
+go get example.net/split/nested@patch
+go list -m all
+stdout '^example.net/split v0.2.1 '
+! stdout '^example.net/split/nested'
+
+# We should get the same behavior if we use a pattern that matches only that package.
+
+cp go.mod.orig go.mod
+
+go get example.net/split/nested/...@patch
+go list -m all
+stdout '^example.net/split v0.2.1 '
+! stdout '^example.net/split/nested'
+
+
+# If we request a version for which the package only exists in one particular module,
+# we should add that one particular module but not resolve import ambiguities.
+#
+# In particular, if the module that previously provided the package has a
+# matching version, but does not itself match the pattern and contains no
+# matching packages, we should not change its version. (We should *not* downgrade
+# module example.net/split to v0.1.0, despite the fact that
+# example.net/split v0.2.0 currently provides the package with the requested path.)
+#
+# TODO(#27899): Maybe we should resolve the ambiguities by upgrading.
+
+cp go.mod.orig go.mod
+
+! go get example.net/split/nested@v0.1.0
+stderr '^go: example.net/split/nested: ambiguous import: found package example.net/split/nested in multiple modules:\n\texample.net/split v0.2.0 \(.*split.2[/\\]nested\)\n\texample.net/split/nested v0.1.0 \(.*nested.1\)$'
+
+# A wildcard that matches packages in some module at its selected version
+# but not at the requested version should fail.
+#
+# We can't set the module to the selected version, because that version doesn't
+# even match the query: if we ran the same query twice, we wouldn't consider the
+# module to match the wildcard during the second call, so why should we consider
+# it to match during the first one? ('go get' should be idempotent, and if we
+# did that then it would not be.)
+#
+# But we also can't leave it where it is: the user requested that we set everything
+# matching the pattern to the given version, and right now we have packages
+# that match the pattern but *not* the version.
+#
+# That only leaves two options: we can set the module to an arbitrary version
+# (perhaps 'latest' or 'none'), or we can report an error and the let the user
+# disambiguate. We would rather not choose arbitrarily, so we do the latter.
+#
+# TODO(#27899): Should we instead upgrade or downgrade to an arbitrary version?
+
+! go get example.net/split/nested/...@v0.1.0
+stderr '^go: example.net/split/nested/\.\.\.@v0.1.0 matches packages in example.net/split@v0.2.0 but not example.net/split@v0.1.0: specify a different version for module example.net/split$'
+
+cmp go.mod go.mod.orig
+
+
+# If another argument resolves the ambiguity, we should be ok again.
+
+go get example.net/split@none example.net/split/nested@v0.1.0
+go list -m all
+! stdout '^example.net/split '
+stdout '^example.net/split/nested v0.1.0 '
+
+cp go.mod.orig go.mod
+
+go get example.net/split@v0.3.0 example.net/split/nested@v0.1.0
+go list -m all
+stdout '^example.net/split v0.3.0 '
+stdout '^example.net/split/nested v0.1.0 '
+
+
+# If a pattern applies to modules and to packages, we should set all matching
+# modules to the version indicated by the pattern, and also resolve packages
+# to match the pattern if possible.
+
+cp go.mod.orig go.mod
+go get example.net/split/nested@v0.0.0
+
+go get example.net/...@v0.1.0
+go list -m all
+stdout '^example.net/split v0.1.0 '
+stdout '^example.net/split/nested v0.1.0 '
+
+go get example.net/...
+go list -m all
+stdout '^example.net/split v0.3.0 '
+stdout '^example.net/split/nested v0.2.0 '
+
+
+# @none applies to all matching module paths,
+# regardless of whether they contain any packages.
+
+go get example.net/...@none
+go list -m all
+! stdout '^example.net'
+
+# Starting from no dependencies, a wildcard can resolve to an empty module with
+# the same prefix even if it contains no packages.
+
+go get example.net/...@none
+go get example.net/split/...@v0.1.0
+go list -m all
+stdout '^example.net/split v0.1.0 '
+
+
+-- go.mod --
+module m
+
+go 1.16
+
+require example.net/split v0.2.0
+
+replace (
+ example.net/split v0.1.0 => ./split.1
+ example.net/split v0.2.0 => ./split.2
+ example.net/split v0.2.1 => ./split.2
+ example.net/split v0.3.0 => ./split.3
+ example.net/split/nested v0.0.0 => ./nested.0
+ example.net/split/nested v0.1.0 => ./nested.1
+ example.net/split/nested v0.2.0 => ./nested.2
+)
+-- split.1/go.mod --
+module example.net/split
+
+go 1.16
+-- split.2/go.mod --
+module example.net/split
+
+go 1.16
+-- split.2/nested/nested.go --
+package nested
+-- split.3/go.mod --
+module example.net/split
+
+go 1.16
+-- nested.0/go.mod --
+module example.net/split/nested
+
+go 1.16
+-- nested.1/go.mod --
+module example.net/split/nested
+
+go 1.16
+-- nested.1/nested.go --
+package nested
+-- nested.2/go.mod --
+module example.net/split/nested
+
+go 1.16
+-- nested.2/nested.go --
+package nested
diff --git a/src/cmd/go/testdata/script/mod_get_sum_noroot.txt b/src/cmd/go/testdata/script/mod_get_sum_noroot.txt
new file mode 100644
index 0000000..0d9a840
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_sum_noroot.txt
@@ -0,0 +1,11 @@
+# When 'go get' is invoked on a module without a package in the root directory,
+# it should add sums for the module's go.mod file and its content to go.sum.
+# Verifies golang.org/issue/41103.
+go mod init m
+go get rsc.io/QUOTE
+grep '^rsc.io/QUOTE v1.5.2/go.mod ' go.sum
+grep '^rsc.io/QUOTE v1.5.2 ' go.sum
+
+# Double-check rsc.io/QUOTE does not have a root package.
+! go list -mod=readonly rsc.io/QUOTE
+stderr '^cannot find module providing package rsc.io/QUOTE: import lookup disabled by -mod=readonly$'
diff --git a/src/cmd/go/testdata/script/mod_get_tags.txt b/src/cmd/go/testdata/script/mod_get_tags.txt
new file mode 100644
index 0000000..e4fb6c4
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_tags.txt
@@ -0,0 +1,34 @@
+env GO111MODULE=on
+
+# get should add modules needed to build packages, even if those
+# dependencies are in sources excluded by build tags.
+# All build tags are considered true except "ignore".
+go mod init m
+go get .
+go list -m all
+stdout 'example.com/version v1.1.0'
+stdout 'rsc.io/quote v1.5.2'
+
+-- empty.go --
+package m
+
+-- excluded.go --
+// +build windows,mips
+
+package m
+
+import _ "example.com/version"
+
+-- tools.go --
+// +build tools
+
+package tools
+
+import _ "rsc.io/quote"
+
+-- ignore.go --
+// +build ignore
+
+package ignore
+
+import _ "example.com/doesnotexist"
diff --git a/src/cmd/go/testdata/script/mod_get_test.txt b/src/cmd/go/testdata/script/mod_get_test.txt
new file mode 100644
index 0000000..0fa7cd9
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_test.txt
@@ -0,0 +1,58 @@
+env GO111MODULE=on
+
+# By default, 'go get' should ignore tests
+cp go.mod.empty go.mod
+go get m/a
+! grep rsc.io/quote go.mod
+
+# 'go get -t' should consider test dependencies of the named package.
+cp go.mod.empty go.mod
+go get -t m/a
+grep 'rsc.io/quote v1.5.2$' go.mod
+
+# 'go get -t' should not consider test dependencies of imported packages,
+# including packages imported from tests.
+cp go.mod.empty go.mod
+go get -t m/b
+! grep rsc.io/quote go.mod
+
+# 'go get -t -u' should update test dependencies of the named package.
+cp go.mod.empty go.mod
+go mod edit -require=rsc.io/quote@v1.5.1
+go get -t -u m/a
+grep 'rsc.io/quote v1.5.2$' go.mod
+
+# 'go get -t -u' should not add or update test dependencies
+# of imported packages, including packages imported from tests.
+cp go.mod.empty go.mod
+go get -t -u m/b
+! grep rsc.io/quote go.mod
+go mod edit -require=rsc.io/quote@v1.5.1
+go get -t -u m/b
+grep 'rsc.io/quote v1.5.1$' go.mod
+
+# 'go get all' should consider test dependencies with or without -t.
+cp go.mod.empty go.mod
+go get all
+grep 'rsc.io/quote v1.5.2$' go.mod
+
+-- go.mod.empty --
+module m
+
+-- a/a.go --
+package a
+
+-- a/a_test.go --
+package a_test
+
+import _ "rsc.io/quote"
+
+-- b/b.go --
+package b
+
+import _ "m/a"
+
+-- b/b_test.go --
+package b_test
+
+import _ "m/a"
diff --git a/src/cmd/go/testdata/script/mod_get_toolchain.txt b/src/cmd/go/testdata/script/mod_get_toolchain.txt
new file mode 100644
index 0000000..758142d
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_toolchain.txt
@@ -0,0 +1,129 @@
+# setup
+env TESTGO_VERSION=go1.99rc1
+env TESTGO_VERSION_SWITCH=switch
+
+# go get go should use the latest Go 1.23
+cp go.mod.orig go.mod
+go get go
+stderr '^go: upgraded go 1.21 => 1.23.9$'
+grep 'go 1.23.9' go.mod
+grep 'toolchain go1.99rc1' go.mod
+
+# go get go@1.23 should use the latest Go 1.23
+cp go.mod.orig go.mod
+go get go@1.23
+stderr '^go: upgraded go 1.21 => 1.23.9$'
+grep 'go 1.23.9' go.mod
+grep 'toolchain go1.99rc1' go.mod
+
+# go get go@1.22 should use the latest Go 1.22
+cp go.mod.orig go.mod
+go get go@1.22
+stderr '^go: upgraded go 1.21 => 1.22.9$'
+grep 'go 1.22.9' go.mod
+grep 'toolchain go1.99rc1' go.mod
+
+# go get go@patch should use the latest patch release
+go get go@1.22.1
+go get go@patch
+stderr '^go: upgraded go 1.22.1 => 1.22.9$'
+grep 'go 1.22.9' go.mod
+grep 'toolchain go1.99rc1' go.mod
+
+# go get go@1.24 does NOT find the release candidate
+cp go.mod.orig go.mod
+! go get go@1.24
+stderr '^go: go@1.24: no matching versions for query "1.24"$'
+
+# go get go@1.24rc1 works
+cp go.mod.orig go.mod
+go get go@1.24rc1
+stderr '^go: upgraded go 1.21 => 1.24rc1$'
+grep 'go 1.24rc1' go.mod
+grep 'toolchain go1.99rc1' go.mod
+
+# go get go@latest finds the latest Go 1.23
+cp go.mod.orig go.mod
+go get go@latest
+stderr '^go: upgraded go 1.21 => 1.23.9$'
+grep 'go 1.23.9' go.mod
+grep 'toolchain go1.99rc1' go.mod
+
+# Again, with toolchains.
+
+# go get toolchain should find go1.999testmod.
+go get toolchain
+stderr '^go: upgraded toolchain go1.99rc1 => go1.999testmod$'
+grep 'go 1.23.9' go.mod
+grep 'toolchain go1.999testmod' go.mod
+
+# go get toolchain@go1.23 should use the latest Go 1.23
+go get toolchain@go1.23
+stderr '^go: removed toolchain go1.999testmod$'
+grep 'go 1.23.9' go.mod
+! grep 'toolchain go1.23.9' go.mod # implied
+
+# go get toolchain@go1.22 should use the latest Go 1.22 and downgrade go.
+go get toolchain@go1.22
+stderr '^go: downgraded go 1.23.9 => 1.22.9$'
+grep 'go 1.22.9' go.mod
+! grep 'toolchain go1.22.9' go.mod # implied
+
+# go get toolchain@patch should use the latest patch release
+go get toolchain@go1.22.1
+go get toolchain@patch
+stderr '^go: added toolchain go1.22.9$'
+grep 'go 1.22.1' go.mod
+grep 'toolchain go1.22.9' go.mod
+go get go@1.22.9 toolchain@none
+grep 'go 1.22.9' go.mod
+! grep 'toolchain go1.22.9' go.mod
+
+# go get toolchain@go1.24 does NOT find the release candidate
+! go get toolchain@go1.24
+stderr '^go: toolchain@go1.24: no matching versions for query "go1.24"$'
+
+# go get toolchain@go1.24rc1 works
+go get toolchain@go1.24rc1
+stderr '^go: added toolchain go1.24rc1$'
+grep 'go 1.22.9' go.mod # no longer implied
+grep 'toolchain go1.24rc1' go.mod
+
+# go get toolchain@latest finds go1.999testmod.
+cp go.mod.orig go.mod
+go get toolchain@latest
+stderr '^go: added toolchain go1.999testmod$'
+grep 'go 1.21' go.mod
+grep 'toolchain go1.999testmod' go.mod
+
+# Bug fixes.
+
+# go get go@garbage should fail but not crash
+! go get go@garbage
+! stderr panic
+stderr '^go: invalid go version garbage$'
+
+# go get go@go1.21.0 is OK - we silently correct to 1.21.0
+go get go@1.19
+go get go@go1.21.0
+stderr '^go: upgraded go 1.19 => 1.21.0'
+
+# go get toolchain@1.24rc1 is OK too.
+go get toolchain@1.24rc1
+stderr '^go: downgraded toolchain go1.999testmod => go1.24rc1$'
+
+# go get go@1.21 should work if we are the Go 1.21 language version,
+# even though there's no toolchain for it.
+# (Older versions resolve to the latest release in that version, so for example
+# go get go@1.20 might resolve to 1.20.9, but if we're the devel copy of
+# Go 1.21, there's no release yet to resolve to, so we resolve to ourselves.)
+env TESTGO_VERSION=go1.21
+go get go@1.19 toolchain@none
+go get go@1.21
+grep 'go 1.21$' go.mod
+! grep toolchain go.mod
+
+-- go.mod.orig --
+module m
+
+go 1.21
diff --git a/src/cmd/go/testdata/script/mod_get_trailing_slash.txt b/src/cmd/go/testdata/script/mod_get_trailing_slash.txt
new file mode 100644
index 0000000..7b46900
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_trailing_slash.txt
@@ -0,0 +1,30 @@
+# go list should succeed to load a package ending with ".go" if the path does
+# not correspond to an existing local file. Listing a pattern ending with
+# ".go/" should try to list a package regardless of whether a file exists at the
+# path without the suffixed "/" or not.
+go list example.com/dotgo.go
+stdout ^example.com/dotgo.go$
+go list example.com/dotgo.go/
+stdout ^example.com/dotgo.go$
+
+# go get should succeed in either case, with or without a version.
+# Arguments are interpreted as packages or package patterns with versions,
+# not source files.
+go get example.com/dotgo.go
+go get example.com/dotgo.go/
+go get example.com/dotgo.go@v1.0.0
+go get example.com/dotgo.go/@v1.0.0
+
+-- go.mod --
+module m
+
+go 1.13
+
+require example.com/dotgo.go v1.0.0
+-- go.sum --
+example.com/dotgo.go v1.0.0 h1:XKJfs0V8x2PvY2tX8bJBCEbCDLnt15ma2onwhVpew/I=
+example.com/dotgo.go v1.0.0/go.mod h1:Qi6z/X3AC5vHiuMt6HF2ICx3KhIBGrMdrA7YoPDKqR0=
+-- use.go --
+package use
+
+import _ "example.com/dotgo.go"
diff --git a/src/cmd/go/testdata/script/mod_get_update_unrelated_sum.txt b/src/cmd/go/testdata/script/mod_get_update_unrelated_sum.txt
new file mode 100644
index 0000000..a5651e9
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_update_unrelated_sum.txt
@@ -0,0 +1,120 @@
+# Check that 'go get' adds sums for updated modules if we had sums before,
+# even if we didn't load packages from them.
+# Verifies #44129.
+
+env fmt='{{.ImportPath}}: {{if .Error}}{{.Error.Err}}{{else}}ok{{end}}'
+
+# Control case: before upgrading, we have the sums we need.
+# go list -deps -e -f $fmt .
+# stdout '^rsc.io/quote: ok$'
+# ! stdout rsc.io/sampler # not imported by quote in this version
+cp go.mod.orig go.mod
+cp go.sum.orig go.sum
+go mod tidy
+cmp go.mod.orig go.mod
+cmp go.sum.orig go.sum
+
+
+# Upgrade a module. This also upgrades rsc.io/quote, and though we didn't load
+# a package from it, we had the sum for its old version, so we need the
+# sum for the new version, too.
+go get example.com/upgrade@v0.0.2
+grep '^rsc.io/quote v1.5.2 ' go.sum
+
+# The upgrade still breaks the build because the new version of quote imports
+# rsc.io/sampler, and we don't have its zip sum.
+go list -deps -e -f $fmt
+stdout 'rsc.io/quote: ok'
+stdout 'rsc.io/sampler: missing go.sum entry for module providing package rsc.io/sampler'
+cp go.mod.orig go.mod
+cp go.sum.orig go.sum
+
+
+# Replace the old version with a directory before upgrading.
+# We didn't need a sum for it before (even though we had one), so we won't
+# fetch a new sum.
+go mod edit -replace rsc.io/quote@v1.0.0=./dummy
+go get example.com/upgrade@v0.0.2
+! grep '^rsc.io/quote v1.5.2 ' go.sum
+cp go.mod.orig go.mod
+cp go.sum.orig go.sum
+
+
+# Replace the new version with a directory before upgrading.
+# We can't get a sum for a directory.
+go mod edit -replace rsc.io/quote@v1.5.2=./dummy
+go get example.com/upgrade@v0.0.2
+! grep '^rsc.io/quote v1.5.2 ' go.sum
+cp go.mod.orig go.mod
+cp go.sum.orig go.sum
+
+
+# Replace the new version with a different version.
+# We should get a sum for that version.
+go mod edit -replace rsc.io/quote@v1.5.2=rsc.io/quote@v1.5.1
+go get example.com/upgrade@v0.0.2
+! grep '^rsc.io/quote v1.5.2 ' go.sum
+grep '^rsc.io/quote v1.5.1 ' go.sum
+cp go.mod.orig go.mod
+cp go.sum.orig go.sum
+
+
+# Delete the new version's zip (but not mod) from the cache and go offline.
+# 'go get' should fail when fetching the zip.
+rm $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip
+env GOPROXY=off
+! go get example.com/upgrade@v0.0.2
+stderr '^go: upgraded rsc.io/quote v1.0.0 => v1.5.2: error finding sum for rsc.io/quote@v1.5.2: module lookup disabled by GOPROXY=off$'
+
+-- go.mod.orig --
+module m
+
+go 1.16
+
+require (
+ example.com/upgrade v0.0.1
+ rsc.io/quote v1.0.0
+)
+
+replace (
+ example.com/upgrade v0.0.1 => ./upgrade1
+ example.com/upgrade v0.0.2 => ./upgrade2
+)
+-- go.sum.orig --
+rsc.io/quote v1.0.0 h1:kQ3IZQzPTiDJxSZI98YaWgxFEhlNdYASHvh+MplbViw=
+rsc.io/quote v1.0.0/go.mod h1:v83Ri/njykPcgJltBc/gEkJTmjTsNgtO1Y7vyIK1CQA=
+-- go.sum.want --
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+rsc.io/quote v1.0.0 h1:kQ3IZQzPTiDJxSZI98YaWgxFEhlNdYASHvh+MplbViw=
+rsc.io/quote v1.0.0/go.mod h1:v83Ri/njykPcgJltBc/gEkJTmjTsNgtO1Y7vyIK1CQA=
+rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0=
+rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+-- use.go --
+package use
+
+import (
+ _ "example.com/upgrade"
+ _ "rsc.io/quote"
+)
+-- upgrade1/go.mod --
+module example.com/upgrade
+
+go 1.16
+-- upgrade1/upgrade.go --
+package upgrade
+-- upgrade2/go.mod --
+module example.com/upgrade
+
+go 1.16
+
+require rsc.io/quote v1.5.2 // indirect
+-- upgrade2/upgrade.go --
+package upgrade
+-- dummy/go.mod --
+module rsc.io/quote
+
+go 1.16
+-- dummy/quote.go --
+package quote
+
diff --git a/src/cmd/go/testdata/script/mod_get_upgrade.txt b/src/cmd/go/testdata/script/mod_get_upgrade.txt
new file mode 100644
index 0000000..51d5990
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_upgrade.txt
@@ -0,0 +1,46 @@
+env GO111MODULE=on
+
+go get rsc.io/quote@v1.5.1
+go list -m all
+stdout 'rsc.io/quote v1.5.1'
+grep 'rsc.io/quote v1.5.1$' go.mod
+
+# get -u should update dependencies of the package in the current directory
+go get -u
+grep 'rsc.io/quote v1.5.2$' go.mod
+grep 'golang.org/x/text [v0-9a-f\.-]+ // indirect' go.mod
+
+# get -u rsc.io/sampler should update only sampler's dependencies
+cp go.mod-v1.5.1 go.mod
+go get -u rsc.io/sampler
+grep 'rsc.io/quote v1.5.1$' go.mod
+grep 'golang.org/x/text [v0-9a-f\.-]+ // indirect' go.mod
+
+# move to a pseudo-version after any tags
+go get rsc.io/quote@dd9747d
+grep 'rsc.io/quote v0.0.0-20180628003336-dd9747d19b04' go.mod
+
+# get -u should not jump off newer pseudo-version to earlier tag
+go get -u
+grep 'rsc.io/quote v0.0.0-20180628003336-dd9747d19b04' go.mod
+
+# move to earlier pseudo-version
+go get rsc.io/quote@e7a685a342
+grep 'rsc.io/quote v0.0.0-20180214005133-e7a685a342c0' go.mod
+
+# get -u should jump off earlier pseudo-version to newer tag
+go get -u
+grep 'rsc.io/quote v1.5.2' go.mod
+
+-- go.mod --
+module x
+require rsc.io/quote v1.1.0
+
+-- go.mod-v1.5.1 --
+module x
+require rsc.io/quote v1.5.1
+
+-- use.go --
+package use
+
+import _ "rsc.io/quote"
diff --git a/src/cmd/go/testdata/script/mod_get_upgrade_pseudo.txt b/src/cmd/go/testdata/script/mod_get_upgrade_pseudo.txt
new file mode 100644
index 0000000..deff935
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_upgrade_pseudo.txt
@@ -0,0 +1,70 @@
+env GO111MODULE=on
+
+# For this test module there are three versions:
+# * v0.1.1-0.20190429073117-b5426c86b553
+# * v0.1.0
+# * v0.0.0-20190430073000-30950c05d534
+# Only v0.1.0 is tagged.
+#
+# The v0.1.1 pseudo-version is semantically higher than the latest tag.
+# The v0.0.0 pseudo-version is chronologically newer.
+
+# Start at v0.1.1-0.20190429073117-b5426c86b553
+go get example.com/pseudoupgrade@b5426c8
+go list -m -u all
+stdout '^example.com/pseudoupgrade v0.1.1-0.20190429073117-b5426c86b553$'
+
+# 'get -u' should not downgrade to the (lower) tagged version.
+go get -u
+go list -m -u all
+stdout '^example.com/pseudoupgrade v0.1.1-0.20190429073117-b5426c86b553$'
+
+# 'get example.com/pseudoupgrade@upgrade' should not downgrade.
+go get example.com/pseudoupgrade@upgrade
+go list -m all
+stdout '^example.com/pseudoupgrade v0.1.1-0.20190429073117-b5426c86b553$'
+
+# 'get example.com/pseudoupgrade' should not downgrade.
+# This is equivalent to 'get example.com/pseudoupgrade@upgrade'.
+go get example.com/pseudoupgrade
+go list -m all
+stdout '^example.com/pseudoupgrade v0.1.1-0.20190429073117-b5426c86b553$'
+
+# 'get example.com/pseudoupgrade@latest' should downgrade.
+# @latest should not consider the current version.
+go get example.com/pseudoupgrade@latest
+go list -m all
+stdout '^example.com/pseudoupgrade v0.1.0$'
+
+# We should observe the same behavior with the newer pseudo-version.
+go get example.com/pseudoupgrade@v0.0.0-20190430073000-30950c05d534
+
+# 'get -u' should not downgrade to the chronologically older tagged version.
+go get -u
+go list -m -u all
+stdout '^example.com/pseudoupgrade v0.0.0-20190430073000-30950c05d534$'
+
+# 'get example.com/pseudoupgrade@upgrade should not downgrade.
+go get example.com/pseudoupgrade@upgrade
+go list -m -u all
+stdout '^example.com/pseudoupgrade v0.0.0-20190430073000-30950c05d534$'
+
+# 'get example.com/pseudoupgrade' should not downgrade.
+go get example.com/pseudoupgrade
+go list -m -u all
+stdout '^example.com/pseudoupgrade v0.0.0-20190430073000-30950c05d534$'
+
+# 'get example.com/pseudoupgrade@latest' should downgrade.
+go get example.com/pseudoupgrade@latest
+go list -m -u all
+stdout '^example.com/pseudoupgrade v0.1.0$'
+
+-- go.mod --
+module x
+
+go 1.12
+
+-- main.go --
+package x
+
+import _ "example.com/pseudoupgrade"
diff --git a/src/cmd/go/testdata/script/mod_get_wild.txt b/src/cmd/go/testdata/script/mod_get_wild.txt
new file mode 100644
index 0000000..06f9973
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_wild.txt
@@ -0,0 +1,95 @@
+# This test covers a crazy edge-case involving wildcards and multiple passes of
+# patch-upgrades, but if we get it right we probably get many other edge-cases
+# right too.
+
+go list -m all
+stdout '^example.net/a v0.1.0 '
+! stdout '^example.net/b '
+
+
+# Requesting pattern example.../b by itself fails: there is no such module
+# already in the build list, and the wildcard in the first element prevents us
+# from attempting to resolve a new module whose path is a prefix of the pattern.
+
+! go get -u=patch example.../b@upgrade
+stderr '^go: no modules to query for example\.\.\./b@upgrade because first path element contains a wildcard$'
+
+
+# Patching . causes a patch to example.net/a, which introduces a new match
+# for example.net/b/..., which is itself patched and causes another upgrade to
+# example.net/a, which is then patched again.
+
+go get -u=patch . example.../b@upgrade
+go list -m all
+stdout '^example.net/a v0.2.1 ' # upgraded by dependency of b and -u=patch
+stdout '^example.net/b v0.2.0 ' # introduced by patch of a and upgraded by wildcard
+
+
+-- go.mod --
+module example
+
+go 1.16
+
+require example.net/a v0.1.0
+
+replace (
+ example.net/a v0.1.0 => ./a10
+ example.net/a v0.1.1 => ./a11
+ example.net/a v0.2.0 => ./a20
+ example.net/a v0.2.1 => ./a20
+ example.net/b v0.1.0 => ./b1
+ example.net/b v0.1.1 => ./b1
+ example.net/b v0.2.0 => ./b2
+)
+-- example.go --
+package example
+
+import _ "example.net/a"
+
+-- a10/go.mod --
+module example.net/a
+
+go 1.16
+-- a10/a.go --
+package a
+
+-- a11/go.mod --
+module example.net/a
+
+go 1.16
+
+require example.net/b v0.1.0
+-- a11/a.go --
+package a
+-- a11/unimported/unimported.go --
+package unimported
+
+import _ "example.net/b"
+
+
+-- a20/go.mod --
+module example.net/a
+
+go 1.16
+-- a20/a.go --
+package a
+
+-- b1/go.mod --
+module example.net/b
+
+go 1.16
+-- b1/b.go --
+package b
+
+-- b2/go.mod --
+module example.net/b
+
+go 1.16
+
+require example.net/a v0.2.0
+-- b2/b.go --
+package b
+-- b2/b_test.go --
+package b_test
+
+import _ "example.net/a"
diff --git a/src/cmd/go/testdata/script/mod_getmode_vendor.txt b/src/cmd/go/testdata/script/mod_getmode_vendor.txt
new file mode 100644
index 0000000..aaf526b
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_getmode_vendor.txt
@@ -0,0 +1,31 @@
+env GO111MODULE=on
+
+go get rsc.io/quote@v1.5.1
+go mod vendor
+env GOPATH=$WORK/empty
+env GOPROXY=file:///nonexist
+
+go list -mod=vendor
+go list -mod=vendor -f '{{with .Module}}{{.Path}} {{.Version}}{{end}} {{.Dir}}' all
+stdout '^rsc.io/quote v1.5.1 .*vendor[\\/]rsc.io[\\/]quote$'
+stdout '^golang.org/x/text v0.0.0.* .*vendor[\\/]golang.org[\\/]x[\\/]text[\\/]language$'
+
+! go list -mod=vendor -m rsc.io/quote@latest
+stderr 'go: rsc.io/quote@latest: cannot query module due to -mod=vendor'
+! go get -mod=vendor -u
+stderr 'flag provided but not defined: -mod'
+
+# Since we don't have a complete module graph, 'go list -m' queries
+# that require the complete graph should fail with a useful error.
+! go list -mod=vendor -m all
+stderr 'go: can''t compute ''all'' using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)'
+! go list -mod=vendor -m ...
+stderr 'go: can''t match module patterns using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)'
+
+-- go.mod --
+module x
+
+go 1.16
+-- x.go --
+package x
+import _ "rsc.io/quote"
diff --git a/src/cmd/go/testdata/script/mod_getx.txt b/src/cmd/go/testdata/script/mod_getx.txt
new file mode 100644
index 0000000..46bb95b
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_getx.txt
@@ -0,0 +1,18 @@
+[!net:golang.org] skip
+[!git] skip
+
+env GO111MODULE=on
+env GOPROXY=direct
+env GOSUMDB=off
+
+# 'go get -x' should log URLs with an HTTP or HTTPS scheme.
+# A bug had caused us to log schemeless URLs instead.
+go get -x golang.org/x/text@v0.1.0
+stderr '^# get https://golang.org/x/text\?go-get=1$'
+stderr '^# get https://golang.org/x/text\?go-get=1: 200 OK \([0-9.]+s\)$'
+! stderr '^# get //.*'
+
+-- go.mod --
+module m
+
+go 1.18
diff --git a/src/cmd/go/testdata/script/mod_git_export_subst.txt b/src/cmd/go/testdata/script/mod_git_export_subst.txt
new file mode 100644
index 0000000..740ccbd
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_git_export_subst.txt
@@ -0,0 +1,21 @@
+env GO111MODULE=on
+env GOPROXY=direct
+
+# Testing that git export-subst is disabled
+[!net:github.com] skip
+[!git] skip
+go build
+
+-- x.go --
+package x
+
+import _ "github.com/jasonkeene/export-subst"
+
+-- go.mod --
+module x
+
+require github.com/jasonkeene/export-subst v0.0.0-20180927204031-5845945ec626
+
+-- go.sum --
+github.com/jasonkeene/export-subst v0.0.0-20180927204031-5845945ec626 h1:AUkXi/xFnm7lH2pgtvVkGb7buRn1ywFHw+xDpZ29Rz0=
+github.com/jasonkeene/export-subst v0.0.0-20180927204031-5845945ec626/go.mod h1:DwJXqVtrgrQkv3Giuf2Jh4YyubVe7y41S1eOIaysTJw=
diff --git a/src/cmd/go/testdata/script/mod_go_version.txt b/src/cmd/go/testdata/script/mod_go_version.txt
new file mode 100644
index 0000000..82b55d8
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_go_version.txt
@@ -0,0 +1,29 @@
+# Test support for declaring needed Go version in module.
+
+env GO111MODULE=on
+env TESTGO_VERSION=go1.21
+
+! go list
+stderr -count=1 '^go: sub@v1.0.0: module ./sub requires go >= 1.999 \(running go 1.21\)$'
+! go build sub
+stderr -count=1 '^go: sub@v1.0.0: module ./sub requires go >= 1.999 \(running go 1.21\)$'
+
+-- go.mod --
+module m
+go 1.1
+require (
+ sub v1.0.0
+)
+replace (
+ sub => ./sub
+)
+
+-- x.go --
+package x
+
+-- sub/go.mod --
+module sub
+go 1.999
+
+-- sub/x.go --
+package x
diff --git a/src/cmd/go/testdata/script/mod_go_version_missing.txt b/src/cmd/go/testdata/script/mod_go_version_missing.txt
new file mode 100644
index 0000000..e9a8e72
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_go_version_missing.txt
@@ -0,0 +1,122 @@
+cp go.mod go.mod.orig
+
+# For modules whose go.mod file does not include a 'go' directive,
+# we assume the language and dependency semantics of Go 1.16,
+# but do not trigger “automatic vendoring” mode (-mod=vendor),
+# which was added in Go 1.14 and was not triggered
+# under the same conditions in Go 1.16 (which would instead
+# default to -mod=readonly when no 'go' directive is present).
+
+# For Go 1.16 modules, 'all' should prune out dependencies of tests,
+# even if the 'go' directive is missing.
+
+go list -mod=readonly all
+stdout '^example.com/dep$'
+! stdout '^example.com/testdep$'
+cp stdout list-1.txt
+cmp go.mod go.mod.orig
+
+# We should only default to -mod=vendor if the 'go' directive is explicit in the
+# go.mod file. Otherwise, we don't actually know whether the module was written
+# against Go 1.11 or 1.16. We would have to update the go.mod file to clarify,
+# and as of Go 1.16 we don't update the go.mod file by default.
+#
+# If we set -mod=vendor explicitly, we shouldn't apply the Go 1.14
+# consistency check, because — again — we don't know whether we're in a 1.11
+# module or a bad-script-edited 1.16 module.
+
+! go list -mod=vendor all
+! stderr '^go: inconsistent vendoring'
+stderr 'cannot find module providing package example.com/badedit: import lookup disabled by -mod=vendor'
+
+# When we set -mod=mod, the go version should be updated immediately,
+# to the current version, converting the requirements from eager to lazy.
+#
+# Since we don't know which requirements are actually relevant to the main
+# module, all requirements are added as roots, making the requirements untidy.
+
+go list -mod=mod all
+! stdout '^example.com/testdep$'
+cmp stdout list-1.txt
+cmpenv go.mod go.mod.untidy
+
+go mod tidy
+cmpenv go.mod go.mod.tidy
+
+# On the other hand, if we jump straight to 'go mod tidy',
+# the requirements remain tidy from the start.
+
+cp go.mod.orig go.mod
+go mod tidy
+cmpenv go.mod go.mod.tidy
+
+
+# The updated version should have been written back to go.mod, so now the 'go'
+# directive is explicit. -mod=vendor should trigger by default, and the stronger
+# Go 1.14 consistency check should apply.
+! go list all
+stderr '^go: inconsistent vendoring'
+! stderr badedit
+
+
+-- go.mod --
+module example.com/m
+
+require example.com/dep v0.1.0
+
+replace (
+ example.com/dep v0.1.0 => ./dep
+ example.com/testdep v0.1.0 => ./testdep
+)
+-- go.mod.untidy --
+module example.com/m
+
+go $goversion
+
+require example.com/dep v0.1.0
+
+require example.com/testdep v0.1.0 // indirect
+
+replace (
+ example.com/dep v0.1.0 => ./dep
+ example.com/testdep v0.1.0 => ./testdep
+)
+-- go.mod.tidy --
+module example.com/m
+
+go $goversion
+
+require example.com/dep v0.1.0
+
+replace (
+ example.com/dep v0.1.0 => ./dep
+ example.com/testdep v0.1.0 => ./testdep
+)
+-- vendor/example.com/dep/dep.go --
+package dep
+import _ "example.com/badedit"
+-- vendor/modules.txt --
+HAHAHA this is broken.
+
+-- m.go --
+package m
+
+import _ "example.com/dep"
+
+const x = 1_000
+
+-- dep/go.mod --
+module example.com/dep
+
+require example.com/testdep v0.1.0
+-- dep/dep.go --
+package dep
+-- dep/dep_test.go --
+package dep_test
+
+import _ "example.com/testdep"
+
+-- testdep/go.mod --
+module example.com/testdep
+-- testdep/testdep.go --
+package testdep
diff --git a/src/cmd/go/testdata/script/mod_go_version_mixed.txt b/src/cmd/go/testdata/script/mod_go_version_mixed.txt
new file mode 100644
index 0000000..d6216ae
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_go_version_mixed.txt
@@ -0,0 +1,43 @@
+# Test that dependencies can use Go language features newer than the
+# Go version specified by the main module.
+
+env GO111MODULE=on
+
+go build
+
+-- go.mod --
+module m
+go 1.12
+require (
+ sub.1 v1.0.0
+)
+replace (
+ sub.1 => ./sub
+)
+
+-- x.go --
+package x
+
+import "sub.1"
+
+func F() { sub.F(0, 0) }
+
+var A sub.Alias
+var D sub.Defined
+
+-- sub/go.mod --
+module m
+go 1.14
+
+-- sub/sub.go --
+package sub
+
+// signed shift counts added in Go 1.13
+func F(l, r int) int { return l << r }
+
+type m1 interface { M() }
+type m2 interface { M() }
+
+// overlapping interfaces added in Go 1.14
+type Alias = interface { m1; m2; M() }
+type Defined interface { m1; m2; M() }
diff --git a/src/cmd/go/testdata/script/mod_gobuild_import.txt b/src/cmd/go/testdata/script/mod_gobuild_import.txt
new file mode 100644
index 0000000..70af331
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_gobuild_import.txt
@@ -0,0 +1,133 @@
+[short] skip
+
+# go/build's Import should find modules by invoking the go command
+
+go build -o $WORK ./testimport ./testfindonly
+
+# GO111MODULE=off
+env GO111MODULE=off
+! exec $WORK/testimport$GOEXE gobuild.example.com/x/y/z/w .
+
+# GO111MODULE=auto in GOPATH/src
+env GO111MODULE=auto
+exec $WORK/testimport$GOEXE gobuild.example.com/x/y/z/w .
+
+# GO111MODULE=auto outside GOPATH/src
+cd $GOPATH/other
+env GO111MODULE=auto
+exec $WORK/testimport$GOEXE other/x/y/z/w .
+stdout w2.go
+
+! exec $WORK/testimport$GOEXE gobuild.example.com/x/y/z/w .
+stderr 'no required module provides package gobuild.example.com/x/y/z/w; to add it:\n\tgo get gobuild.example.com/x/y/z/w'
+
+cd z
+exec $WORK/testimport$GOEXE other/x/y/z/w .
+stdout w2.go
+
+# GO111MODULE=on outside GOPATH/src
+env GO111MODULE=
+exec $WORK/testimport$GOEXE other/x/y/z/w .
+stdout w2.go
+env GO111MODULE=on
+exec $WORK/testimport$GOEXE other/x/y/z/w .
+stdout w2.go
+
+# GO111MODULE=on in GOPATH/src
+cd $GOPATH/src
+env GO111MODULE=
+exec $WORK/testimport$GOEXE gobuild.example.com/x/y/z/w .
+stdout w1.go
+env GO111MODULE=on
+exec $WORK/testimport$GOEXE gobuild.example.com/x/y/z/w .
+stdout w1.go
+cd w
+exec $WORK/testimport$GOEXE gobuild.example.com/x/y/z/w ..
+stdout w1.go
+
+# go/build's Import in FindOnly mode should find directories by invoking the go command
+#
+# Calling build.Import in build.FindOnly mode on an import path of a Go package
+# that produces errors when loading (e.g., due to build constraints not matching
+# the current build context) should return the package directory and nil error.
+
+# Issue 31603: Import with non-empty srcDir should work.
+env GO111MODULE=on
+exec $WORK/testfindonly$GOEXE gobuild.example.com/x/y/z/i $WORK
+! stdout 'build constraints'
+stdout '^dir='$WORK'.+i err=<nil>$'
+
+# Issue 37153: Import with empty srcDir should work.
+env GO111MODULE=on
+exec $WORK/testfindonly$GOEXE gobuild.example.com/x/y/z/i ''
+! stdout 'build constraints'
+stdout '^dir='$WORK'.+i err=<nil>$'
+
+-- go.mod --
+module gobuild.example.com/x/y/z
+
+-- z.go --
+package z
+
+-- w/w1.go --
+package w
+
+-- i/i.go --
+// +build i
+
+package i
+
+-- testimport/x.go --
+package main
+
+import (
+ "fmt"
+ "go/build"
+ "log"
+ "os"
+ "path/filepath"
+ "strings"
+)
+
+func main() {
+ // build.Import should support relative and absolute source dir paths.
+ path := os.Args[1]
+ srcDir := os.Args[2]
+ p1, err := build.Import(path, srcDir, 0)
+ if err != nil {
+ log.Fatal(err)
+ }
+ absSrcDir, err := filepath.Abs(srcDir)
+ if err != nil {
+ log.Fatal(err)
+ }
+ p2, err := build.Import(path, absSrcDir, 0)
+ if err != nil {
+ log.Fatal(err)
+ }
+ if p1.Dir != p2.Dir {
+ log.Fatalf("different packages loaded with relative and absolute paths:\n\t%s\n\t%s", p1.Dir, p2.Dir)
+ }
+
+ fmt.Printf("%s\n%s\n", p1.Dir, strings.Join(p1.GoFiles, " "))
+}
+
+-- testfindonly/x.go --
+package main
+
+import (
+ "fmt"
+ "go/build"
+ "os"
+)
+
+func main() {
+ p, err := build.Import(os.Args[1], os.Args[2], build.FindOnly)
+ fmt.Printf("dir=%s err=%v\n", p.Dir, err)
+}
+
+-- $GOPATH/other/go.mod --
+module other/x/y
+
+-- $GOPATH/other/z/w/w2.go --
+package w
diff --git a/src/cmd/go/testdata/script/mod_gofmt_invalid.txt b/src/cmd/go/testdata/script/mod_gofmt_invalid.txt
new file mode 100644
index 0000000..21edc7d
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_gofmt_invalid.txt
@@ -0,0 +1,13 @@
+# Test for a crash in go fmt on invalid input when using modules.
+# Issue 26792.
+
+env GO111MODULE=on
+! go fmt x.go
+! stderr panic
+
+-- go.mod --
+module x
+
+-- x.go --
+// Missing package declaration.
+var V int
diff --git a/src/cmd/go/testdata/script/mod_goline.txt b/src/cmd/go/testdata/script/mod_goline.txt
new file mode 100644
index 0000000..6b2eab0
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_goline.txt
@@ -0,0 +1,117 @@
+env TESTGO_VERSION=go1.99
+
+! go list -f '{{.Module.GoVersion}}'
+stderr 'go: updates to go.mod needed'
+stderr 'go mod tidy'
+
+go mod tidy
+cat go.mod
+go list -f '{{.Module.GoVersion}}'
+stdout 1.22
+
+# Adding a@v1.0.01 should upgrade to Go 1.23rc1.
+cp go.mod go.mod1
+go get example.com/a@v1.0.1
+stderr '^go: upgraded go 1.22 => 1.23rc1\ngo: upgraded example.com/a v1.0.0 => v1.0.1\ngo: upgraded example.com/b v1.0.0 => v1.0.1$'
+go list -f '{{.Module.GoVersion}}'
+stdout 1.23rc1
+
+# Repeating the update with go@1.24.0 should use that Go version.
+cp go.mod1 go.mod
+go get example.com/a@v1.0.1 go@1.24.0
+go list -f '{{.Module.GoVersion}}'
+stdout 1.24.0
+
+# Go version-constrained updates should report the problems.
+cp go.mod1 go.mod
+! go get example.com/a@v1.0.2 go@1.24.2
+stderr '^go: example.com/a@v1.0.2 requires go@1.25, not go@1.24.2$'
+! go get example.com/a@v1.0.2 go@1.26.3
+stderr '^go: example.com/a@v1.0.2 indirectly requires go@1.27, not go@1.26.3$'
+go get example.com/a@v1.0.2 go@1.28rc1
+go list -f '{{.Module.GoVersion}}'
+stdout 1.28rc1
+go get go@1.24.2
+stderr '^go: downgraded go 1.28rc1 => 1.24.2$'
+stderr '^go: downgraded example.com/a v1.0.2 => v1.0.1$'
+stderr '^go: downgraded example.com/b v1.0.2 => v1.0.1$'
+go list -f '{{.Module.GoVersion}}'
+stdout 1.24.2
+
+-- go.mod --
+module m
+go 1.21
+
+require (
+ example.com/a v1.0.0
+ example.com/b v0.9.0
+)
+
+replace example.com/a v1.0.0 => ./a100
+replace example.com/a v1.0.1 => ./a101
+replace example.com/a v1.0.2 => ./a102
+replace example.com/b v1.0.1 => ./b101
+replace example.com/b v1.0.2 => ./b102
+replace example.com/b v1.0.0 => ./b100
+replace example.com/b v0.9.0 => ./b100
+
+-- x.go --
+package m
+
+import (
+ _ "example.com/a"
+ _ "example.com/b"
+)
+
+-- a100/go.mod --
+module example.com/a
+go 1.22
+
+require example.com/b v1.0.0
+
+-- a100/a.go --
+package a
+
+-- a101/go.mod --
+// this module is technically invalid, since the dep example.com/b has a newer go line than this module,
+// but we should still be able to handle it.
+module example.com/a
+go 1.22
+
+require example.com/b v1.0.1
+
+-- a101/a.go --
+package a
+
+-- a102/go.mod --
+// this module is technically invalid, since the dep example.com/b has a newer go line than this module,
+// but we should still be able to handle it.
+module example.com/a
+go 1.25
+
+require example.com/b v1.0.2
+
+-- a102/a.go --
+package a
+
+-- b100/go.mod --
+module example.com/b
+go 1.22
+
+-- b100/b.go --
+package b
+
+-- b101/go.mod --
+module example.com/b
+go 1.23rc1
+
+-- b101/b.go --
+package b
+
+-- b102/go.mod --
+module example.com/b
+go 1.27
+
+-- b102/b.go --
+package b
+
diff --git a/src/cmd/go/testdata/script/mod_goline_old.txt b/src/cmd/go/testdata/script/mod_goline_old.txt
new file mode 100644
index 0000000..bbe611b
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_goline_old.txt
@@ -0,0 +1,72 @@
+env TESTGO_VERSION=go1.24
+
+go list -f '{{.Module.GoVersion}}'
+stdout 1.15
+
+go mod tidy
+go list -f '{{.Module.GoVersion}}'
+stdout 1.15
+
+go get example.com/a@v1.0.1
+go list -f '{{.Module.GoVersion}}'
+stdout 1.15
+
+go get example.com/a@v1.0.1 go@1.16
+go list -f '{{.Module.GoVersion}}'
+stdout 1.16
+
+-- go.mod --
+module m
+go 1.15
+
+require (
+ example.com/a v1.0.0
+ example.com/b v1.0.0
+)
+
+replace example.com/a v1.0.0 => ./a100
+replace example.com/a v1.0.1 => ./a101
+replace example.com/b v1.0.1 => ./b101
+replace example.com/b v1.0.0 => ./b100
+replace example.com/b v0.9.0 => ./b100
+
+-- x.go --
+package m
+
+import (
+ _ "example.com/a"
+ _ "example.com/b"
+)
+
+-- a100/go.mod --
+module example.com/a
+go 1.16
+
+require example.com/b v1.0.0
+
+-- a100/a.go --
+package a
+
+-- a101/go.mod --
+module example.com/a
+go 1.17
+
+require example.com/b v1.0.1
+
+-- a101/a.go --
+package a
+
+-- b100/go.mod --
+module example.com/b
+go 1.18
+
+-- b100/b.go --
+package b
+
+-- b101/go.mod --
+module example.com/b
+go 1.19
+
+-- b101/b.go --
+package b
+
diff --git a/src/cmd/go/testdata/script/mod_goline_too_new.txt b/src/cmd/go/testdata/script/mod_goline_too_new.txt
new file mode 100644
index 0000000..6d26679
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_goline_too_new.txt
@@ -0,0 +1,50 @@
+# Go should refuse to build code that is too new according to go.mod.
+
+# go.mod too new
+env GOTOOLCHAIN=local
+! go build .
+stderr '^go: go.mod requires go >= 1.99999 \(running go 1\..+\)$'
+
+# go.mod referenced from go.work too new
+cp go.work.old go.work
+! go build .
+stderr '^go: module . listed in go.work file requires go >= 1.99999, but go.work lists go 1.10; to update it:\n\tgo work use$'
+
+! go work sync
+stderr '^go: cannot load module . listed in go.work file: go.mod requires go >= 1.99999 \(running go 1\..+\)$'
+
+# go.work too new
+cp go.work.new go.work
+cp go.mod.old go.mod
+! go build .
+stderr '^go: go.work requires go >= 1.99999 \(running go 1\..+\)$'
+
+# vendor too new
+rm go.work
+mv notvendor vendor
+! go build -mod=vendor .
+stderr '^go: golang.org/x/text in vendor'${/}'modules.txt requires go >= 1.99999 \(running go 1\..+\)$'
+
+-- go.mod --
+module example
+go 1.99999
+
+-- p.go --
+package p
+
+-- go.mod.old --
+module example
+go 1.10
+
+-- go.work.new --
+go 1.99999
+use .
+
+-- go.work.old --
+go 1.10
+use .
+
+-- notvendor/modules.txt --
+# golang.org/x/text v0.9.0
+## explicit; go 1.99999
+golang.org/x/text/internal/language
diff --git a/src/cmd/go/testdata/script/mod_gomodcache.txt b/src/cmd/go/testdata/script/mod_gomodcache.txt
new file mode 100644
index 0000000..bfc6cb1
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_gomodcache.txt
@@ -0,0 +1,74 @@
+# Test GOMODCACHE
+env GO111MODULE=on
+
+# Explicitly set GOMODCACHE
+env GOMODCACHE=$WORK/modcache
+go env GOMODCACHE
+stdout $WORK[/\\]modcache
+go get rsc.io/quote@v1.0.0
+exists $WORK/modcache/cache/download/rsc.io/quote/@v/v1.0.0.info
+grep '{"Version":"v1.0.0","Time":"2018-02-14T00:45:20Z"}' $WORK/modcache/cache/download/rsc.io/quote/@v/v1.0.0.info
+
+# Ensure GOMODCACHE doesn't affect location of sumdb, but $GOMODCACHE/cache/download/sumdb is still written
+exists $GOPATH/pkg/sumdb
+! exists $WORK/modcache/sumdb
+exists $WORK/modcache/cache/download/sumdb
+
+# Test that the default GOMODCACHE is $GOPATH[0]/pkg/mod
+env GOMODCACHE=
+go env GOMODCACHE
+stdout $GOPATH[/\\]pkg[/\\]mod
+go get rsc.io/quote@v1.0.0
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.0.0.info
+grep '{"Version":"v1.0.0","Time":"2018-02-14T00:45:20Z"}' $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.0.0.info
+
+# If neither GOMODCACHE or GOPATH are set, GOPATH defaults to the user's $HOME/go, so GOMODCACHE becomes $HOME/go/pkg/mod
+[GOOS:windows] env USERPROFILE=$WORK/home # Ensure USERPROFILE is a valid path (rather than /no-home/ so we don't run into the logic that "uninfers" GOPATH in cmd/go/main.go
+[GOOS:plan9] env home=$WORK/home
+[!GOOS:windows] [!GOOS:plan9] env HOME=$WORK/home
+env GOMODCACHE=
+env GOPATH=
+go env GOMODCACHE
+stdout $HOME[/\\]go[/\\]pkg[/\\]mod
+
+# If GOMODCACHE isn't set and GOPATH starts with the path list separator,
+# GOMODCACHE is empty and any command that needs it errors out.
+env GOMODCACHE=
+env GOPATH=${:}$WORK/this/is/ignored
+
+go env GOMODCACHE
+stdout '^$'
+! stdout .
+! stderr .
+
+! go mod download rsc.io/quote@v1.0.0
+stderr '^go: module cache not found: neither GOMODCACHE nor GOPATH is set$'
+
+# If GOMODCACHE isn't set and GOPATH has multiple elements only the first is used.
+env GOMODCACHE=
+env GOPATH=$WORK/first/path${:}$WORK/this/is/ignored
+go env GOMODCACHE
+stdout $WORK[/\\]first[/\\]path[/\\]pkg[/\\]mod
+
+env GOMODCACHE=$WORK/modcache
+go mod download rsc.io/quote@v1.0.0
+exists $WORK/modcache/cache/download/rsc.io/quote/@v/v1.0.0.info
+
+# Test error when cannot create GOMODCACHE directory
+env GOMODCACHE=$WORK/modcachefile
+! go install example.com/cmd/a@v1.0.0
+stderr 'go: could not create module cache'
+
+# Test that the following work even with GO111MODULE=off
+env GO111MODULE=off
+
+# Cleaning modcache
+exists $WORK/modcache
+env GOMODCACHE=$WORK/modcache
+go clean -modcache
+! exists $WORK/modcache
+
+-- go.mod --
+module m
+
+-- $WORK/modcachefile --
diff --git a/src/cmd/go/testdata/script/mod_gonoproxy.txt b/src/cmd/go/testdata/script/mod_gonoproxy.txt
new file mode 100644
index 0000000..94d03f2
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_gonoproxy.txt
@@ -0,0 +1,55 @@
+env GO111MODULE=on
+env sumdb=$GOSUMDB
+env proxy=$GOPROXY
+env GOPRIVATE GOPROXY GONOPROXY GOSUMDB GONOSUMDB
+env dbname=localhost.localdev/sumdb
+
+# disagree with sumdb fails
+cp go.mod.orig go.mod
+env GOSUMDB=$sumdb' '$proxy/sumdb-wrong
+! go get rsc.io/quote
+stderr 'SECURITY ERROR'
+
+# GONOSUMDB bypasses sumdb, for rsc.io/quote, rsc.io/sampler, golang.org/x/text
+env GONOSUMDB='*/quote,*/*mple*,golang.org/x'
+go get rsc.io/quote
+rm go.sum
+env GOPRIVATE='*/quote,*/*mple*,golang.org/x'
+env GONOPROXY=none # that is, proxy all despite GOPRIVATE
+go get rsc.io/quote
+
+# Download .info files needed for 'go list -m all' later.
+# TODO(#42723): either 'go list -m' should not read these files,
+# or 'go get' and 'go mod tidy' should download them.
+go list -m all
+stdout '^golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c$'
+
+# When GOPROXY is not empty but contains no entries, an error should be reported.
+env GOPROXY=','
+! go get golang.org/x/text
+stderr '^go: golang.org/x/text: GOPROXY list is not the empty string, but contains no entries$'
+
+# When GOPROXY=off, fetching modules not matched by GONOPROXY fails.
+env GONOPROXY=*/fortune
+env GOPROXY=off
+! go get golang.org/x/text
+stderr '^go: golang.org/x/text: module lookup disabled by GOPROXY=off$'
+
+# GONOPROXY bypasses proxy
+[!net:rsc.io] skip
+[!git] skip
+env GOPRIVATE=none
+env GONOPROXY='*/fortune'
+! go get rsc.io/fortune # does not exist in real world, only on test proxy
+stderr 'git ls-remote'
+
+[!net:golang.org] skip
+env GOSUMDB=
+env GONOPROXY=
+env GOPRIVATE='*/x'
+go get golang.org/x/text
+go list -m all
+! stdout 'text.*v0.0.0-2017' # should not have the version from the proxy
+
+-- go.mod.orig --
+module m
diff --git a/src/cmd/go/testdata/script/mod_gopkg_unstable.txt b/src/cmd/go/testdata/script/mod_gopkg_unstable.txt
new file mode 100644
index 0000000..856f493
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_gopkg_unstable.txt
@@ -0,0 +1,26 @@
+env GO111MODULE=on
+
+cp go.mod.empty go.mod
+go get gopkg.in/dummy.v2-unstable
+
+cp x.go.txt x.go
+cp go.mod.empty go.mod
+go list
+
+[!net:gopkg.in] skip
+[!git] skip
+
+skip # TODO(#54503): redirect gopkg.in requests to a local server and re-enable.
+
+env GOPROXY=direct
+env GOSUMDB=off
+go get gopkg.in/macaroon-bakery.v2-unstable/bakery
+go list -m all
+stdout 'gopkg.in/macaroon-bakery.v2-unstable v2.0.0-[0-9]+-[0-9a-f]+$'
+
+-- go.mod.empty --
+module m
+
+-- x.go.txt --
+package x
+import _ "gopkg.in/dummy.v2-unstable"
diff --git a/src/cmd/go/testdata/script/mod_goroot_errors.txt b/src/cmd/go/testdata/script/mod_goroot_errors.txt
new file mode 100644
index 0000000..110a196
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_goroot_errors.txt
@@ -0,0 +1,53 @@
+env GO111MODULE=on
+
+# Regression test for https://golang.org/issue/34769.
+# Missing standard-library imports should refer to GOROOT rather than
+# complaining about a malformed module path.
+# This is especially important when GOROOT is set incorrectly,
+# since such an error will occur for every package in std.
+
+# Building a nonexistent std package directly should fail usefully.
+
+! go build -mod=readonly nonexist
+! stderr 'import lookup disabled'
+! stderr 'missing dot'
+stderr '^package nonexist is not in std \('$GOROOT'[/\\]src[/\\]nonexist\)$'
+
+! go build nonexist
+! stderr 'import lookup disabled'
+! stderr 'missing dot'
+stderr '^package nonexist is not in std \('$GOROOT'[/\\]src[/\\]nonexist\)$'
+
+# Building a nonexistent std package indirectly should also fail usefully.
+
+! go build -mod=readonly ./importnonexist
+! stderr 'import lookup disabled'
+! stderr 'missing dot'
+stderr '^importnonexist[/\\]x.go:2:8: package nonexist is not in std \('$GOROOT'[/\\]src[/\\]nonexist\)$'
+
+! go build ./importnonexist
+! stderr 'import lookup disabled'
+! stderr 'missing dot'
+stderr '^importnonexist[/\\]x.go:2:8: package nonexist is not in std \('$GOROOT'[/\\]src[/\\]nonexist\)$'
+
+# Building an *actual* std package should fail if GOROOT is set to something bogus.
+
+[!short] go build ./importjson # Prove that it works when GOROOT is valid.
+
+env GOROOT=$WORK/not-a-valid-goroot
+! go build ./importjson
+! stderr 'import lookup disabled'
+! stderr 'missing dot'
+stderr 'importjson[/\\]x.go:2:8: package encoding/json is not in std \('$WORK'[/\\]not-a-valid-goroot[/\\]src[/\\]encoding[/\\]json\)$'
+
+-- go.mod --
+module example.com
+go 1.14
+-- importnonexist/x.go --
+package importnonexist
+import _ "nonexist"
+-- importjson/x.go --
+package importjson
+import _ "encoding/json"
+-- $WORK/not-a-valid-goroot/README --
+This directory is not a valid GOROOT.
diff --git a/src/cmd/go/testdata/script/mod_graph.txt b/src/cmd/go/testdata/script/mod_graph.txt
new file mode 100644
index 0000000..8d51439
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_graph.txt
@@ -0,0 +1,15 @@
+env GO111MODULE=on
+
+go mod graph
+stdout '^m rsc.io/quote@v1.5.2$'
+stdout '^rsc.io/quote@v1.5.2 rsc.io/sampler@v1.3.0$'
+! stdout '^m rsc.io/sampler@v1.3.0$'
+! stderr 'get '$GOPROXY
+
+rm $GOPATH/pkg/mod/cache/download/rsc.io/quote
+go mod graph -x
+stderr 'get '$GOPROXY
+
+-- go.mod --
+module m
+require rsc.io/quote v1.5.2
diff --git a/src/cmd/go/testdata/script/mod_graph_version.txt b/src/cmd/go/testdata/script/mod_graph_version.txt
new file mode 100644
index 0000000..ed7e399
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_graph_version.txt
@@ -0,0 +1,101 @@
+# For this module, Go 1.17 prunes out a (transitive and otherwise-irrelevant)
+# requirement on a retracted higher version of a dependency.
+# However, when Go 1.16 reads the same requirements from the go.mod file,
+# it does not prune out that requirement, and selects the retracted version.
+#
+# The Go 1.16 module graph looks like:
+#
+# m ---- lazy v0.1.0 ---- requireincompatible v0.1.0 ---- incompatible v2.0.0+incompatible
+# | |
+# + -------+------------- incompatible v1.0.0
+#
+# The Go 1.17 module graph is the same except that the dependencies of
+# requireincompatible are pruned out (because the module that requires
+# it — lazy v0.1.0 — specifies 'go 1.17', and it is not otherwise relevant to
+# the main module).
+
+cp go.mod go.mod.orig
+
+go mod graph
+cp stdout graph-1.17.txt
+stdout '^example\.com/m example\.com/retract/incompatible@v1\.0\.0$'
+stdout '^example\.net/lazy@v0\.1\.0 example\.com/retract/incompatible@v1\.0\.0$'
+! stdout 'example\.com/retract/incompatible@v2\.0\.0\+incompatible'
+
+go mod graph -go=1.17
+cmp stdout graph-1.17.txt
+
+cmp go.mod go.mod.orig
+
+
+# Setting -go=1.16 should report the graph as viewed by Go 1.16,
+# but should not edit the go.mod file.
+
+go mod graph -go=1.16
+cp stdout graph-1.16.txt
+stdout '^example\.com/m example\.com/retract/incompatible@v1\.0\.0$'
+stdout '^example\.net/lazy@v0\.1\.0 example.com/retract/incompatible@v1\.0\.0$'
+stdout '^example.net/requireincompatible@v0.1.0 example.com/retract/incompatible@v2\.0\.0\+incompatible$'
+
+cmp go.mod go.mod.orig
+
+
+# If we actually update the go.mod file to the requested go version,
+# we should get the same selected versions, but the roots of the graph
+# may be updated.
+#
+# TODO(#45551): The roots should not be updated.
+
+go mod edit -go=1.16
+go mod graph
+! stdout '^example\.com/m example\.com/retract/incompatible@v1\.0\.0$'
+stdout '^example\.net/lazy@v0.1.0 example.com/retract/incompatible@v1\.0\.0$'
+stdout '^example.net/requireincompatible@v0.1.0 example.com/retract/incompatible@v2\.0\.0\+incompatible$'
+ # TODO(#45551): cmp stdout graph-1.16.txt
+
+
+# Unsupported go versions should be rejected, since we don't know
+# what versions they would report.
+! go mod graph -go=1.99999999999
+stderr '^invalid value "1\.99999999999" for flag -go: maximum supported Go version is '$goversion'\nusage: go mod graph \[-go=version\] \[-x\]\nRun ''go help mod graph'' for details.$'
+
+
+-- go.mod --
+// Module m indirectly imports a package from
+// example.com/retract/incompatible. Its selected version of
+// that module is lower under Go 1.17 semantics than under Go 1.16.
+module example.com/m
+
+go 1.17
+
+replace (
+ example.net/lazy v0.1.0 => ./lazy
+ example.net/requireincompatible v0.1.0 => ./requireincompatible
+)
+
+require (
+ example.com/retract/incompatible v1.0.0 // indirect
+ example.net/lazy v0.1.0
+)
+-- lazy/go.mod --
+// Module lazy requires example.com/retract/incompatible v1.0.0.
+//
+// When viewed from the outside it also has a transitive dependency
+// on v2.0.0+incompatible, but in lazy mode that transitive dependency
+// is pruned out.
+module example.net/lazy
+
+go 1.17
+
+exclude example.com/retract/incompatible v2.0.0+incompatible
+
+require (
+ example.com/retract/incompatible v1.0.0
+ example.net/requireincompatible v0.1.0
+)
+-- requireincompatible/go.mod --
+module example.net/requireincompatible
+
+go 1.15
+
+require example.com/retract/incompatible v2.0.0+incompatible
diff --git a/src/cmd/go/testdata/script/mod_help.txt b/src/cmd/go/testdata/script/mod_help.txt
new file mode 100644
index 0000000..b5cd30c
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_help.txt
@@ -0,0 +1,6 @@
+env GO111MODULE=on
+
+# go help get shows usage for get
+go help get
+stdout 'usage: go get'
+stdout 'get using modules to manage source' \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/mod_import.txt b/src/cmd/go/testdata/script/mod_import.txt
new file mode 100644
index 0000000..07714e9
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_import.txt
@@ -0,0 +1,18 @@
+env GO111MODULE=on
+
+# latest rsc.io/quote should be v1.5.2 not v1.5.3-pre1
+go get
+go list -m all
+stdout 'rsc.io/quote v1.5.2'
+
+# but v1.5.3-pre1 should be a known version
+go list -m -versions rsc.io/quote
+stdout '^rsc.io/quote v1.0.0 v1.1.0 v1.2.0 v1.2.1 v1.3.0 v1.4.0 v1.5.0 v1.5.1 v1.5.2 v1.5.3-pre1$'
+
+-- go.mod --
+module x
+
+-- x.go --
+package x
+import _ "rsc.io/quote"
+
diff --git a/src/cmd/go/testdata/script/mod_import_cycle.txt b/src/cmd/go/testdata/script/mod_import_cycle.txt
new file mode 100644
index 0000000..7be0749
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_import_cycle.txt
@@ -0,0 +1,40 @@
+env GO111MODULE=on
+
+# 'go list all' should fail with a reasonable error message
+! go list all
+stderr '^package m\n\timports m/a\n\timports m/b\n\timports m/a: import cycle not allowed'
+
+# 'go list -e' should not print to stderr, but should mark all three
+# packages (m, m/a, and m/b) as Incomplete.
+go list -e -json all
+! stderr .
+stdout -count=3 '"Incomplete": true,'
+
+-- go.mod --
+module m
+
+require (
+ m/a v0.0.0
+ m/b v0.0.0
+)
+
+replace (
+ m/a => ./a
+ m/b => ./b
+)
+-- m.go --
+package m
+import (
+ _ "m/a"
+ _ "m/b"
+)
+-- a/go.mod --
+module m/a
+-- a/a.go --
+package a
+import _ "m/b"
+-- b/go.mod --
+module m/b
+-- b/b.go --
+package b
+import _ "m/a"
diff --git a/src/cmd/go/testdata/script/mod_import_issue41113.txt b/src/cmd/go/testdata/script/mod_import_issue41113.txt
new file mode 100644
index 0000000..fed2510
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_import_issue41113.txt
@@ -0,0 +1,28 @@
+# Regression test for https://golang.org/issue/41113.
+#
+# When resolving a missing import path, the inability to add the package from
+# one module path should not interfere with adding a nested path.
+
+# Initially, our module depends on split-incompatible v2.1.0-pre+incompatible,
+# from which an imported package has been removed (and relocated to the nested
+# split-incompatible/subpkg module). modload.QueryPattern will suggest
+# split-incompatible v2.0.0+incompatible, which we cannot use (because it would
+# be an implicit downgrade), and split-incompatible/subpkg v0.1.0, which we
+# *should* use.
+
+go mod tidy
+
+go list -m all
+stdout '^example.com/split-incompatible/subpkg v0\.1\.0$'
+! stdout '^example.com/split-incompatible .*'
+
+-- go.mod --
+module golang.org/issue/41113
+
+go 1.16
+
+require example.com/split-incompatible v2.1.0-pre+incompatible
+-- x.go --
+package issue41113
+
+import _ "example.com/split-incompatible/subpkg"
diff --git a/src/cmd/go/testdata/script/mod_import_issue42891.txt b/src/cmd/go/testdata/script/mod_import_issue42891.txt
new file mode 100644
index 0000000..a78cab2
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_import_issue42891.txt
@@ -0,0 +1,14 @@
+# If an import declaration is an absolute path, most commands should report
+# an error instead of going into an infinite loop.
+# Verifies golang.org/issue/42891.
+go list .
+stdout '^m$'
+
+-- go.mod --
+module m
+
+go 1.16
+-- m.go --
+package m
+
+import "/"
diff --git a/src/cmd/go/testdata/script/mod_import_meta.txt b/src/cmd/go/testdata/script/mod_import_meta.txt
new file mode 100644
index 0000000..0e469d0
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_import_meta.txt
@@ -0,0 +1,45 @@
+# The loader should not attempt to resolve imports of the "all", "std", and "cmd" meta-packages.
+
+! go list -deps ./importall
+! stderr 'internal error'
+stderr '^importall[/\\]x.go:3:8: "all" is not an importable package; see ''go help packages''$'
+
+! go list -deps ./importcmd
+! stderr 'internal error'
+stderr '^importcmd[/\\]x.go:3:8: "cmd" is not an importable package; see ''go help packages''$'
+
+! go list -deps ./importstd
+! stderr 'internal error'
+stderr '^importstd[/\\]x.go:3:8: "std" is not an importable package; see ''go help packages''$'
+
+
+# Not even if such a path is theoretically provided by a (necessarily replaced) module.
+
+go mod edit -replace std@v0.1.0=./modstd
+go mod edit -require std@v0.1.0
+
+! go list -deps ./importstd
+stderr '^importstd[/\\]x.go:3:8: "std" is not an importable package; see ''go help packages''$'
+
+
+-- go.mod --
+module example.com
+go 1.16
+-- importall/x.go --
+package importall
+
+import _ "all"
+-- importcmd/x.go --
+package importcmd
+
+import _ "cmd"
+-- importstd/x.go --
+package importstd
+
+import _ "std"
+-- modstd/go.mod --
+module std
+go 1.16
+-- modstd/std.go --
+// Package std is an incredibly confusingly-named package.
+package std
diff --git a/src/cmd/go/testdata/script/mod_import_mod.txt b/src/cmd/go/testdata/script/mod_import_mod.txt
new file mode 100644
index 0000000..b035e3d
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_import_mod.txt
@@ -0,0 +1,7 @@
+# Test that GOPATH/pkg/mod is excluded
+env GO111MODULE=off
+! go list mod/foo
+stderr 'disallowed import path'
+
+-- mod/foo/foo.go --
+package foo
diff --git a/src/cmd/go/testdata/script/mod_import_toolchain.txt b/src/cmd/go/testdata/script/mod_import_toolchain.txt
new file mode 100644
index 0000000..42c12c1
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_import_toolchain.txt
@@ -0,0 +1,192 @@
+# This test verifies that 'go get' and 'go mod tidy' switch to a newer toolchain
+# if needed to process newly-reolved imports.
+
+env TESTGO_VERSION=go1.21.0
+env TESTGO_VERSION_SWITCH=switch
+
+cp go.mod go.mod.orig
+
+# tidy reports needing 1.22.0 for b1
+env GOTOOLCHAIN=local
+! go mod tidy
+stderr '^go: example imports\n\texample.net/b: module ./b1 requires go >= 1.22.0 \(running go 1.21.0; GOTOOLCHAIN=local\)$'
+env GOTOOLCHAIN=auto
+go mod tidy
+
+cmp stderr tidy-stderr.want
+cmp go.mod go.mod.tidy
+
+cp go.mod.orig go.mod
+env GOTOOLCHAIN=local
+! go get -v .
+stderr '^go: example.net/b@v0.1.0: module ./b1 requires go >= 1.22.0 \(running go 1.21.0; GOTOOLCHAIN=local\)$'
+env GOTOOLCHAIN=auto
+go get -v .
+cmp stderr get-v-stderr.want
+cmp go.mod go.mod.tidy
+
+cp go.mod.orig go.mod
+env GOTOOLCHAIN=local
+! go get -u -v .
+stderr '^go: example.net/a@v0.2.0: module ./a2 requires go >= 1.22.0 \(running go 1.21.0; GOTOOLCHAIN=local\)$'
+env GOTOOLCHAIN=auto
+go get -u -v .
+cmp stderr get-u-v-stderr.want
+cmp go.mod go.mod.upgraded
+
+-- tidy-stderr.want --
+go: found example.net/b in example.net/b v0.1.0
+go: module ./b1 requires go >= 1.22.0; switching to go1.22.9
+go: found example.net/b in example.net/b v0.1.0
+go: found example.net/c in example.net/c v0.1.0
+-- get-v-stderr.want --
+go: trying upgrade to example.net/b@v0.1.0
+go: module ./b1 requires go >= 1.22.0; switching to go1.22.9
+go: trying upgrade to example.net/b@v0.1.0
+go: accepting indirect upgrade from go@1.20 to 1.22.0
+go: trying upgrade to example.net/c@v0.1.0
+go: upgraded go 1.20 => 1.22.0
+go: added toolchain go1.22.9
+go: added example.net/b v0.1.0
+go: added example.net/c v0.1.0
+go: added example.net/d v0.1.0
+-- get-u-v-stderr.want --
+go: trying upgrade to example.net/a@v0.2.0
+go: trying upgrade to example.net/b@v0.1.0
+go: module ./a2 requires go >= 1.22.0; switching to go1.22.9
+go: trying upgrade to example.net/a@v0.2.0
+go: trying upgrade to example.net/b@v0.1.0
+go: accepting indirect upgrade from go@1.20 to 1.22.0
+go: trying upgrade to example.net/c@v0.1.0
+go: trying upgrade to example.net/d@v0.2.0
+go: module ./d2 requires go >= 1.23.0; switching to go1.23.9
+go: trying upgrade to example.net/a@v0.2.0
+go: trying upgrade to example.net/b@v0.1.0
+go: accepting indirect upgrade from go@1.20 to 1.22.0
+go: trying upgrade to example.net/c@v0.1.0
+go: trying upgrade to example.net/d@v0.2.0
+go: accepting indirect upgrade from go@1.22.0 to 1.23.0
+go: upgraded go 1.20 => 1.23.0
+go: added toolchain go1.23.9
+go: upgraded example.net/a v0.1.0 => v0.2.0
+go: added example.net/b v0.1.0
+go: added example.net/c v0.1.0
+go: added example.net/d v0.2.0
+-- go.mod --
+module example
+
+go 1.20
+
+require example.net/a v0.1.0
+
+replace (
+ example.net/a v0.1.0 => ./a1
+ example.net/a v0.2.0 => ./a2
+ example.net/b v0.1.0 => ./b1
+ example.net/c v0.1.0 => ./c1
+ example.net/d v0.1.0 => ./d1
+ example.net/d v0.2.0 => ./d2
+)
+-- go.mod.tidy --
+module example
+
+go 1.22.0
+
+toolchain go1.22.9
+
+require (
+ example.net/a v0.1.0
+ example.net/b v0.1.0
+)
+
+require (
+ example.net/c v0.1.0 // indirect
+ example.net/d v0.1.0 // indirect
+)
+
+replace (
+ example.net/a v0.1.0 => ./a1
+ example.net/a v0.2.0 => ./a2
+ example.net/b v0.1.0 => ./b1
+ example.net/c v0.1.0 => ./c1
+ example.net/d v0.1.0 => ./d1
+ example.net/d v0.2.0 => ./d2
+)
+-- go.mod.upgraded --
+module example
+
+go 1.23.0
+
+toolchain go1.23.9
+
+require (
+ example.net/a v0.2.0
+ example.net/b v0.1.0
+)
+
+require (
+ example.net/c v0.1.0 // indirect
+ example.net/d v0.2.0 // indirect
+)
+
+replace (
+ example.net/a v0.1.0 => ./a1
+ example.net/a v0.2.0 => ./a2
+ example.net/b v0.1.0 => ./b1
+ example.net/c v0.1.0 => ./c1
+ example.net/d v0.1.0 => ./d1
+ example.net/d v0.2.0 => ./d2
+)
+-- example.go --
+package example
+
+import (
+ _ "example.net/a"
+ _ "example.net/b"
+)
+-- a1/go.mod --
+module example.net/a
+
+go 1.20
+-- a1/a.go --
+package a
+-- a2/go.mod --
+module example.net/a
+
+go 1.22.0
+
+toolchain go1.23.0
+-- a2/a.go --
+package a
+-- b1/go.mod --
+module example.net/b
+
+go 1.22.0
+
+toolchain go1.23.0
+-- b1/b.go --
+package b
+
+import _ "example.net/c" // Note: module b is intentionally untidy, as if due to a bad git merge
+-- c1/go.mod --
+module example.net/c
+
+go 1.22.0
+
+require example.net/d v0.1.0
+-- c1/c.go --
+package c
+
+import _ "example.net/d"
+-- d1/go.mod --
+module example.net/d
+
+go 1.22.0
+-- d1/d.go --
+package d
+-- d2/go.mod --
+module example.net/d
+
+go 1.23.0
+-- d2/d.go --
+package d
diff --git a/src/cmd/go/testdata/script/mod_import_v1suffix.txt b/src/cmd/go/testdata/script/mod_import_v1suffix.txt
new file mode 100644
index 0000000..75b3374
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_import_v1suffix.txt
@@ -0,0 +1,11 @@
+env GO111MODULE=on
+
+! go get example.com/invalidpath/v1
+! go install .
+
+-- go.mod --
+module example.com
+-- main.go --
+package main
+import _ "example.com/invalidpath/v1"
+func main() {}
diff --git a/src/cmd/go/testdata/script/mod_in_testdata_dir.txt b/src/cmd/go/testdata/script/mod_in_testdata_dir.txt
new file mode 100644
index 0000000..866f784
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_in_testdata_dir.txt
@@ -0,0 +1,45 @@
+# Regression test for golang.org/issue/28481:
+# 'mod tidy' removed dependencies if the module root was
+# within a directory named 'testdata' or '_foo'.
+
+env GO111MODULE=on
+
+# A module should be allowed in a directory named testdata.
+cd $WORK/testdata
+go mod init testdata.tld/foo
+
+# Getting a package within that module should resolve its dependencies.
+go get
+grep 'rsc.io/quote' go.mod
+
+# Tidying the module should preserve those dependencies.
+go mod tidy
+grep 'rsc.io/quote' go.mod
+
+[short] stop
+
+# Vendoring the module's dependencies should work too.
+go mod vendor
+exists vendor/rsc.io/quote
+
+# The same should work in directories with names starting with underscores.
+cd $WORK/_ignored
+go mod init testdata.tld/foo
+
+go get
+grep 'rsc.io/quote' go.mod
+
+go mod tidy
+grep 'rsc.io/quote' go.mod
+
+go mod vendor
+exists vendor/rsc.io/quote
+
+-- $WORK/testdata/main.go --
+package foo
+
+import _ "rsc.io/quote"
+-- $WORK/_ignored/main.go --
+package foo
+
+import _ "rsc.io/quote"
diff --git a/src/cmd/go/testdata/script/mod_indirect.txt b/src/cmd/go/testdata/script/mod_indirect.txt
new file mode 100644
index 0000000..6ea1cae
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_indirect.txt
@@ -0,0 +1,81 @@
+env GO111MODULE=on
+
+# golang.org/issue/31248: required modules imposed by dependency versions
+# older than the selected version must still be taken into account.
+
+env GOFLAGS=-mod=readonly
+
+# Indirect dependencies required via older-than-selected versions must exist in
+# the module graph, but do not need to be listed explicitly in the go.mod file
+# (since they are implied).
+go mod graph
+stdout i@v0.1.0
+
+# The modules must also appear in the build list, not just the graph.
+go list -m all
+stdout '^i v0.1.0'
+
+# The packages provided by those dependencies must resolve.
+go list all
+stdout '^i$'
+
+-- go.mod --
+module main
+
+go 1.13
+
+require (
+ a v0.0.0
+ b v0.0.0
+ c v0.0.0
+)
+
+// Apply replacements so that the test can be self-contained.
+// (It's easier to see all of the modules here than to go
+// rooting around in testdata/mod.)
+replace (
+ a => ./a
+ b => ./b
+ c => ./c
+ x v0.1.0 => ./x1
+ x v0.2.0 => ./x2
+ i => ./i
+)
+-- main.go --
+package main
+
+import (
+ _ "a"
+ _ "b"
+ _ "c"
+)
+
+func main() {}
+-- a/go.mod --
+module a
+go 1.13
+require x v0.1.0
+-- a/a.go --
+package a
+-- b/go.mod --
+module b
+go 1.13
+require x v0.2.0
+-- b/b.go --
+package b
+-- c/go.mod --
+module c
+go 1.13
+-- c/c.go --
+package c
+import _ "i"
+-- x1/go.mod --
+module x
+go1.13
+require i v0.1.0
+-- x2/go.mod --
+module x
+go1.13
+-- i/go.mod --
+-- i/i.go --
+package i
diff --git a/src/cmd/go/testdata/script/mod_indirect_main.txt b/src/cmd/go/testdata/script/mod_indirect_main.txt
new file mode 100644
index 0000000..e84eb9c
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_indirect_main.txt
@@ -0,0 +1,66 @@
+env GO111MODULE=on
+
+# Regression test for golang.org/issue/29773: 'go list -m' was not following
+# dependencies through older versions of the main module.
+
+go list -f '{{with .Module}}{{.Path}}{{with .Version}} {{.}}{{end}}{{end}}' all
+cmp stdout pkgmods.txt
+
+go list -m all
+cmp stdout mods.txt
+
+go mod graph
+cmp stdout graph.txt
+
+-- go.mod --
+module golang.org/issue/root
+
+go 1.12
+
+replace (
+ golang.org/issue/mirror v0.1.0 => ./mirror-v0.1.0
+ golang.org/issue/pkg v0.1.0 => ./pkg-v0.1.0
+ golang.org/issue/root v0.1.0 => ./root-v0.1.0
+)
+
+require golang.org/issue/mirror v0.1.0
+
+-- root.go --
+package root
+
+import _ "golang.org/issue/mirror"
+
+-- mirror-v0.1.0/go.mod --
+module golang.org/issue/mirror
+
+require golang.org/issue/root v0.1.0
+
+-- mirror-v0.1.0/mirror.go --
+package mirror
+
+import _ "golang.org/issue/pkg"
+
+-- pkg-v0.1.0/go.mod --
+module golang.org/issue/pkg
+
+-- pkg-v0.1.0/pkg.go --
+package pkg
+
+-- root-v0.1.0/go.mod --
+module golang.org/issue/root
+
+require golang.org/issue/pkg v0.1.0
+
+-- pkgmods.txt --
+golang.org/issue/mirror v0.1.0
+golang.org/issue/pkg v0.1.0
+golang.org/issue/root
+-- mods.txt --
+golang.org/issue/root
+golang.org/issue/mirror v0.1.0 => ./mirror-v0.1.0
+golang.org/issue/pkg v0.1.0 => ./pkg-v0.1.0
+-- graph.txt --
+golang.org/issue/root go@1.12
+golang.org/issue/root golang.org/issue/mirror@v0.1.0
+golang.org/issue/mirror@v0.1.0 golang.org/issue/root@v0.1.0
+golang.org/issue/root@v0.1.0 golang.org/issue/pkg@v0.1.0
diff --git a/src/cmd/go/testdata/script/mod_indirect_nospace.txt b/src/cmd/go/testdata/script/mod_indirect_nospace.txt
new file mode 100644
index 0000000..f4fb6a8
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_indirect_nospace.txt
@@ -0,0 +1,32 @@
+# https://golang.org/issue/45932: "indirect" comments missing spaces
+# should not be corrupted when the comment is removed.
+
+go mod tidy
+cmp go.mod go.mod.direct
+
+-- go.mod --
+module example.net/m
+
+go 1.16
+
+require example.net/x v0.1.0 //indirect
+
+replace example.net/x v0.1.0 => ./x
+-- go.mod.direct --
+module example.net/m
+
+go 1.16
+
+require example.net/x v0.1.0
+
+replace example.net/x v0.1.0 => ./x
+-- m.go --
+package m
+import _ "example.net/x"
+
+-- x/go.mod --
+module example.net/x
+
+go 1.16
+-- x/x.go --
+package x
diff --git a/src/cmd/go/testdata/script/mod_indirect_tidy.txt b/src/cmd/go/testdata/script/mod_indirect_tidy.txt
new file mode 100644
index 0000000..a12b35c
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_indirect_tidy.txt
@@ -0,0 +1,60 @@
+env GO111MODULE=on
+
+# golang.org/issue/31248: loading the build list must not add explicit entries
+# for indirect dependencies already implied by older-than-selected versions
+# already in the build list.
+
+cp go.mod.orig go.mod
+go mod tidy
+cmp go.mod go.mod.orig
+
+cp go.mod.orig go.mod
+go list -m all
+cmp go.mod go.mod.orig
+
+-- go.mod.orig --
+module main
+
+go 1.13
+
+require a v0.0.0
+
+replace (
+ a v0.0.0 => ./a
+ b v0.0.0 => ./b
+ i v0.0.0 => ./i
+ x v0.1.0 => ./x1
+ x v0.2.0 => ./x2
+)
+-- main.go --
+package main
+
+import _ "a"
+
+func main() {}
+-- a/go.mod --
+module a
+go 1.13
+require (
+ x v0.2.0
+ b v0.0.0
+)
+-- a/a.go --
+package a
+-- b/go.mod --
+module b
+go 1.13
+require x v0.1.0
+-- x1/go.mod --
+module x
+go 1.13
+require (
+ b v0.0.0
+ i v0.0.0
+)
+-- x2/go.mod --
+module x
+go 1.13
+-- i/go.mod --
+module i
+go 1.13
diff --git a/src/cmd/go/testdata/script/mod_init_empty.txt b/src/cmd/go/testdata/script/mod_init_empty.txt
new file mode 100644
index 0000000..d197a79
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_init_empty.txt
@@ -0,0 +1,21 @@
+env GO111MODULE=on
+
+env GOPATH=$WORK${/}invalid-gopath
+
+go list -m
+stdout '^example.com$'
+
+go list
+stdout '^example.com$'
+
+-- go.mod --
+module example.com
+
+go 1.13
+-- main.go --
+package main
+
+func main() {}
+
+-- $WORK/invalid-gopath
+This is a text file, not a directory.
diff --git a/src/cmd/go/testdata/script/mod_init_invalid_major.txt b/src/cmd/go/testdata/script/mod_init_invalid_major.txt
new file mode 100644
index 0000000..ae93e70
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_init_invalid_major.txt
@@ -0,0 +1,82 @@
+env GO111MODULE=on
+env GOFLAGS=-mod=mod
+
+! go mod init example.com/user/repo/v0
+stderr '(?s)^go: invalid module path "example.com/user/repo/v0": major version suffixes must be in the form of /vN and are only allowed for v2 or later(.*)go mod init example.com/user/repo/v2$'
+
+! go mod init example.com/user/repo/v02
+stderr '(?s)^go: invalid module path "example.com/user/repo/v02": major version suffixes must be in the form of /vN and are only allowed for v2 or later(.*)go mod init example.com/user/repo/v2$'
+
+! go mod init example.com/user/repo/v023
+stderr '(?s)^go: invalid module path "example.com/user/repo/v023": major version suffixes must be in the form of /vN and are only allowed for v2 or later(.*)go mod init example.com/user/repo/v23$'
+
+! go mod init example.com/user/repo/v1
+stderr '(?s)^go: invalid module path "example.com/user/repo/v1": major version suffixes must be in the form of /vN and are only allowed for v2 or later(.*)go mod init example.com/user/repo/v2$'
+
+! go mod init example.com/user/repo/v2.0
+stderr '(?s)^go: invalid module path "example.com/user/repo/v2.0": major version suffixes must be in the form of /vN and are only allowed for v2 or later(.*)go mod init example.com/user/repo/v2$'
+
+! go mod init example.com/user/repo/v2.1.4
+stderr '(?s)^go: invalid module path "example.com/user/repo/v2.1.4": major version suffixes must be in the form of /vN and are only allowed for v2 or later(.*)go mod init example.com/user/repo/v2$'
+
+! go mod init example.com/user/repo/v3.5
+stderr '(?s)^go: invalid module path "example.com/user/repo/v3.5": major version suffixes must be in the form of /vN and are only allowed for v2 or later(.*)go mod init example.com/user/repo/v3$'
+
+! go mod init example.com/user/repo/v4.1.4
+stderr '(?s)^go: invalid module path "example.com/user/repo/v4.1.4": major version suffixes must be in the form of /vN and are only allowed for v2 or later(.*)go mod init example.com/user/repo/v4$'
+
+! go mod init example.com/user/repo/v.2.3
+stderr '(?s)^go: invalid module path "example.com/user/repo/v.2.3": major version suffixes must be in the form of /vN and are only allowed for v2 or later(.*)go mod init example.com/user/repo/v2$'
+
+! go mod init example.com/user/repo/v.5.3
+stderr '(?s)^go: invalid module path "example.com/user/repo/v.5.3": major version suffixes must be in the form of /vN and are only allowed for v2 or later(.*)go mod init example.com/user/repo/v5$'
+
+! go mod init gopkg.in/pkg
+stderr '(?s)^go: invalid module path "gopkg.in/pkg": module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN(.*)go mod init gopkg.in/pkg.v1$'
+
+! go mod init gopkg.in/user/pkg
+stderr '(?s)^go: invalid module path "gopkg.in/user/pkg": module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN(.*)go mod init gopkg.in/user/pkg.v1$'
+
+! go mod init gopkg.in/user/pkg/v0
+stderr '(?s)^go: invalid module path "gopkg.in/user/pkg/v0": module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN(.*)go mod init gopkg.in/user/pkg.v1$'
+
+! go mod init gopkg.in/user/pkg/v1
+stderr '(?s)^go: invalid module path "gopkg.in/user/pkg/v1": module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN(.*)go mod init gopkg.in/user/pkg.v1$'
+
+! go mod init gopkg.in/user/pkg/v2
+stderr '(?s)^go: invalid module path "gopkg.in/user/pkg/v2": module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN(.*)go mod init gopkg.in/user/pkg.v2$'
+
+! go mod init gopkg.in/user/pkg.v
+stderr '(?s)^go: invalid module path "gopkg.in/user/pkg.v": module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN(.*)go mod init gopkg.in/user/pkg.v1$'
+
+! go mod init gopkg.in/user/pkg.v0.1
+stderr '(?s)^go: invalid module path "gopkg.in/user/pkg.v0.1": module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN(.*)go mod init gopkg.in/user/pkg.v1$'
+
+! go mod init gopkg.in/user/pkg.v.1
+stderr '(?s)^go: invalid module path "gopkg.in/user/pkg.v.1": module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN(.*)go mod init gopkg.in/user/pkg.v1$'
+
+! go mod init gopkg.in/user/pkg.v01
+stderr '(?s)^go: invalid module path "gopkg.in/user/pkg.v01": module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN(.*)go mod init gopkg.in/user/pkg.v1$'
+
+! go mod init gopkg.in/user/pkg.v.2.3
+stderr '(?s)^go: invalid module path "gopkg.in/user/pkg.v.2.3": module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN(.*)go mod init gopkg.in/user/pkg.v2$'
+
+# module paths with a trailing dot are rejected as invalid import paths
+! go mod init example.com/user/repo/v2.
+stderr '(?s)^go: malformed module path "example.com/user/repo/v2.": trailing dot in path element$'
+
+! go mod init example.com/user/repo/v2..
+stderr '(?s)^go: malformed module path "example.com/user/repo/v2..": trailing dot in path element$'
+
+! go mod init gopkg.in/user/pkg.v.2.
+stderr '(?s)^go: malformed module path "gopkg.in/user/pkg.v.2.": trailing dot in path element$'
+
+! go mod init gopkg.in/user/pkg.v.2..
+stderr '(?s)^go: malformed module path "gopkg.in/user/pkg.v.2..": trailing dot in path element$'
+
+# module paths with spaces are also rejected
+! go mod init 'foo bar'
+stderr '(?s)^go: malformed module path "foo bar": invalid char '' ''$'
+
+! go mod init 'foo bar baz'
+stderr '(?s)^go: malformed module path "foo bar baz": invalid char '' ''$'
diff --git a/src/cmd/go/testdata/script/mod_init_path.txt b/src/cmd/go/testdata/script/mod_init_path.txt
new file mode 100644
index 0000000..e5fd4dd
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_init_path.txt
@@ -0,0 +1,20 @@
+env GO111MODULE=on
+
+! go mod init .
+stderr '^go: malformed module path ".": is a local import path$'
+
+cd x
+go mod init example.com/x
+
+cd ../y
+go mod init m
+
+-- x/main.go --
+package main
+
+func main() {}
+
+-- y/main.go --
+package main
+
+func main() {}
diff --git a/src/cmd/go/testdata/script/mod_init_tidy.txt b/src/cmd/go/testdata/script/mod_init_tidy.txt
new file mode 100644
index 0000000..4a52590
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_init_tidy.txt
@@ -0,0 +1,30 @@
+# 'go mod init' should not recommend 'go mod tidy' in an empty directory
+# (one that contains no non-hidden .go files or subdirectories).
+cd empty
+go mod init m
+! stderr tidy
+cd ..
+
+# 'go mod init' should recommend 'go mod tidy' if the directory has a .go file.
+cd pkginroot
+go mod init m
+stderr '^go: to add module requirements and sums:\n\tgo mod tidy$'
+cd ..
+
+# 'go mod init' should recommend 'go mod tidy' if the directory has a
+# subdirectory. We don't walk the tree to see if it has .go files.
+cd subdir
+go mod init m
+stderr '^go: to add module requirements and sums:\n\tgo mod tidy$'
+cd ..
+
+-- empty/empty.txt --
+Not a .go file. Still counts as an empty project.
+-- empty/.hidden/empty.go --
+File in hidden directory. Still as an empty project.
+-- empty/_hidden/empty.go --
+File in hidden directory. Still as an empty project.
+-- pkginroot/hello.go --
+package vendorimport
+-- subdir/sub/empty.txt --
+Subdirectory doesn't need to contain a package.
diff --git a/src/cmd/go/testdata/script/mod_insecure_issue63845.txt b/src/cmd/go/testdata/script/mod_insecure_issue63845.txt
new file mode 100644
index 0000000..c051c05
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_insecure_issue63845.txt
@@ -0,0 +1,28 @@
+# Regression test for https://go.dev/issue/63845:
+# If 'git ls-remote' fails for all secure protocols,
+# we should fail instead of falling back to an arbitrary protocol.
+#
+# Note that this test does not use the local vcweb test server
+# (vcs-test.golang.org), because the hook for redirecting to that
+# server bypasses the "ping to determine protocol" logic
+# in cmd/go/internal/vcs.
+
+[!net:golang.org] skip
+[!git] skip
+[short] skip 'tries to access a nonexistent external Git repo'
+
+env GOPRIVATE=golang.org
+env CURLOPT_TIMEOUT_MS=100
+env GIT_SSH_COMMAND=false
+
+! go get -x golang.org/nonexist.git@latest
+stderr '^git ls-remote https://golang.org/nonexist$'
+stderr '^git ls-remote git\+ssh://golang.org/nonexist'
+stderr '^git ls-remote ssh://golang.org/nonexist$'
+! stderr 'git://'
+stderr '^go: golang.org/nonexist.git@latest: no secure protocol found for repository$'
+
+-- go.mod --
+module example
+
+go 1.19
diff --git a/src/cmd/go/testdata/script/mod_install_hint.txt b/src/cmd/go/testdata/script/mod_install_hint.txt
new file mode 100644
index 0000000..ab02840
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_install_hint.txt
@@ -0,0 +1,5 @@
+# Module is replaced but not required. No hint appears as no module is suggested.
+go mod init m
+go mod edit -replace=github.com/notrequired@v0.5.0=github.com/doesnotexist@v0.5.0
+! go install github.com/notrequired
+! stderr 'to add it:' \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/mod_install_pkg_version.txt b/src/cmd/go/testdata/script/mod_install_pkg_version.txt
new file mode 100644
index 0000000..89dfc14
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_install_pkg_version.txt
@@ -0,0 +1,204 @@
+# 'go install pkg@version' works outside a module.
+env GO111MODULE=auto
+go install example.com/cmd/a@v1.0.0
+exists $GOPATH/bin/a$GOEXE
+rm $GOPATH/bin
+
+
+# 'go install pkg@version' reports an error if modules are disabled.
+env GO111MODULE=off
+! go install example.com/cmd/a@v1.0.0
+stderr '^go: modules disabled by GO111MODULE=off; see ''go help modules''$'
+env GO111MODULE=auto
+
+
+# 'go install pkg@version' ignores go.mod in current directory.
+cd m
+cp go.mod go.mod.orig
+! go list -m all
+stderr '^go: example.com/cmd@v1.1.0-doesnotexist: reading http.*/mod/example.com/cmd/@v/v1.1.0-doesnotexist.info: 404 Not Found\n\tserver response: 404 page not found$'
+stderr '^go: example.com/cmd@v1.1.0-doesnotexist: missing go.sum entry for go.mod file; to add it:\n\tgo mod download example.com/cmd$'
+go install example.com/cmd/a@latest
+cmp go.mod go.mod.orig
+exists $GOPATH/bin/a$GOEXE
+go version -m $GOPATH/bin/a$GOEXE
+stdout '^\tmod\texample.com/cmd\tv1.0.0\t' # "latest", not from go.mod
+rm $GOPATH/bin/a
+cd ..
+
+
+# 'go install -modfile=x.mod pkg@version' reports an error, but only if
+# -modfile is specified explicitly on the command line.
+cd m
+env GOFLAGS=-modfile=go.mod
+go install example.com/cmd/a@latest # same as above
+env GOFLAGS=
+! go install -modfile=go.mod example.com/cmd/a@latest
+stderr '^go: -modfile cannot be used with commands that ignore the current module$'
+cd ..
+
+
+# Every test case requires linking, so we only cover the most important cases
+# when -short is set.
+[short] stop
+
+
+# 'go install pkg@version' works on a module that doesn't have a go.mod file
+# and with a module whose go.mod file has missing requirements.
+# With a proxy, the two cases are indistinguishable.
+go install rsc.io/fortune@v1.0.0
+stderr '^go: found rsc.io/quote in rsc.io/quote v1.5.2$'
+exists $GOPATH/bin/fortune$GOEXE
+! exists $GOPATH/pkg/mod/rsc.io/fortune@v1.0.0/go.mod # no go.mod file
+go version -m $GOPATH/bin/fortune$GOEXE
+stdout '^\tdep\trsc.io/quote\tv1.5.2\t' # latest version of fortune's dependency
+rm $GOPATH/bin
+
+
+# 'go install dir@version' works like a normal 'go install' command if
+# dir is a relative or absolute path.
+env GO111MODULE=on
+go mod download rsc.io/fortune@v1.0.0
+! go install $GOPATH/pkg/mod/rsc.io/fortune@v1.0.0
+stderr '^go: go\.mod file not found in current directory or any parent directory; see ''go help modules''$'
+! go install ../pkg/mod/rsc.io/fortune@v1.0.0
+stderr '^go: go\.mod file not found in current directory or any parent directory; see ''go help modules''$'
+mkdir tmp
+cd tmp
+go mod init tmp
+go mod edit -require=rsc.io/fortune@v1.0.0
+! go install -mod=readonly $GOPATH/pkg/mod/rsc.io/fortune@v1.0.0
+stderr '^missing go\.sum entry for module providing package rsc\.io/fortune; to add:\n\tgo mod download rsc\.io/fortune$'
+! go install -mod=readonly ../../pkg/mod/rsc.io/fortune@v1.0.0
+stderr '^missing go\.sum entry for module providing package rsc\.io/fortune; to add:\n\tgo mod download rsc\.io/fortune$'
+go get rsc.io/fortune@v1.0.0
+go install -mod=readonly $GOPATH/pkg/mod/rsc.io/fortune@v1.0.0
+exists $GOPATH/bin/fortune$GOEXE
+cd ..
+rm tmp
+rm $GOPATH/bin
+env GO111MODULE=auto
+
+# 'go install pkg@version' reports errors for meta packages, std packages,
+# and directories.
+! go install std@v1.0.0
+stderr '^go: std@v1.0.0: argument must be a package path, not a meta-package$'
+! go install fmt@v1.0.0
+stderr '^go: fmt@v1.0.0: argument must not be a package in the standard library$'
+! go install example.com//cmd/a@v1.0.0
+stderr '^go: example.com//cmd/a@v1.0.0: argument must be a clean package path$'
+! go install example.com/cmd/a@v1.0.0 ./x@v1.0.0
+stderr '^go: ./x@v1.0.0: argument must be a package path, not a relative path$'
+! go install example.com/cmd/a@v1.0.0 $GOPATH/src/x@v1.0.0
+stderr '^go: '$WORK'[/\\]gopath/src/x@v1.0.0: argument must be a package path, not an absolute path$'
+! go install example.com/cmd/a@v1.0.0 cmd/...@v1.0.0
+stderr '^package cmd/go not provided by module example.com/cmd@v1.0.0$'
+
+# 'go install pkg@version' should accept multiple arguments but report an error
+# if the version suffixes are different, even if they refer to the same version.
+go install example.com/cmd/a@v1.0.0 example.com/cmd/b@v1.0.0
+exists $GOPATH/bin/a$GOEXE
+exists $GOPATH/bin/b$GOEXE
+rm $GOPATH/bin
+
+env GO111MODULE=on
+go list -m example.com/cmd@latest
+stdout '^example.com/cmd v1.0.0$'
+env GO111MODULE=auto
+
+! go install example.com/cmd/a@v1.0.0 example.com/cmd/b@latest
+stderr '^go: example.com/cmd/b@latest: all arguments must refer to packages in the same module at the same version \(@v1.0.0\)$'
+
+
+# 'go install pkg@version' should report an error if the arguments are in
+# different modules.
+! go install example.com/cmd/a@v1.0.0 rsc.io/fortune@v1.0.0
+stderr '^package rsc.io/fortune provided by module rsc.io/fortune@v1.0.0\n\tAll packages must be provided by the same module \(example.com/cmd@v1.0.0\).$'
+
+
+# 'go install pkg@version' should report an error if an argument is not
+# a main package.
+! go install example.com/cmd/a@v1.0.0 example.com/cmd/err@v1.0.0
+stderr '^package example.com/cmd/err is not a main package$'
+
+# Wildcards should match only main packages. This module has a non-main package
+# with an error, so we'll know if that gets built.
+mkdir tmp
+cd tmp
+go mod init m
+go get example.com/cmd@v1.0.0
+! go build example.com/cmd/...
+stderr 'err[/\\]err.go:3:9: undefined: DoesNotCompile( .*)?$'
+cd ..
+
+go install example.com/cmd/...@v1.0.0
+exists $GOPATH/bin/a$GOEXE
+exists $GOPATH/bin/b$GOEXE
+rm $GOPATH/bin
+
+# If a wildcard matches no packages, we should see a warning.
+! go install example.com/cmd/nomatch...@v1.0.0
+stderr '^go: example.com/cmd/nomatch\.\.\.@v1.0.0: module example.com/cmd@v1.0.0 found, but does not contain packages matching example.com/cmd/nomatch\.\.\.$'
+go install example.com/cmd/a@v1.0.0 example.com/cmd/nomatch...@v1.0.0
+stderr '^go: warning: "example.com/cmd/nomatch\.\.\." matched no packages$'
+
+# If a wildcard matches only non-main packages, we should see a different warning.
+go install example.com/cmd/err...@v1.0.0
+stderr '^go: warning: "example.com/cmd/err\.\.\." matched only non-main packages$'
+
+
+# 'go install pkg@version' should report errors if the module contains
+# replace or exclude directives.
+go mod download example.com/cmd@v1.0.0-replace
+! go install example.com/cmd/a@v1.0.0-replace
+cmp stderr replace-err
+
+go mod download example.com/cmd@v1.0.0-exclude
+! go install example.com/cmd/a@v1.0.0-exclude
+cmp stderr exclude-err
+
+# 'go install pkg@version' should report an error if the module requires a
+# higher version of itself.
+! go install example.com/cmd/a@v1.0.0-newerself
+stderr '^go: example.com/cmd/a@v1.0.0-newerself: version constraints conflict:\n\texample.com/cmd@v1.0.0-newerself requires example.com/cmd@v1.0.0, but v1.0.0-newerself is requested$'
+
+
+# 'go install pkg@version' will only match a retracted version if it's
+# explicitly requested.
+env GO111MODULE=on
+go list -m -versions example.com/cmd
+! stdout v1.9.0
+go list -m -versions -retracted example.com/cmd
+stdout v1.9.0
+go install example.com/cmd/a@latest
+go version -m $GOPATH/bin/a$GOEXE
+stdout '^\tmod\texample.com/cmd\tv1.0.0\t'
+go install example.com/cmd/a@v1.9.0
+go version -m $GOPATH/bin/a$GOEXE
+stdout '^\tmod\texample.com/cmd\tv1.9.0\t'
+env GO111MODULE=
+
+# 'go install pkg@version' succeeds when -mod=readonly is set explicitly.
+# Verifies #43278.
+go install -mod=readonly example.com/cmd/a@v1.0.0
+
+-- m/go.mod --
+module m
+
+go 1.16
+
+require example.com/cmd v1.1.0-doesnotexist
+-- x/x.go --
+package main
+
+func main() {}
+-- replace-err --
+go: example.com/cmd/a@v1.0.0-replace (in example.com/cmd@v1.0.0-replace):
+ The go.mod file for the module providing named packages contains one or
+ more replace directives. It must not contain directives that would cause
+ it to be interpreted differently than if it were the main module.
+-- exclude-err --
+go: example.com/cmd/a@v1.0.0-exclude (in example.com/cmd@v1.0.0-exclude):
+ The go.mod file for the module providing named packages contains one or
+ more exclude directives. It must not contain directives that would cause
+ it to be interpreted differently than if it were the main module.
diff --git a/src/cmd/go/testdata/script/mod_install_versioned.txt b/src/cmd/go/testdata/script/mod_install_versioned.txt
new file mode 100644
index 0000000..627a9a8
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_install_versioned.txt
@@ -0,0 +1,14 @@
+env GO111MODULE=on
+
+go get rsc.io/fortune
+go list -f '{{.Target}}' rsc.io/fortune
+! stdout fortune@v1
+stdout 'fortune(\.exe)?$'
+
+go get rsc.io/fortune/v2
+go list -f '{{.Target}}' rsc.io/fortune/v2
+! stdout v2
+stdout 'fortune(\.exe)?$'
+
+-- go.mod --
+module m
diff --git a/src/cmd/go/testdata/script/mod_internal.txt b/src/cmd/go/testdata/script/mod_internal.txt
new file mode 100644
index 0000000..787b21f
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_internal.txt
@@ -0,0 +1,96 @@
+env GO111MODULE=on
+[short] skip
+
+# golang.org/x/internal should be importable from other golang.org/x modules.
+go mod edit -module=golang.org/x/anything
+go get .
+
+# ...and their tests...
+go test
+stdout PASS
+
+# ...but that should not leak into other modules.
+go get ./baddep
+! go build ./baddep
+stderr golang.org[/\\]notx[/\\]useinternal
+stderr 'use of internal package golang.org/x/.* not allowed'
+
+# Internal packages in the standard library should not leak into modules.
+go get ./fromstd
+! go build ./fromstd
+stderr 'use of internal package internal/testenv not allowed'
+
+# Dependencies should be able to use their own internal modules...
+go mod edit -module=golang.org/notx
+go get ./throughdep
+
+# ... but other modules should not, even if they have transitive dependencies.
+go get .
+! go build .
+stderr 'use of internal package golang.org/x/.* not allowed'
+
+# And transitive dependencies still should not leak.
+go get ./baddep
+! go build ./baddep
+stderr golang.org[/\\]notx[/\\]useinternal
+stderr 'use of internal package golang.org/x/.* not allowed'
+
+# Replacing an internal module should keep it internal to the same paths.
+go mod edit -module=golang.org/notx
+go mod edit -replace golang.org/x/internal=./replace/golang.org/notx/internal
+go get ./throughdep
+
+go get ./baddep
+! go build ./baddep
+stderr golang.org[/\\]notx[/\\]useinternal
+stderr 'use of internal package golang.org/x/.* not allowed'
+
+go mod edit -replace golang.org/x/internal=./vendor/golang.org/x/internal
+go get ./throughdep
+
+go get ./baddep
+! go build ./baddep
+stderr golang.org[/\\]notx[/\\]useinternal
+stderr 'use of internal package golang.org/x/.* not allowed'
+
+-- go.mod --
+module TBD
+go 1.12
+-- useinternal.go --
+package useinternal
+import _ "golang.org/x/internal/subtle"
+
+-- useinternal_test.go --
+package useinternal_test
+import (
+ "testing"
+ _ "golang.org/x/internal/subtle"
+)
+
+func Test(*testing.T) {}
+
+-- throughdep/useinternal.go --
+package throughdep
+import _ "golang.org/x/useinternal"
+
+-- baddep/useinternal.go --
+package baddep
+import _ "golang.org/notx/useinternal"
+
+-- fromstd/useinternal.go --
+package fromstd
+import _ "internal/testenv"
+
+-- replace/golang.org/notx/internal/go.mod --
+module golang.org/x/internal
+
+-- replace/golang.org/notx/internal/subtle/subtle.go --
+package subtle
+// Ha ha! Nothing here!
+
+-- vendor/golang.org/x/internal/go.mod --
+module golang.org/x/internal
+
+-- vendor/golang.org/x/internal/subtle/subtle.go --
+package subtle
+// Ha ha! Nothing here!
diff --git a/src/cmd/go/testdata/script/mod_invalid_path.txt b/src/cmd/go/testdata/script/mod_invalid_path.txt
new file mode 100644
index 0000000..975de5e
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_invalid_path.txt
@@ -0,0 +1,61 @@
+# Test that mod files with invalid or missing paths produce an error.
+
+# Test that go list fails on a go.mod with no module declaration.
+cd $WORK/gopath/src/mod
+! go list .
+stderr '^go: error reading go.mod: missing module declaration. To specify the module path:\n\tgo mod edit -module=example.com/mod$'
+
+# Test that go mod init in GOPATH doesn't add a module declaration
+# with a path that can't possibly be a module path, because
+# it isn't even a valid import path.
+# The single quote and backtick are the only characters which are not allowed
+# but are a valid Windows file name.
+cd $WORK/'gopath/src/m''d'
+! go mod init
+stderr 'cannot determine module path'
+
+# Test that a go.mod file is rejected when its module declaration has a path that can't
+# possibly be a module path, because it isn't even a valid import path
+cd $WORK/gopath/src/badname
+! go list .
+stderr 'malformed module path'
+
+# Test that an import path containing an element with a leading dot is valid,
+# but such a module path is not.
+# Verifies #43985.
+cd $WORK/gopath/src/dotname
+go list ./.dot
+stdout '^example.com/dotname/.dot$'
+go list ./use
+stdout '^example.com/dotname/use$'
+! go list -m example.com/dotname/.dot@latest
+stderr '^go: example.com/dotname/.dot@latest: malformed module path "example.com/dotname/.dot": leading dot in path element$'
+go get example.com/dotname/.dot
+go get example.com/dotname/use
+go mod tidy
+
+-- mod/go.mod --
+
+-- mod/foo.go --
+package foo
+
+-- m'd/foo.go --
+package mad
+
+-- badname/go.mod --
+
+module .\.
+
+-- badname/foo.go --
+package badname
+
+-- dotname/go.mod --
+module example.com/dotname
+
+go 1.16
+-- dotname/.dot/dot.go --
+package dot
+-- dotname/use/use.go --
+package use
+
+import _ "example.com/dotname/.dot"
diff --git a/src/cmd/go/testdata/script/mod_invalid_path_dotname.txt b/src/cmd/go/testdata/script/mod_invalid_path_dotname.txt
new file mode 100644
index 0000000..484c208
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_invalid_path_dotname.txt
@@ -0,0 +1,46 @@
+# Test that an import path containing an element with a leading dot
+# in another module is valid.
+
+# 'go get' works with no version query.
+cp go.mod.empty go.mod
+go get example.com/dotname/.dot
+go list -m example.com/dotname
+stdout '^example.com/dotname v1.0.0$'
+
+# 'go get' works with a version query.
+cp go.mod.empty go.mod
+go get example.com/dotname/.dot@latest
+go list -m example.com/dotname
+stdout '^example.com/dotname v1.0.0$'
+
+# 'go get' works on an importing package.
+cp go.mod.empty go.mod
+go get .
+go list -m example.com/dotname
+stdout '^example.com/dotname v1.0.0$'
+
+# 'go list' works on the dotted package.
+go list example.com/dotname/.dot
+stdout '^example.com/dotname/.dot$'
+
+# 'go list' works on an importing package.
+go list .
+stdout '^m$'
+
+# 'go mod tidy' works.
+cp go.mod.empty go.mod
+go mod tidy
+go list -m example.com/dotname
+stdout '^example.com/dotname v1.0.0$'
+
+-- go.mod.empty --
+module m
+
+go 1.16
+-- go.sum --
+example.com/dotname v1.0.0 h1:Q0JMAn464CnwFVCshs1n4+f5EFiW/eRhnx/fTWjw2Ag=
+example.com/dotname v1.0.0/go.mod h1:7K4VLT7QylRI8H7yZwUkeDH2s19wQnyfp/3oBlItWJ0=
+-- use.go --
+package use
+
+import _ "example.com/dotname/.dot"
diff --git a/src/cmd/go/testdata/script/mod_invalid_path_plus.txt b/src/cmd/go/testdata/script/mod_invalid_path_plus.txt
new file mode 100644
index 0000000..dd59eb1
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_invalid_path_plus.txt
@@ -0,0 +1,36 @@
+# https://golang.org/issue/44776
+# The '+' character should be disallowed in module paths, but allowed in package
+# paths within valid modules.
+
+# 'go list' accepts package paths with pluses.
+cp go.mod.orig go.mod
+go get example.net/cmd
+go list example.net/cmd/x++
+
+# 'go list -m' rejects module paths with pluses.
+! go list -versions -m 'example.net/bad++'
+stderr '^go: malformed module path "example.net/bad\+\+": invalid char ''\+''$'
+
+# 'go get' accepts package paths with pluses.
+cp go.mod.orig go.mod
+go get example.net/cmd/x++
+go list -m example.net/cmd
+stdout '^example.net/cmd v0.0.0-00010101000000-000000000000 => ./cmd$'
+
+-- go.mod.orig --
+module example.com/m
+
+go 1.16
+
+replace (
+ example.net/cmd => ./cmd
+)
+
+-- cmd/go.mod --
+module example.net/cmd
+
+go 1.16
+-- cmd/x++/main.go --
+package main
+
+func main() {}
diff --git a/src/cmd/go/testdata/script/mod_invalid_version.txt b/src/cmd/go/testdata/script/mod_invalid_version.txt
new file mode 100644
index 0000000..a0427b3
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_invalid_version.txt
@@ -0,0 +1,253 @@
+[!net:golang.org] skip
+[!git] skip
+
+env GO111MODULE=on
+env GOPROXY=direct
+env GOSUMDB=off
+env GOFLAGS=-mod=mod
+
+# Regression test for golang.org/issue/27173: if the user (or go.mod file)
+# requests a pseudo-version that does not match both the module path and commit
+# metadata, reject it with a helpful error message.
+#
+# TODO(bcmills): Replace the github.com/pierrec/lz4 examples with something
+# equivalent on vcs-test.golang.org.
+
+# An incomplete commit hash is not a valid semantic version,
+# but can appear in the main go.mod file anyway and should be resolved.
+cp go.mod.orig go.mod
+go mod edit -require golang.org/x/text@14c0d48ead0c
+cd outside
+! go list -m golang.org/x/text
+stderr 'go: example.com@v0.0.0 \(replaced by \./\.\.\): parsing ..[/\\]go.mod: '$WORK'[/\\]gopath[/\\]src[/\\]go.mod:5: require golang.org/x/text: version "14c0d48ead0c" invalid: must be of the form v1.2.3'
+cd ..
+go list -m golang.org/x/text
+stdout 'golang.org/x/text v0.1.1-0.20170915032832-14c0d48ead0c'
+grep 'golang.org/x/text v0.1.1-0.20170915032832-14c0d48ead0c' go.mod
+
+# A module path below the repo root that does not contain a go.mod file is invalid.
+cp go.mod.orig go.mod
+go mod edit -require golang.org/x/text/unicode@v0.0.0-20170915032832-14c0d48ead0c
+cd outside
+! go list -m golang.org/x/text
+stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text/unicode@v0.0.0-20170915032832-14c0d48ead0c: invalid version: missing golang.org/x/text/unicode/go.mod at revision 14c0d48ead0c'
+cd ..
+! go list -m golang.org/x/text
+stderr 'golang.org/x/text/unicode@v0.0.0-20170915032832-14c0d48ead0c: invalid version: missing golang.org/x/text/unicode/go.mod at revision 14c0d48ead0c'
+
+# However, arguments to 'go get' can name packages above the root.
+cp go.mod.orig go.mod
+go get golang.org/x/text/unicode@v0.0.0-20170915032832-14c0d48ead0c
+go list -m golang.org/x/text/...
+stdout 'golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c'
+! stdout 'golang.org/x/text/unicode'
+
+# A major version that does not match the module path is invalid.
+cp go.mod.orig go.mod
+go mod edit -require golang.org/x/text@v2.1.1-0.20170915032832-14c0d48ead0c
+cd outside
+! go list -m golang.org/x/text
+stderr 'go: example.com@v0.0.0 \(replaced by \./\.\.\): parsing ..[/\\]go.mod: '$WORK'[/\\]gopath[/\\]src[/\\]go.mod:5: require golang.org/x/text: version "v2.1.1-0.20170915032832-14c0d48ead0c" invalid: should be v0 or v1, not v2'
+cd ..
+! go list -m golang.org/x/text
+stderr '^go.mod:5: require golang.org/x/text: version "v2.1.1-0.20170915032832-14c0d48ead0c" invalid: should be v0 or v1, not v2'
+
+# A pseudo-version with fewer than 12 digits of SHA-1 prefix is invalid.
+cp go.mod.orig go.mod
+go mod edit -require golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0
+cd outside
+! go list -m golang.org/x/text
+stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0: invalid pseudo-version: revision is shorter than canonical \(expected 14c0d48ead0c\)'
+cd ..
+! go list -m golang.org/x/text
+stderr 'golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0: invalid pseudo-version: revision is shorter than canonical \(expected 14c0d48ead0c\)'
+
+# A pseudo-version with more than 12 digits of SHA-1 prefix is invalid.
+cp go.mod.orig go.mod
+go mod edit -require golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0cd47e3104ada247d91be04afc7a5a
+cd outside
+! go list -m golang.org/x/text
+stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0cd47e3104ada247d91be04afc7a5a: invalid pseudo-version: revision is longer than canonical \(expected 14c0d48ead0c\)'
+cd ..
+! go list -m golang.org/x/text
+stderr 'golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0cd47e3104ada247d91be04afc7a5a: invalid pseudo-version: revision is longer than canonical \(expected 14c0d48ead0c\)'
+
+# A pseudo-version that does not match the commit timestamp is invalid.
+cp go.mod.orig go.mod
+go mod edit -require golang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c
+cd outside
+! go list -m golang.org/x/text
+stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c: invalid pseudo-version: does not match version-control timestamp \(expected 20170915032832\)'
+cd ..
+! go list -m golang.org/x/text
+stderr 'golang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c: invalid pseudo-version: does not match version-control timestamp \(expected 20170915032832\)'
+
+# A 'replace' directive in the main module can replace an invalid timestamp
+# with a valid one.
+go mod edit -replace golang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c=golang.org/x/text@14c0d48ead0c
+cd outside
+! go list -m golang.org/x/text
+stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c: invalid pseudo-version: does not match version-control timestamp \(expected 20170915032832\)'
+cd ..
+go list -m golang.org/x/text
+stdout 'golang.org/x/text v0.1.1-0.20190915032832-14c0d48ead0c => golang.org/x/text v0.1.1-0.20170915032832-14c0d48ead0c'
+
+# A pseudo-version that is not derived from a tag is invalid.
+cp go.mod.orig go.mod
+go mod edit -require golang.org/x/text@v1.999.999-0.20170915032832-14c0d48ead0c
+cd outside
+! go list -m golang.org/x/text
+stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v1.999.999-0.20170915032832-14c0d48ead0c: invalid pseudo-version: preceding tag \(v1.999.998\) not found'
+cd ..
+! go list -m golang.org/x/text
+stderr 'golang.org/x/text@v1.999.999-0.20170915032832-14c0d48ead0c: invalid pseudo-version: preceding tag \(v1.999.998\) not found'
+
+# A v1.0.0- pseudo-version that is not derived from a tag is invalid:
+# v1.0.0- implies no tag, but the correct no-tag prefix for a module path
+# without a major-version suffix is v0.0.0-.
+cp go.mod.orig go.mod
+go mod edit -require golang.org/x/text@v1.0.0-20170915032832-14c0d48ead0c
+cd outside
+! go list -m golang.org/x/text
+stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v1.0.0-20170915032832-14c0d48ead0c: invalid pseudo-version: major version without preceding tag must be v0, not v1'
+cd ..
+! go list -m golang.org/x/text
+stderr 'golang.org/x/text@v1.0.0-20170915032832-14c0d48ead0c: invalid pseudo-version: major version without preceding tag must be v0, not v1'
+
+# A pseudo-version vX.Y.Z+1 cannot have Z+1 == 0, since that would
+# imply a base tag with a negative patch field.
+cp go.mod.orig go.mod
+go mod edit -require golang.org/x/text@v0.0.0-0.20170915032832-14c0d48ead0c
+cd outside
+! go list -m golang.org/x/text
+stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.0.0-0.20170915032832-14c0d48ead0c: invalid pseudo-version: version before v0.0.0 would have negative patch number'
+cd ..
+! go list -m golang.org/x/text
+stderr 'golang.org/x/text@v0.0.0-0.20170915032832-14c0d48ead0c: invalid pseudo-version: version before v0.0.0 would have negative patch number'
+
+# A 'replace' directive in the main module can replace an
+# invalid pseudo-version base with a valid one.
+go mod edit -replace golang.org/x/text@v0.0.0-0.20170915032832-14c0d48ead0c=golang.org/x/text@v0.0.0-20170915032832-14c0d48ead0c
+cd outside
+! go list -m golang.org/x/text
+stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.0.0-0.20170915032832-14c0d48ead0c: invalid pseudo-version: version before v0.0.0 would have negative patch number'
+cd ..
+go list -m golang.org/x/text
+stdout 'golang.org/x/text v0.0.0-0.20170915032832-14c0d48ead0c => golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c'
+
+# A 'replace' directive can replace an invalid 'latest' version, and
+# should suppress errors for that version in 'go get -u'
+cp go.mod.orig go.mod
+go mod edit -require golang.org/x/text@v1.999999.0
+go mod edit -replace golang.org/x/text@v1.999999.0=golang.org/x/text@v0.0.0-20170915032832-14c0d48ead0c
+cd outside
+! go get golang.org/x/text@upgrade
+stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v1.999999.0: reading golang.org/x/text/go.mod at revision v1.999999.0: unknown revision v1.999999.0'
+cd ..
+go get golang.org/x/text@upgrade
+go list -m golang.org/x/text
+stdout 'golang.org/x/text v1.999999.0 => golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c'
+
+# A pseudo-version derived from a non-ancestor tag is invalid.
+cp go.mod.orig go.mod
+go mod edit -require golang.org/x/text@v0.2.1-0.20170915032832-14c0d48ead0c
+cd outside
+! go list -m golang.org/x/text
+stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.2.1-0.20170915032832-14c0d48ead0c: invalid pseudo-version: revision 14c0d48ead0c is not a descendent of preceding tag \(v0.2.0\)'
+cd ..
+! go list -m golang.org/x/text
+stderr 'golang.org/x/text@v0.2.1-0.20170915032832-14c0d48ead0c: invalid pseudo-version: revision 14c0d48ead0c is not a descendent of preceding tag \(v0.2.0\)'
+
+# A pseudo-version derived from a canonical tag on the same revision is invalid.
+cp go.mod.orig go.mod
+go mod edit -require golang.org/x/text@v0.2.1-0.20171213102548-c4d099d611ac
+cd outside
+! go list -m golang.org/x/text
+stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.2.1-0.20171213102548-c4d099d611ac: invalid pseudo-version: tag \(v0.2.0\) found on revision c4d099d611ac is already canonical, so should not be replaced with a pseudo-version derived from that tag'
+cd ..
+! go list -m golang.org/x/text
+stderr 'golang.org/x/text@v0.2.1-0.20171213102548-c4d099d611ac: invalid pseudo-version: tag \(v0.2.0\) found on revision c4d099d611ac is already canonical, so should not be replaced with a pseudo-version derived from that tag'
+
+# A +incompatible suffix is not allowed on a version that is actually compatible.
+cp go.mod.orig go.mod
+go mod edit -require golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0c+incompatible
+cd outside
+! go list -m golang.org/x/text
+stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0c\+incompatible: invalid version: \+incompatible suffix not allowed: major version v0 is compatible'
+cd ..
+! go list -m golang.org/x/text
+stderr 'golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0c\+incompatible: invalid version: \+incompatible suffix not allowed: major version v0 is compatible'
+
+[!net:github.com] stop
+
+# The pseudo-version for a commit after a tag with a non-matching major version
+# should instead be based on the last matching tag.
+cp go.mod.orig go.mod
+go mod edit -require github.com/pierrec/lz4@473cd7ce01a1
+go list -m github.com/pierrec/lz4
+stdout 'github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1'
+cd outside
+go list -m github.com/pierrec/lz4
+stdout 'github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1'
+cd ..
+
+# A +incompatible pseudo-version for a module that has an explicit go.mod file is invalid.
+cp go.mod.orig go.mod
+go mod edit -require github.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d+incompatible
+cd outside
+! go list -m github.com/pierrec/lz4
+stderr '^go: example.com@v0.0.0 requires\n\tgithub.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d\+incompatible: invalid version: module contains a go.mod file, so module path must match major version \("github.com/pierrec/lz4/v2"\)$'
+cd ..
+! go list -m github.com/pierrec/lz4
+stderr '^go: github.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d\+incompatible: invalid version: module contains a go.mod file, so module path must match major version \("github.com/pierrec/lz4/v2"\)$'
+
+# A +incompatible pseudo-version is valid for a revision of the module
+# that lacks a go.mod file.
+cp go.mod.orig go.mod
+go mod edit -require github.com/pierrec/lz4@v2.0.4-0.20180826165652-dbe9298ce099+incompatible
+cd outside
+go list -m github.com/pierrec/lz4
+stdout 'github.com/pierrec/lz4 v2.0.4-0.20180826165652-dbe9298ce099\+incompatible'
+cd ..
+go list -m github.com/pierrec/lz4
+stdout 'github.com/pierrec/lz4 v2.0.4-0.20180826165652-dbe9298ce099\+incompatible'
+
+# 'go get' for a mismatched major version without a go.mod file should resolve
+# to the equivalent +incompatible version, not a pseudo-version with a different
+# major version.
+cp go.mod.orig go.mod
+go get github.com/pierrec/lz4@v2.0.5
+go list -m github.com/pierrec/lz4
+stdout 'github.com/pierrec/lz4 v2.0.5\+incompatible'
+
+# 'go get' for a mismatched major version with a go.mod file should error out,
+# not resolve to a pseudo-version with a different major version.
+cp go.mod.orig go.mod
+! go get github.com/pierrec/lz4@v2.0.8
+stderr 'go: github.com/pierrec/lz4@v2.0.8: invalid version: module contains a go.mod file, so module path must match major version \("github.com/pierrec/lz4/v2"\)$'
+
+# An invalid +incompatible suffix for a canonical version should error out,
+# not resolve to a pseudo-version.
+#
+# TODO(bcmills): The "outside" view for this failure mode is missing its import stack.
+# Figure out why and fix it.
+cp go.mod.orig go.mod
+go mod edit -require github.com/pierrec/lz4@v2.0.8+incompatible
+cd outside
+! go list -m github.com/pierrec/lz4
+stderr '^go: github.com/pierrec/lz4@v2.0.8\+incompatible: invalid version: module contains a go.mod file, so module path must match major version \("github.com/pierrec/lz4/v2"\)$'
+cd ..
+! go list -m github.com/pierrec/lz4
+stderr '^go: github.com/pierrec/lz4@v2.0.8\+incompatible: invalid version: module contains a go.mod file, so module path must match major version \("github.com/pierrec/lz4/v2"\)$'
+
+-- go.mod.orig --
+module example.com
+
+go 1.13
+-- outside/go.mod --
+module example.com/outside
+
+go 1.13
+
+require example.com v0.0.0
+replace example.com v0.0.0 => ./..
diff --git a/src/cmd/go/testdata/script/mod_issue35270.txt b/src/cmd/go/testdata/script/mod_issue35270.txt
new file mode 100644
index 0000000..27b9226
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_issue35270.txt
@@ -0,0 +1,57 @@
+
+cd a
+! go build
+stderr '^ambiguous import: found package image in multiple modules:\s+image\s+.+\s.+image.+\s$'
+
+
+cd ../b
+! go build -mod=vendor
+stderr '^main.go:4:5: ambiguous import: found package image in multiple directories:\s+.+image\s+.+image\s+$'
+
+cd ../c
+! go build -mod=vendor
+stderr 'main.go:4:5: package p is not in std'
+
+-- a/go.mod --
+module image
+
+-- a/main.go --
+package main
+
+func main() {
+ println("hello world!")
+}
+
+-- b/go.mod --
+module test
+
+-- b/vendor/image/b.go --
+package image
+func Add(a, b int) int {
+ return a + b
+}
+
+-- b/main.go --
+package main
+
+import (
+ "image"
+)
+
+func main() {
+ println(image.Add(1,1))
+}
+
+-- c/go.mod --
+module test
+
+-- c/main.go --
+package main
+
+import (
+ "p"
+)
+
+func main() {
+ println(p.Add(1,1))
+} \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/mod_issue35317.txt b/src/cmd/go/testdata/script/mod_issue35317.txt
new file mode 100644
index 0000000..92416a5
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_issue35317.txt
@@ -0,0 +1,8 @@
+# Regression test for golang.org/issue/35317:
+# 'go get' with multiple module-only arguments was racy.
+
+env GO111MODULE=on
+[short] skip
+
+go mod init example.com
+go get golang.org/x/text@v0.3.0 golang.org/x/internal@v0.1.0 golang.org/x/exp@none
diff --git a/src/cmd/go/testdata/script/mod_lazy_consistency.txt b/src/cmd/go/testdata/script/mod_lazy_consistency.txt
new file mode 100644
index 0000000..1bf3e31
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_lazy_consistency.txt
@@ -0,0 +1,95 @@
+# If the root requirements in a lazy module are inconsistent
+# (for example, due to a bad hand-edit or git merge),
+# they can go unnoticed as long as the module with the violated
+# requirement is not used.
+# When we load a package from that module, we should spot-check its
+# requirements and either emit an error or update the go.mod file.
+
+cp go.mod go.mod.orig
+
+
+# If we load package x from x.1, we only check the requirements of x,
+# which are fine: loading succeeds.
+
+go list -deps ./usex
+stdout '^example.net/x$'
+cmp go.mod go.mod.orig
+
+
+# However, if we load needx2, we should load the requirements of needx2.
+# Those requirements indicate x.2, not x.1, so the module graph is
+# inconsistent and needs to be fixed.
+
+! go list -deps ./useneedx2
+stderr '^go: updates to go.mod needed; to update it:\n\tgo mod tidy$'
+
+! go list -deps example.net/needx2
+stderr '^go: updates to go.mod needed; to update it:\n\tgo mod tidy$'
+
+
+# The command printed in the error message should fix the problem.
+
+go mod tidy
+go list -deps ./useneedx2
+stdout '^example.net/m/useneedx2$'
+stdout '^example.net/needx2$'
+stdout '^example.net/x$'
+
+go list -m all
+stdout '^example.net/needx2 v0\.1\.0 '
+stdout '^example.net/x v0\.2\.0 '
+
+
+-- go.mod --
+module example.net/m
+
+go 1.17
+
+require (
+ example.net/needx2 v0.1.0
+ example.net/x v0.1.0
+)
+
+replace (
+ example.net/needx2 v0.1.0 => ./needx2.1
+ example.net/x v0.1.0 => ./x.1
+ example.net/x v0.2.0 => ./x.2
+)
+-- useneedx2/useneedx2.go --
+package useneedx2
+
+import _ "example.net/needx2"
+-- usex/usex.go --
+package usex
+
+import _ "example.net/x"
+
+-- x.1/go.mod --
+module example.com/x
+
+go 1.17
+-- x.1/x.go --
+package x
+
+-- x.2/go.mod --
+module example.com/x
+
+go 1.17
+-- x.2/x.go --
+package x
+
+const AddedInV2 = true
+
+-- needx2.1/go.mod --
+module example.com/x
+
+go 1.17
+
+require example.net/x v0.2.0
+-- needx2.1/needx2.go --
+// Package needx2 needs x v0.2.0 or higher.
+package needx2
+
+import "example.net/x"
+
+var _ = x.AddedInV2
diff --git a/src/cmd/go/testdata/script/mod_lazy_downgrade.txt b/src/cmd/go/testdata/script/mod_lazy_downgrade.txt
new file mode 100644
index 0000000..eb69d2e
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_lazy_downgrade.txt
@@ -0,0 +1,183 @@
+# This test illustrates the interaction between lazy loading and downgrading in
+# 'go get'.
+
+# The package import graph used in this test looks like:
+#
+# lazy ---- a
+# |
+# a_test ---- b
+# b_test ---- c
+#
+# The module dependency graph initially looks like:
+#
+# lazy ---- a.1 ---- b.1 ---- c.1
+# \ /
+# b.3 ---- c.2 b.2
+#
+# (Note that lazy loading will prune out the dependency from b.1 on c.1.)
+
+cp go.mod go.mod.orig
+go mod tidy
+cmp go.mod.orig go.mod
+
+go list -m all
+stdout '^example.com/a v0.1.0 '
+stdout '^example.com/b v0.3.0 '
+stdout '^example.com/c v0.2.0 '
+
+# Downgrading c should also downgrade the b that requires it.
+
+go get example.com/c@v0.1.0
+go list -m all
+stdout '^example.com/a v0.1.0 '
+stdout '^example.com/b v0.2.0 '
+stdout '^example.com/c v0.1.0 '
+
+# Removing c entirely should also remove the a and b that require it.
+
+go get example.com/c@none
+go list -m all
+! stdout '^example.com/a '
+! stdout '^example.com/b '
+! stdout '^example.com/c '
+
+
+# With lazy loading, downgrading c should work the same way, but dependencies
+# outside of the deepening scan should not affect the downgrade.
+
+cp go.mod.orig go.mod
+go mod edit -go=1.17
+
+go list -m all
+stdout '^example.com/a v0.1.0 '
+stdout '^example.com/b v0.3.0 '
+stdout '^example.com/c v0.2.0 '
+
+go get example.com/c@v0.1.0
+go list -m all
+stdout '^example.com/a v0.1.0 '
+stdout '^example.com/b v0.2.0 '
+stdout '^example.com/c v0.1.0 '
+
+# At this point, b.2 is still an explicit root, so its dependency on c
+# is still tracked, and it will still be downgraded away if we remove c.
+# ('go get' never makes a root into a non-root. Only 'go mod tidy' does that.)
+
+go get example.com/c@none
+go list -m all
+! stdout '^example.com/a '
+! stdout '^example.com/b '
+! stdout '^example.com/c '
+
+
+# This time, we drop the explicit 'b' root by downgrading it to v0.1.0
+# (the version required by a.1) and running 'go mod tidy'.
+# It is still selected at v0.1.0 (as a dependency of a),
+# but its dependency on c is now pruned from the module graph, so it doesn't
+# result in any downgrades to b or a if we run 'go get c@none'.
+
+cp go.mod.orig go.mod
+go mod edit -go=1.17
+
+go list -m all
+stdout '^example.com/a v0.1.0 '
+stdout '^example.com/b v0.3.0 '
+stdout '^example.com/c v0.2.0 '
+
+go get example.com/c@v0.1.0 example.com/b@v0.1.0
+go list -m all
+stdout '^example.com/a v0.1.0 '
+stdout '^example.com/b v0.1.0 '
+stdout '^example.com/c v0.1.0 '
+
+go mod tidy
+go list -m all
+stdout '^example.com/a v0.1.0 '
+stdout '^example.com/b v0.1.0 '
+! stdout '^example.com/c '
+
+go get example.com/c@none
+go list -m all
+stdout '^example.com/a v0.1.0'
+stdout '^example.com/b v0.1.0'
+! stdout '^example.com/c '
+
+
+-- go.mod --
+module example.com/lazy
+
+go 1.15
+
+require (
+ example.com/a v0.1.0
+ example.com/b v0.3.0 // indirect
+)
+
+replace (
+ example.com/a v0.1.0 => ./a
+ example.com/b v0.1.0 => ./b1
+ example.com/b v0.2.0 => ./b2
+ example.com/b v0.3.0 => ./b3
+ example.com/c v0.1.0 => ./c
+ example.com/c v0.2.0 => ./c
+)
+-- lazy.go --
+package lazy
+
+import _ "example.com/a"
+
+-- a/go.mod --
+module example.com/a
+
+go 1.17
+
+require example.com/b v0.1.0
+-- a/a.go --
+package a
+-- a/a_test.go --
+package a_test
+
+import _ "example.com/b"
+
+-- b1/go.mod --
+module example.com/b
+
+go 1.17
+
+require example.com/c v0.1.0
+-- b1/b.go --
+package b
+-- b1/b_test.go --
+package b_test
+import _ "example.com/c"
+
+-- b2/go.mod --
+module example.com/b
+
+go 1.17
+
+require example.com/c v0.1.0
+-- b2/b.go --
+package b
+-- b2/b_test.go --
+package b_test
+import _ "example.com/c"
+
+-- b3/go.mod --
+module example.com/b
+
+go 1.17
+
+require example.com/c v0.2.0
+-- b3/b.go --
+package b
+-- b3/b_test.go --
+package b_test
+import _ "example.com/c"
+
+-- c/go.mod --
+module example.com/c
+
+go 1.17
+-- c/c.go --
+package c
diff --git a/src/cmd/go/testdata/script/mod_lazy_import_allmod.txt b/src/cmd/go/testdata/script/mod_lazy_import_allmod.txt
new file mode 100644
index 0000000..60d4187
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_lazy_import_allmod.txt
@@ -0,0 +1,191 @@
+# This test demonstrates dependency resolution when the main module imports a
+# new package from a previously-test-only dependency.
+#
+# When lazy loading is active, the loader will not load dependencies of any
+# module whose packages are *only* imported by tests outside the main module. If
+# the main module is changed to import a package from such a module, the
+# dependencies of that module will need to be reloaded.
+
+# The import graph used in this test looks like:
+#
+# m ---- a
+# \ |
+# \ a_test ---- b/x
+# \
+# --------------b/y (new) ---- c
+#
+# Where b/x and b/y are disjoint packages, but both contained in module b.
+#
+# The module dependency graph initially looks like:
+#
+# m ---- a.1 ---- b.1 ---- c.1
+#
+# This configuration is similar to that used in mod_lazy_new_import,
+# but the new import is from what is initially a test-only dependency.
+
+# Control case: in Go 1.14, the original go.mod is tidy,
+# and the dependency on c is eagerly loaded.
+
+cp go.mod go.mod.orig
+go mod tidy
+cmp go.mod.orig go.mod
+
+go list -m all
+stdout '^a v0.1.0 '
+stdout '^b v0.1.0 '
+stdout '^c v0.1.0 '
+
+# After adding a new import of b/y,
+# the import of c from b/y should resolve to the version required by b.
+
+cp m.go m.go.orig
+cp m.go.new m.go
+go mod tidy
+cmp go.mod.new go.mod
+
+go list -m all
+stdout '^a v0.1.0 '
+stdout '^b v0.1.0 '
+stdout '^c v0.1.0 '
+
+# With lazy loading, the go.mod requirements are the same,
+# but the dependency on c is initially pruned out.
+
+cp m.go.orig m.go
+cp go.mod.orig go.mod
+go mod edit -go=1.17
+go mod edit -go=1.17 go.mod.new
+
+cp go.mod go.mod.orig
+go mod tidy
+cmp go.mod.orig go.mod
+
+go list -m all
+stdout '^a v0.1.0 '
+stdout '^b v0.1.0 '
+! stdout '^c '
+
+# After adding a new direct import of b/y,
+# the existing version of b should be promoted to a root,
+# bringing the version of c required by b into the build list.
+
+cp m.go.new m.go
+go mod tidy
+cmp go.mod.lazy go.mod
+
+go list -m all
+stdout '^a v0.1.0 '
+stdout '^b v0.1.0 '
+stdout '^c v0.1.0 '
+
+-- m.go --
+package main
+
+import (
+ "fmt"
+
+ _ "a" // a_test imports b/x.
+)
+
+func main() {
+}
+-- m.go.new --
+package main
+
+import (
+ "fmt"
+
+ _ "a" // a_test imports b/x.
+ "b/y" // This is a new import, not yet reflected in the go.mod file.
+)
+
+func main() {
+ fmt.Println(b.CVersion())
+}
+-- go.mod --
+module m
+
+go 1.14
+
+require a v0.1.0
+
+replace (
+ a v0.1.0 => ./a1
+ b v0.1.0 => ./b1
+ c v0.1.0 => ./c1
+ c v0.2.0 => ./c2
+)
+-- go.mod.new --
+module m
+
+go 1.14
+
+require (
+ a v0.1.0
+ b v0.1.0
+)
+
+replace (
+ a v0.1.0 => ./a1
+ b v0.1.0 => ./b1
+ c v0.1.0 => ./c1
+ c v0.2.0 => ./c2
+)
+-- go.mod.lazy --
+module m
+
+go 1.17
+
+require (
+ a v0.1.0
+ b v0.1.0
+)
+
+require c v0.1.0 // indirect
+
+replace (
+ a v0.1.0 => ./a1
+ b v0.1.0 => ./b1
+ c v0.1.0 => ./c1
+ c v0.2.0 => ./c2
+)
+-- a1/go.mod --
+module a
+
+go 1.17
+
+require b v0.1.0
+-- a1/a.go --
+package a
+-- a1/a_test.go --
+package a_test
+
+import _ "b/x"
+-- b1/go.mod --
+module b
+
+go 1.17
+
+require c v0.1.0
+-- b1/x/x.go --
+package x
+-- b1/y/y.go --
+package y
+
+import "c"
+
+func CVersion() string {
+ return c.Version
+}
+-- c1/go.mod --
+module c
+
+go 1.17
+-- c1/c.go --
+package c
+
+const Version = "v0.1.0"
+-- c2/go.mod --
+This file should be unused.
+-- c2/c.go --
+This file should be unused.
diff --git a/src/cmd/go/testdata/script/mod_lazy_new_import.txt b/src/cmd/go/testdata/script/mod_lazy_new_import.txt
new file mode 100644
index 0000000..520d845
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_lazy_new_import.txt
@@ -0,0 +1,155 @@
+# This test illustrates the use of a deepening scan to resolve transitive
+# imports of imports of new packages from within existing dependencies.
+
+# The package import graph used in this test looks like:
+#
+# lazy ---- a/x ---- b
+# \
+# ---- a/y (new) ---- c
+#
+# Where a/x and a/y are disjoint packages, but both contained in module a.
+#
+# The module dependency graph initially looks like:
+#
+# lazy ---- a.1 ---- b.1
+# \
+# c.1
+
+
+cp go.mod go.mod.old
+cp lazy.go lazy.go.old
+go mod tidy
+cmp go.mod go.mod.old
+
+# Before adding a new import, the go.mod file should
+# enumerate modules for all packages already imported.
+go list all
+cmp go.mod go.mod.old
+
+# When we add a new import of a package in an existing dependency,
+# and that dependency is already tidy, its transitive dependencies
+# should already be present.
+cp lazy.go.new lazy.go
+go list all
+go list -m all
+stdout '^example.com/c v0.1.0' # not v0.2.0 as would be resolved by 'latest'
+cmp go.mod go.mod.old
+
+# Now, we repeat the test with a lazy main module.
+cp lazy.go.old lazy.go
+cp go.mod.117 go.mod
+
+# Before adding a new import, the go.mod file should
+# enumerate modules for all packages already imported.
+go list all
+cmp go.mod go.mod.117
+
+# When a new import is found, we should perform a deepening scan of the existing
+# dependencies and add a requirement on the version required by those
+# dependencies — not re-resolve 'latest'.
+cp lazy.go.new lazy.go
+
+! go list all
+stderr '^go: updates to go.mod needed; to update it:\n\tgo mod tidy$'
+
+go mod tidy
+go list all
+go list -m all
+stdout '^example.com/c v0.1.0' # not v0.2.0 as would be resolved by 'latest'
+
+cmp go.mod go.mod.new
+
+
+-- go.mod --
+module example.com/lazy
+
+go 1.15
+
+require example.com/a v0.1.0
+
+replace (
+ example.com/a v0.1.0 => ./a
+ example.com/b v0.1.0 => ./b
+ example.com/c v0.1.0 => ./c1
+ example.com/c v0.2.0 => ./c2
+)
+-- go.mod.117 --
+module example.com/lazy
+
+go 1.17
+
+require example.com/a v0.1.0
+
+require example.com/b v0.1.0 // indirect
+
+replace (
+ example.com/a v0.1.0 => ./a
+ example.com/b v0.1.0 => ./b
+ example.com/c v0.1.0 => ./c1
+ example.com/c v0.2.0 => ./c2
+)
+-- go.mod.new --
+module example.com/lazy
+
+go 1.17
+
+require example.com/a v0.1.0
+
+require (
+ example.com/b v0.1.0 // indirect
+ example.com/c v0.1.0 // indirect
+)
+
+replace (
+ example.com/a v0.1.0 => ./a
+ example.com/b v0.1.0 => ./b
+ example.com/c v0.1.0 => ./c1
+ example.com/c v0.2.0 => ./c2
+)
+-- lazy.go --
+package lazy
+
+import (
+ _ "example.com/a/x"
+)
+-- lazy.go.new --
+package lazy
+
+import (
+ _ "example.com/a/x"
+ _ "example.com/a/y"
+)
+-- a/go.mod --
+module example.com/a
+
+go 1.15
+
+require (
+ example.com/b v0.1.0
+ example.com/c v0.1.0
+)
+-- a/x/x.go --
+package x
+import _ "example.com/b"
+-- a/y/y.go --
+package y
+import _ "example.com/c"
+-- b/go.mod --
+module example.com/b
+
+go 1.15
+-- b/b.go --
+package b
+-- c1/go.mod --
+module example.com/c
+
+go 1.15
+-- c1/c.go --
+package c
+-- c2/go.mod --
+module example.com/c
+
+go 1.15
+-- c2/c.go --
+package c
+This file should not be used, so this syntax error should be ignored.
diff --git a/src/cmd/go/testdata/script/mod_lazy_test_horizon.txt b/src/cmd/go/testdata/script/mod_lazy_test_horizon.txt
new file mode 100644
index 0000000..7d07eb6
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_lazy_test_horizon.txt
@@ -0,0 +1,131 @@
+# This file demonstrates the effect of lazy loading on the selected
+# versions of test dependencies.
+
+# The package import graph used in this test looks like:
+#
+# m ---- a
+# \ |
+# \ a_test ---- b
+# \ |
+# x b_test
+# | \
+# x_test -------------- c
+#
+# And the module dependency graph looks like:
+#
+# m -- a.1 -- b.1 -- c.2
+# \
+# x.1 ------------ c.1
+
+# Control case: in Go 1.15, the version of c imported by 'go test x' is the
+# version required by module b, even though b_test is not relevant to the main
+# module. (The main module imports a, and a_test imports b, but all of the
+# packages and tests in the main module can be built without b.)
+
+go list -m c
+stdout '^c v0.2.0 '
+
+[!short] go test -v x
+[!short] stdout ' c v0.2.0$'
+
+# With lazy loading, the go.mod requirements are the same,
+# but the irrelevant dependency on c v0.2.0 should be pruned out,
+# leaving only the relevant dependency on c v0.1.0.
+
+go mod edit -go=1.17
+go list -m c
+stdout '^c v0.1.0'
+
+[!short] go test -v x
+[!short] stdout ' c v0.1.0$'
+
+-- m.go --
+package m
+
+import (
+ _ "a"
+ _ "x"
+)
+-- go.mod --
+module m
+
+go 1.15
+
+require (
+ a v0.1.0
+ x v0.1.0
+)
+
+replace (
+ a v0.1.0 => ./a1
+ b v0.1.0 => ./b1
+ c v0.1.0 => ./c1
+ c v0.2.0 => ./c2
+ x v0.1.0 => ./x1
+)
+-- a1/go.mod --
+module a
+
+go 1.17
+
+require b v0.1.0
+-- a1/a.go --
+package a
+-- a1/a_test.go --
+package a_test
+
+import _ "b"
+-- b1/go.mod --
+module b
+
+go 1.17
+
+require c v0.2.0
+-- b1/b.go --
+package b
+-- b1/b_test.go --
+package b_test
+
+import (
+ "c"
+ "testing"
+)
+
+func TestCVersion(t *testing.T) {
+ t.Log(c.Version)
+}
+-- c1/go.mod --
+module c
+
+go 1.17
+-- c1/c.go --
+package c
+
+const Version = "v0.1.0"
+-- c2/go.mod --
+module c
+
+go 1.17
+-- c2/c.go --
+package c
+
+const Version = "v0.2.0"
+-- x1/go.mod --
+module x
+
+go 1.17
+
+require c v0.1.0
+-- x1/x.go --
+package x
+-- x1/x_test.go --
+package x_test
+
+import (
+ "c"
+ "testing"
+)
+
+func TestCVersion(t *testing.T) {
+ t.Log("c", c.Version)
+}
diff --git a/src/cmd/go/testdata/script/mod_lazy_test_of_test_dep.txt b/src/cmd/go/testdata/script/mod_lazy_test_of_test_dep.txt
new file mode 100644
index 0000000..68a5b6d
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_lazy_test_of_test_dep.txt
@@ -0,0 +1,224 @@
+# This file demonstrates the effect of lazy loading on the reproducibility of
+# tests (and tests of test dependencies) outside the main module.
+#
+# It is similar to the cases in mod_all.txt and mod_lazy_test_horizon.txt, but
+# focuses on the effect of "go test" on specific packages instead of the "all"
+# pattern.
+
+# The package import graph used in this test looks like:
+#
+# lazy ---- a
+# |
+# a_test ---- b
+# |
+# b_test ---- c
+#
+# And the non-lazy module dependency graph looks like:
+#
+# lazy ---- a.1 ---- b.1 ---- c.1
+
+cp go.mod go.mod.old
+go mod tidy
+cmp go.mod go.mod.old
+
+
+# In Go 1.15 mode, 'go list -m all' includes modules needed by the
+# transitive closure of tests of dependencies of tests of dependencies of ….
+
+go list -m all
+stdout '^example.com/b v0.1.0 '
+stdout '^example.com/c v0.1.0 '
+cmp go.mod go.mod.old
+
+# 'go test' (or equivalent) of any such dependency, no matter how remote, does
+# not update the go.mod file.
+
+go list -test -deps example.com/a
+stdout example.com/b
+! stdout example.com/c
+
+[!short] go test -c -o $devnull example.com/a
+[!short] cmp go.mod go.mod.old
+
+go list -test -deps example.com/b
+stdout example.com/c
+
+[!short] go test -c -o $devnull example.com/b
+[!short] cmp go.mod go.mod.old
+
+go mod edit -go=1.17 a/go.mod
+go mod edit -go=1.17 b1/go.mod
+go mod edit -go=1.17 b2/go.mod
+go mod edit -go=1.17 c1/go.mod
+go mod edit -go=1.17 c2/go.mod
+go mod edit -go=1.17
+
+
+# After changing to 'go 1.17` uniformly, 'go list -m all' should prune out
+# example.com/c, because it is not imported by any package (or test of a package)
+# transitively imported by the main module.
+#
+# example.com/a is imported,
+# and example.com/b is needed in order to run 'go test example.com/a',
+# but example.com/c is not needed because we don't expect the user to need to run
+# 'go test example.com/b'.
+
+# If we skip directly to adding a new import of c, the dependency is too far
+# away for a deepening scan to find, which is fine because the package whose
+# test imported it wasn't even it "all". It should resolve from the latest
+# version of its module.
+
+# However, if we reach c by running successive tests starting from the main
+# module, we should end up with exactly the version required by b, with an update
+# to the go.mod file as soon as we test a test dependency that is not itself in
+# "all".
+
+cp go.mod go.mod.117
+go mod tidy
+cmp go.mod go.mod.117
+
+go list -m all
+stdout '^example.com/b v0.1.0 '
+! stdout '^example.com/c '
+
+# 'go test' of a package (transitively) imported by the main module
+# should work without changes to the go.mod file.
+
+go list -test -deps example.com/a
+stdout example.com/b
+! stdout example.com/c
+
+[!short] go test -c -o $devnull example.com/a
+
+# However, 'go test' of a package that is itself a dependency should require an
+# update to the go.mod file.
+! go list -test -deps example.com/b
+
+ # TODO(#36460): The hint here is wrong. We should suggest
+ # 'go get -t example.com/b@v0.1.0' instead of 'go mod tidy'.
+stderr '^go: updates to go\.mod needed; to update it:\n\tgo mod tidy$'
+
+[!short] ! go test -c -o $devnull example.com/b
+[!short] stderr '^go: updates to go\.mod needed; to update it:\n\tgo mod tidy$'
+
+go get -t example.com/b@v0.1.0
+go list -test -deps example.com/b
+stdout example.com/c
+
+[!short] go test -c -o $devnull example.com/b
+
+# The update should bring the version required by b, not the latest version of c.
+
+go list -m example.com/c
+stdout '^example.com/c v0.1.0 '
+
+cmp go.mod go.mod.b
+
+
+# We should reach the same state if we arrive at it via `go test -mod=mod`.
+
+cp go.mod.117 go.mod
+
+[short] go list -mod=mod -test -deps example.com/a
+[!short] go test -mod=mod -c -o $devnull example.com/a
+
+[short] go list -mod=mod -test -deps example.com/b
+[!short] go test -mod=mod -c -o $devnull example.com/b
+
+cmp go.mod go.mod.b
+
+
+
+-- go.mod --
+module example.com/lazy
+
+go 1.15
+
+require example.com/a v0.1.0
+
+replace (
+ example.com/a v0.1.0 => ./a
+ example.com/b v0.1.0 => ./b1
+ example.com/b v0.2.0 => ./b2
+ example.com/c v0.1.0 => ./c1
+ example.com/c v0.2.0 => ./c2
+)
+-- go.mod.b --
+module example.com/lazy
+
+go 1.17
+
+require example.com/a v0.1.0
+
+require example.com/b v0.1.0 // indirect
+
+replace (
+ example.com/a v0.1.0 => ./a
+ example.com/b v0.1.0 => ./b1
+ example.com/b v0.2.0 => ./b2
+ example.com/c v0.1.0 => ./c1
+ example.com/c v0.2.0 => ./c2
+)
+-- lazy.go --
+package lazy
+
+import (
+ _ "example.com/a"
+)
+-- a/go.mod --
+module example.com/a
+
+go 1.15
+
+require example.com/b v0.1.0
+-- a/a.go --
+package a
+-- a/a_test.go --
+package a
+
+import (
+ "testing"
+
+ _ "example.com/b"
+)
+
+func TestUsingB(t *testing.T) {
+ // …
+}
+-- b1/go.mod --
+module example.com/b
+
+go 1.15
+
+require example.com/c v0.1.0
+-- b1/b.go --
+package b
+-- b1/b_test.go --
+package b
+
+import _ "example.com/c"
+-- b2/go.mod --
+module example.com/b
+
+go 1.15
+
+require example.com/c v0.1.0
+-- b2/b.go --
+package b
+This file should not be used, so this syntax error should be ignored.
+-- b2/b_test.go --
+package b
+This file should not be used, so this syntax error should be ignored.
+-- c1/go.mod --
+module example.com/c
+
+go 1.15
+-- c1/c.go --
+package c
+-- c2/go.mod --
+module example.com/c
+
+go 1.15
+-- c2/c.go --
+package c
+This file should not be used, so this syntax error should be ignored.
diff --git a/src/cmd/go/testdata/script/mod_list.txt b/src/cmd/go/testdata/script/mod_list.txt
new file mode 100644
index 0000000..06316cc
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_list.txt
@@ -0,0 +1,62 @@
+env GO111MODULE=on
+[short] skip
+
+# list {{.Dir}} shows main module and go.mod but not not-yet-downloaded dependency dir.
+go list -mod=mod -m -f '{{.Path}} {{.Main}} {{.GoMod}} {{.Dir}}' all
+stdout '^x true .*[\\/]src[\\/]go.mod .*[\\/]src$'
+stdout '^rsc.io/quote false .*[\\/]v1.5.2.mod $'
+
+# list {{.Dir}} shows dependency after download (and go list without -m downloads it)
+go list -mod=mod -f '{{.Dir}}' rsc.io/quote
+stdout '.*mod[\\/]rsc.io[\\/]quote@v1.5.2$'
+
+# downloaded dependencies are read-only
+exists -readonly $GOPATH/pkg/mod/rsc.io/quote@v1.5.2
+exists -readonly $GOPATH/pkg/mod/rsc.io/quote@v1.5.2/buggy
+
+# go clean -modcache can delete read-only dependencies
+go clean -modcache
+! exists $GOPATH/pkg/mod/rsc.io/quote@v1.5.2
+
+# list {{.Dir}} shows replaced directories
+cp go.mod2 go.mod
+go list -mod=mod -f {{.Dir}} rsc.io/quote
+go list -m -f '{{.Path}} {{.Version}} {{.Dir}}{{with .Replace}} {{.GoMod}} => {{.Version}} {{.Dir}} {{.GoMod}}{{end}}' all
+stdout 'mod[\\/]rsc.io[\\/]quote@v1.5.1'
+stdout 'v1.3.0.*mod[\\/]rsc.io[\\/]sampler@v1.3.1 .*[\\/]v1.3.1.mod => v1.3.1.*sampler@v1.3.1 .*[\\/]v1.3.1.mod'
+
+# list std should work
+go list std
+stdout ^math/big
+
+# rsc.io/quote/buggy should be listable as a package,
+# even though it is only a test.
+go list -mod=mod rsc.io/quote/buggy
+
+# rsc.io/quote/buggy should not be listable as a module
+go list -m -e -f '{{.Error.Err}}' nonexist rsc.io/quote/buggy
+stdout '^module nonexist: not a known dependency$'
+stdout '^module rsc.io/quote/buggy: not a known dependency$'
+
+! go list -m nonexist rsc.io/quote/buggy
+stderr '^go: module nonexist: not a known dependency'
+stderr '^go: module rsc.io/quote/buggy: not a known dependency'
+
+# Module loader does not interfere with list -e (golang.org/issue/24149).
+go list -e -f '{{.Error.Err}}' database
+stdout 'no Go files in '
+! go list database
+stderr 'no Go files in '
+
+-- go.mod --
+module x
+require rsc.io/quote v1.5.2
+
+-- go.mod2 --
+module x
+require rsc.io/quote v1.5.1
+replace rsc.io/sampler v1.3.0 => rsc.io/sampler v1.3.1
+
+-- x.go --
+package x
+import _ "rsc.io/quote"
diff --git a/src/cmd/go/testdata/script/mod_list_bad_import.txt b/src/cmd/go/testdata/script/mod_list_bad_import.txt
new file mode 100644
index 0000000..b128408
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_list_bad_import.txt
@@ -0,0 +1,75 @@
+# This test matches list_bad_import, but in module mode.
+# Please keep them in sync.
+
+env GO111MODULE=on
+cd example.com
+
+# Without -e, listing an otherwise-valid package with an unsatisfied direct import should fail.
+# BUG: Today it succeeds.
+go list -f '{{if .Error}}error{{end}} {{if .Incomplete}}incomplete{{end}} {{range .DepsErrors}}bad dep: {{.Err}}{{end}}' example.com/direct
+! stdout ^error
+stdout 'incomplete'
+stdout 'bad dep: .*example.com/notfound'
+
+# Listing with -deps should also fail.
+! go list -deps example.com/direct
+stderr example.com/notfound
+
+# But -e -deps should succeed.
+go list -e -deps example.com/direct
+stdout example.com/notfound
+
+
+# Listing an otherwise-valid package that imports some *other* package with an
+# unsatisfied import should also fail.
+# BUG: Today, it succeeds.
+go list -f '{{if .Error}}error{{end}} {{if .Incomplete}}incomplete{{end}} {{range .DepsErrors}}bad dep: {{.Err}}{{end}}' example.com/indirect
+! stdout ^error
+stdout incomplete
+stdout 'bad dep: .*example.com/notfound'
+
+# Again, -deps should fail.
+! go list -deps example.com/indirect
+stderr example.com/notfound
+
+# But -e -deps should succeed.
+go list -e -deps example.com/indirect
+stdout example.com/notfound
+
+
+# Listing the missing dependency directly should fail outright...
+! go list -f '{{if .Error}}error{{end}} {{if .Incomplete}}incomplete{{end}}' example.com/notfound
+stderr 'no required module provides package example.com/notfound; to add it:\n\tgo get example.com/notfound'
+! stdout error
+! stdout incomplete
+
+# ...but listing with -e should succeed.
+go list -e -f '{{if .Error}}error{{end}} {{if .Incomplete}}incomplete{{end}}' example.com/notfound
+stdout error
+stdout incomplete
+
+
+# The pattern "all" should match only packages that actually exist,
+# ignoring those whose existence is merely implied by imports.
+go list -e -f '{{.ImportPath}} {{.Error}}' all
+stdout example.com/direct
+stdout example.com/indirect
+# TODO: go list creates a dummy package with the import-not-found
+# but really the Error belongs on example.com/direct, and this package
+# should not be printed.
+# ! stdout example.com/notfound
+
+
+-- example.com/go.mod --
+module example.com
+
+-- example.com/direct/direct.go --
+package direct
+import _ "example.com/notfound"
+
+-- example.com/indirect/indirect.go --
+package indirect
+import _ "example.com/direct"
+
+-- example.com/notfound/README --
+This directory intentionally left blank.
diff --git a/src/cmd/go/testdata/script/mod_list_command_line_arguments.txt b/src/cmd/go/testdata/script/mod_list_command_line_arguments.txt
new file mode 100644
index 0000000..25c68c5
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_list_command_line_arguments.txt
@@ -0,0 +1,35 @@
+# The command-line-arguments package does not belong to a module...
+cd a
+go list -f '{{.Module}}' ../b/b.go
+stdout '^<nil>$'
+
+# ... even if the arguments are sources from that module
+go list -f '{{.Module}}' a.go
+stdout '^<nil>$'
+
+[short] skip
+
+# check that the version of command-line-arguments doesn't include a module
+go build -o a.exe a.go
+go version -m a.exe
+stdout '^\tpath\tcommand-line-arguments$'
+stdout '^\tdep\ta\t\(devel\)\t$'
+! stdout mod[^e]
+
+-- a/go.mod --
+module a
+go 1.17
+-- a/a.go --
+package main
+
+import "a/dep"
+
+func main() {
+ dep.D()
+}
+-- a/dep/dep.go --
+package dep
+
+func D() {}
+-- b/b.go --
+package b \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/mod_list_compiled_concurrent.txt b/src/cmd/go/testdata/script/mod_list_compiled_concurrent.txt
new file mode 100644
index 0000000..195f7b1
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_list_compiled_concurrent.txt
@@ -0,0 +1,21 @@
+env GO111MODULE=on
+
+[short] skip
+[!cgo] skip
+
+# Regression test for golang.org/issue/29667:
+# spurious 'failed to cache compiled Go files' errors.
+
+env GOCACHE=$WORK/gocache
+mkdir $GOCACHE
+
+go list -json -compiled -test=false -export=false -deps=true -- . &
+go list -json -compiled -test=false -export=false -deps=true -- . &
+wait
+
+-- go.mod --
+module sandbox/bar
+-- bar.go --
+package bar
+
+import "C"
diff --git a/src/cmd/go/testdata/script/mod_list_deprecated.txt b/src/cmd/go/testdata/script/mod_list_deprecated.txt
new file mode 100644
index 0000000..ee985cc
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_list_deprecated.txt
@@ -0,0 +1,52 @@
+# 'go list pkg' does not show deprecation.
+go list example.com/deprecated/a
+stdout '^example.com/deprecated/a$'
+
+# 'go list -m' does not show deprecation.
+go list -m example.com/deprecated/a
+stdout '^example.com/deprecated/a v1.9.0$'
+
+# 'go list -m -versions' does not show deprecation.
+go list -m -versions example.com/deprecated/a
+stdout '^example.com/deprecated/a v1.0.0 v1.9.0$'
+
+# 'go list -m -u' shows deprecation.
+go list -m -u example.com/deprecated/a
+stdout '^example.com/deprecated/a v1.9.0 \(deprecated\)$'
+
+# 'go list -m -u -f' exposes the deprecation message.
+go list -m -u -f {{.Deprecated}} example.com/deprecated/a
+stdout '^in example.com/deprecated/a@v1.9.0$'
+
+# This works even if we use an old version that does not have the deprecation
+# message in its go.mod file.
+go get example.com/deprecated/a@v1.0.0
+! grep Deprecated: $WORK/gopath/pkg/mod/cache/download/example.com/deprecated/a/@v/v1.0.0.mod
+go list -m -u -f {{.Deprecated}} example.com/deprecated/a
+stdout '^in example.com/deprecated/a@v1.9.0$'
+
+# 'go list -m -u' does not show deprecation for the main module.
+go list -m -u
+! stdout deprecated
+go list -m -u -f '{{if not .Deprecated}}ok{{end}}'
+stdout ok
+
+# 'go list -m -u' does not show a deprecation message for a module that is not
+# deprecated at the latest version, even if it is deprecated at the current
+# version.
+go list -m -u example.com/undeprecated
+stdout '^example.com/undeprecated v1.0.0 \[v1.0.1\]$'
+-- go.mod --
+// Deprecated: main module is deprecated, too!
+module example.com/use
+
+go 1.17
+
+require (
+ example.com/deprecated/a v1.9.0
+ example.com/undeprecated v1.0.0
+)
+-- go.sum --
+example.com/deprecated/a v1.9.0 h1:pRyvBIZheJpQVVnNW4Fdg8QuoqDgtkCreqZZbASV3BE=
+example.com/deprecated/a v1.9.0/go.mod h1:Z1uUVshSY9kh6l/2hZ8oA9SBviX2yfaeEpcLDz6AZwY=
+example.com/undeprecated v1.0.0/go.mod h1:1qiRbdA9VzJXDqlG26Y41O5Z7YyO+jAD9do8XCZQ+Gg=
diff --git a/src/cmd/go/testdata/script/mod_list_deprecated_replace.txt b/src/cmd/go/testdata/script/mod_list_deprecated_replace.txt
new file mode 100644
index 0000000..48b991f
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_list_deprecated_replace.txt
@@ -0,0 +1,68 @@
+# When all versions are replaced, we should not look up a deprecation message.
+# We will still look up a deprecation message for the replacement.
+cp go.mod.allreplaced go.mod
+go list -m -u -f '{{.Path}}@{{.Version}} <{{.Deprecated}}>{{with .Replace}} => {{.Path}}@{{.Version}} <{{.Deprecated}}>{{end}}' all
+stdout '^example.com/deprecated/a@v1.0.0 <> => example.com/deprecated/b@v1.0.0 <in example.com/deprecated/b@v1.9.0>$'
+
+# When one version is replaced, we should see a deprecation message.
+cp go.mod.onereplaced go.mod
+go list -m -u -f '{{.Path}}@{{.Version}} <{{.Deprecated}}>{{with .Replace}} => {{.Path}}@{{.Version}} <{{.Deprecated}}>{{end}}' all
+stdout '^example.com/deprecated/a@v1.0.0 <in example.com/deprecated/a@v1.9.0> => example.com/deprecated/b@v1.0.0 <in example.com/deprecated/b@v1.9.0>$'
+
+# If the replacement is a directory, we won't look that up.
+cp go.mod.dirreplacement go.mod
+go list -m -u -f '{{.Path}}@{{.Version}} <{{.Deprecated}}>{{with .Replace}} => {{.Path}}@{{.Version}} <{{.Deprecated}}>{{end}}' all
+stdout '^example.com/deprecated/a@v1.0.0 <> => ./a@ <>$'
+
+# If the latest version of the replacement is replaced, we'll use the content
+# from that replacement.
+cp go.mod.latestreplaced go.mod
+go list -m -u -f '{{.Path}}@{{.Version}} <{{.Deprecated}}>{{with .Replace}} => {{.Path}}@{{.Version}} <{{.Deprecated}}>{{end}}' all
+stdout '^example.com/deprecated/a@v1.0.0 <> => example.com/deprecated/b@v1.0.0 <in ./b>$'
+
+-- go.mod.allreplaced --
+module m
+
+go 1.17
+
+require example.com/deprecated/a v1.0.0
+
+replace example.com/deprecated/a => example.com/deprecated/b v1.0.0
+-- go.mod.onereplaced --
+module m
+
+go 1.17
+
+require example.com/deprecated/a v1.0.0
+
+replace example.com/deprecated/a v1.0.0 => example.com/deprecated/b v1.0.0
+-- go.mod.dirreplacement --
+module m
+
+go 1.17
+
+require example.com/deprecated/a v1.0.0
+
+replace example.com/deprecated/a => ./a
+-- go.mod.latestreplaced --
+module m
+
+go 1.17
+
+require example.com/deprecated/a v1.0.0
+
+replace (
+ example.com/deprecated/a => example.com/deprecated/b v1.0.0
+ example.com/deprecated/b v1.9.0 => ./b
+)
+-- go.sum --
+example.com/deprecated/b v1.0.0/go.mod h1:b19J9ywRGviY7Nq4aJ1WBJ+A7qUlEY9ihp22yI4/F6M=
+-- a/go.mod --
+module example.com/deprecated/a
+
+go 1.17
+-- b/go.mod --
+// Deprecated: in ./b
+module example.com/deprecated/b
+
+go 1.17
diff --git a/src/cmd/go/testdata/script/mod_list_dir.txt b/src/cmd/go/testdata/script/mod_list_dir.txt
new file mode 100644
index 0000000..157d3b6
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_list_dir.txt
@@ -0,0 +1,36 @@
+[short] skip
+
+# go list with path to directory should work
+
+# populate go.sum
+go get
+
+env GO111MODULE=off
+go list -f '{{.ImportPath}}' $GOROOT/src/math
+stdout ^math$
+
+env GO111MODULE=on
+go list -f '{{.ImportPath}}' $GOROOT/src/math
+stdout ^math$
+go list -f '{{.ImportPath}}' .
+stdout ^x$
+
+go mod download rsc.io/quote@v1.5.2
+go list -f '{{.ImportPath}}' $GOPATH/pkg/mod/rsc.io/quote@v1.5.2
+stdout '^rsc.io/quote$'
+go list -f '{{.ImportPath}}' $GOPATH/pkg/mod/rsc.io/sampler@v1.3.0
+stdout '^rsc.io/sampler$'
+go get rsc.io/sampler@v1.3.1
+go list -f '{{.ImportPath}}' $GOPATH/pkg/mod/rsc.io/sampler@v1.3.1
+stdout '^rsc.io/sampler$'
+! go list -f '{{.ImportPath}}' $GOPATH/pkg/mod/rsc.io/sampler@v1.3.0
+stderr 'outside main module or its selected dependencies'
+
+-- go.mod --
+module x
+require rsc.io/quote v1.5.2
+
+-- x.go --
+package x
+
+import _ "rsc.io/quote"
diff --git a/src/cmd/go/testdata/script/mod_list_direct.txt b/src/cmd/go/testdata/script/mod_list_direct.txt
new file mode 100644
index 0000000..8bab330
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_list_direct.txt
@@ -0,0 +1,24 @@
+env GO111MODULE=on
+env GOPROXY=direct
+env GOSUMDB=off
+
+[short] skip
+[!git] skip
+
+# golang.org/issue/33099: if an import path ends in a major-version suffix,
+# ensure that 'direct' mode can resolve the package to the module.
+# For a while, (*modfetch.codeRepo).Stat was not checking for a go.mod file,
+# which would produce a hard error at the subsequent call to GoMod.
+
+go get -v
+
+-- go.mod --
+module example.com
+go 1.13
+
+-- main.go --
+package main
+
+import _ "vcs-test.golang.org/git/v3pkg.git/v3"
+
+func main() {}
diff --git a/src/cmd/go/testdata/script/mod_list_e_readonly.txt b/src/cmd/go/testdata/script/mod_list_e_readonly.txt
new file mode 100644
index 0000000..4969434
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_list_e_readonly.txt
@@ -0,0 +1,15 @@
+# 'go list -mod=readonly -e should attribute errors
+# to individual missing packages.
+# Verifies golang.org/issue/34829.
+go list -mod=readonly -e -deps -f '{{if .Error}}{{.ImportPath}}: {{.Error}}{{end}}' .
+stdout 'example.com/missing: use.go:3:8: cannot find module providing package example.com/missing: import lookup disabled by -mod=readonly'
+
+-- go.mod --
+module example.com/m
+
+go 1.14
+
+-- use.go --
+package use
+
+import _ "example.com/missing"
diff --git a/src/cmd/go/testdata/script/mod_list_issue61415.txt b/src/cmd/go/testdata/script/mod_list_issue61415.txt
new file mode 100644
index 0000000..e763fae
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_list_issue61415.txt
@@ -0,0 +1,76 @@
+[short] skip 'generates a vcstest git repo'
+[!git] skip
+
+env GOPROXY=direct
+
+# Control case: fetching a nested module at a tag that exists should
+# emit Origin metadata for that tag and commit, and the origin should
+# be reusable for that tag.
+
+go list -json -m --versions -e vcs-test.golang.org/git/issue61415.git/nested@has-nested
+cp stdout has-nested.json
+stdout '"Origin":'
+stdout '"VCS": "git"'
+stdout '"URL":' # randomly-chosen vcweb localhost URL
+stdout '"Subdir": "nested"'
+stdout '"TagPrefix": "nested/"'
+stdout '"TagSum": "t1:47DEQpj8HBSa\+/TImW\+5JCeuQeRkm5NMpJWZG3hSuFU="'
+stdout '"Ref": "refs/tags/has-nested"'
+stdout '"Hash": "08a4fa6bb9c04ffba03b26ae427b0d6335d90a2a"'
+
+go list -reuse=has-nested.json -json -m --versions -e vcs-test.golang.org/git/issue61415.git/nested@has-nested
+stdout '"Origin":'
+stdout '"VCS": "git"'
+stdout '"URL":' # randomly-chosen vcweb localhost URL
+stdout '"Subdir": "nested"'
+stdout '"TagPrefix": "nested/"'
+stdout '"TagSum": "t1:47DEQpj8HBSa\+/TImW\+5JCeuQeRkm5NMpJWZG3hSuFU="'
+stdout '"Ref": "refs/tags/has-nested"'
+stdout '"Hash": "08a4fa6bb9c04ffba03b26ae427b0d6335d90a2a"'
+stdout '"Reuse": true'
+
+
+# Experiment case: if the nested module doesn't exist at "latest",
+# the Origin metadata should include the ref that we tried to resolve
+# (HEAD for a repo without version tags) and the hash to which it refers,
+# so that changing the HEAD ref will invalidate the result.
+
+go list -json -m --versions -e vcs-test.golang.org/git/issue61415.git/nested@latest
+cp stdout no-nested.json
+stdout '"Err": "module vcs-test.golang.org/git/issue61415.git/nested: no matching versions for query \\"latest\\""'
+stdout '"URL":' # randomly-chosen vcweb localhost URL
+stdout '"Subdir": "nested"'
+stdout '"TagPrefix": "nested/"'
+stdout '"TagSum": "t1:47DEQpj8HBSa\+/TImW\+5JCeuQeRkm5NMpJWZG3hSuFU="'
+
+stdout '"Ref": "HEAD"'
+stdout '"Hash": "f213069baa68ec26412fb373c7cf6669db1f8e69"'
+
+# The error result should be reusable.
+
+go list -reuse=no-nested.json -json -m --versions -e vcs-test.golang.org/git/issue61415.git/nested@latest
+
+stdout '"Err": "module vcs-test.golang.org/git/issue61415.git/nested: no matching versions for query \\"latest\\""'
+stdout '"URL":' # randomly-chosen vcweb localhost URL
+stdout '"Subdir": "nested"'
+stdout '"TagPrefix": "nested/"'
+stdout '"TagSum": "t1:47DEQpj8HBSa\+/TImW\+5JCeuQeRkm5NMpJWZG3hSuFU="'
+stdout '"Ref": "HEAD"'
+stdout '"Hash": "f213069baa68ec26412fb373c7cf6669db1f8e69"'
+stdout '"Reuse": true'
+
+
+# If the hash refers to some other commit instead, the
+# result should not be reused.
+
+replace f213069baa68ec26412fb373c7cf6669db1f8e69 08a4fa6bb9c04ffba03b26ae427b0d6335d90a2a no-nested.json
+
+go list -reuse=no-nested.json -json -m --versions -e vcs-test.golang.org/git/issue61415.git/nested@latest
+stdout '"Err": "module vcs-test.golang.org/git/issue61415.git/nested: no matching versions for query \\"latest\\""'
+stdout '"URL":' # randomly-chosen vcweb localhost URL
+stdout '"Subdir": "nested"'
+stdout '"TagPrefix": "nested/"'
+stdout '"TagSum": "t1:47DEQpj8HBSa\+/TImW\+5JCeuQeRkm5NMpJWZG3hSuFU="'
+stdout '"Ref": "HEAD"'
+stdout '"Hash": "f213069baa68ec26412fb373c7cf6669db1f8e69"'
+! stdout '"Reuse"'
diff --git a/src/cmd/go/testdata/script/mod_list_issue61423.txt b/src/cmd/go/testdata/script/mod_list_issue61423.txt
new file mode 100644
index 0000000..2888391
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_list_issue61423.txt
@@ -0,0 +1,100 @@
+[short] skip 'generates a vcstest git repo'
+[!git] skip
+
+mkdir $WORK/mod1
+mkdir $WORK/mod2
+env GONOSUMDB=vcs-test.golang.org
+
+env GOPROXY=direct
+env GOMODCACHE=$WORK/mod1
+
+
+# If we query a module version from a git repo, we expect its
+# Origin data to be reusable.
+
+go list -m -json vcs-test.golang.org/git/issue61415.git@latest
+cp stdout git-latest.json
+stdout '"Version": "v0.0.0-20231114180001-f213069baa68"'
+stdout '"Origin":'
+stdout '"VCS": "git"'
+stdout '"Hash": "f213069baa68ec26412fb373c7cf6669db1f8e69"'
+stdout '"Ref": "HEAD"'
+stdout '"TagSum": "t1:47DEQpj8HBSa\+/TImW\+5JCeuQeRkm5NMpJWZG3hSuFU="'
+
+go list -reuse=git-latest.json -m -json vcs-test.golang.org/git/issue61415.git@latest
+stdout '"Version": "v0.0.0-20231114180001-f213069baa68"'
+stdout '"Origin":'
+stdout '"VCS": "git"'
+stdout '"Hash": "f213069baa68ec26412fb373c7cf6669db1f8e69"'
+stdout '"Ref": "HEAD"'
+stdout '"TagSum": "t1:47DEQpj8HBSa\+/TImW\+5JCeuQeRkm5NMpJWZG3hSuFU="'
+stdout '"Reuse": true'
+
+
+# Now we construct a filesystem-based module proxy that
+# contains only an older commit.
+
+go clean -modcache
+
+go mod download -json vcs-test.golang.org/git/issue61415.git@08a4fa6bb9c04ffba03b26ae427b0d6335d90a2a
+stdout '"Version": "v0.0.0-20231114180000-08a4fa6bb9c0"'
+stdout '"Origin":'
+stdout '"VCS": "git"'
+stdout '"Hash": "08a4fa6bb9c04ffba03b26ae427b0d6335d90a2a"'
+
+[GOOS:windows] env GOPROXY=file:///$WORK/mod1/cache/download
+[!GOOS:windows] env GOPROXY=file://$WORK/mod1/cache/download
+env GOMODCACHE=$WORK/modcache2
+
+
+# If we resolve the "latest" version query using a proxy,
+# it is only going to have Git origin information about the one
+# commit — not the other tags that would go into resolving
+# the underlying version list.
+# 'go list' should not emit the partial information,
+# since it isn't enough to reconstruct the result.
+
+go list -m -json vcs-test.golang.org/git/issue61415.git@latest
+cp stdout proxy-latest.json
+stdout '"Version": "v0.0.0-20231114180000-08a4fa6bb9c0"'
+! stdout '"Origin":'
+
+# However, if we list a specific, stable version, we should get
+# whatever origin metadata the proxy has for the version.
+
+go list -m -json vcs-test.golang.org/git/issue61415.git@v0.0.0-20231114180000-08a4fa6bb9c0
+cp stdout proxy-version.json
+stdout '"Version": "v0.0.0-20231114180000-08a4fa6bb9c0"'
+stdout '"Origin":'
+stdout '"VCS": "git"'
+stdout '"Hash": "08a4fa6bb9c04ffba03b26ae427b0d6335d90a2a"'
+! stdout '"Ref":'
+! stdout '"TagSum":'
+
+# The -reuse flag has no effect with a proxy, since the proxy can serve
+# metadata about a given module version cheaply anyway.
+
+go list -reuse=proxy-version.json -m -json vcs-test.golang.org/git/issue61415.git@v0.0.0-20231114180000-08a4fa6bb9c0
+stdout '"Version": "v0.0.0-20231114180000-08a4fa6bb9c0"'
+stdout '"Origin":'
+stdout '"VCS": "git"'
+stdout '"Hash": "08a4fa6bb9c04ffba03b26ae427b0d6335d90a2a"'
+! stdout '"Ref":'
+! stdout '"TagSum":'
+! stdout '"Reuse":'
+
+
+# With GOPROXY=direct, the -reuse flag has an effect, but
+# the Origin data from the proxy should not be sufficient
+# for the proxy response to be reused.
+
+env GOPROXY=direct
+
+go list -reuse=proxy-latest.json -m -json vcs-test.golang.org/git/issue61415.git@latest
+stdout '"Version": "v0.0.0-20231114180001-f213069baa68"'
+stdout '"Origin":'
+stdout '"VCS": "git"'
+stdout '"Hash": "f213069baa68ec26412fb373c7cf6669db1f8e69"'
+stdout '"Ref": "HEAD"'
+stdout '"TagSum": "t1:47DEQpj8HBSa\+/TImW\+5JCeuQeRkm5NMpJWZG3hSuFU="'
+! stdout '"Reuse":'
diff --git a/src/cmd/go/testdata/script/mod_list_odd_tags.txt b/src/cmd/go/testdata/script/mod_list_odd_tags.txt
new file mode 100644
index 0000000..232754e
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_list_odd_tags.txt
@@ -0,0 +1,12 @@
+[short] skip
+[!git] skip
+
+env GOPROXY=direct
+
+go list -m vcs-test.golang.org/git/odd-tags.git@latest
+stdout -count=1 '^.'
+stdout '^vcs-test.golang.org/git/odd-tags.git v0.1.1-0.20220223184835-9d863d525bbf$'
+
+go list -m -versions vcs-test.golang.org/git/odd-tags.git
+stdout -count=1 '^.'
+stdout '^vcs-test.golang.org/git/odd-tags.git$' # No versions listed — the odd tags are filtered out.
diff --git a/src/cmd/go/testdata/script/mod_list_pseudo.txt b/src/cmd/go/testdata/script/mod_list_pseudo.txt
new file mode 100644
index 0000000..056c093
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_list_pseudo.txt
@@ -0,0 +1,39 @@
+env GO111MODULE=on
+
+# Regression test for golang.org/issue/32715.
+
+# When using $GOPATH/pkg/mod/cache/download as a proxy,
+# 'latest' queries should prefer tagged versions over pseudo-versions.
+
+go mod download github.com/dmitshur-test/modtest5@v0.0.0-20190619020302-197a620e0c9a
+go mod download github.com/dmitshur-test/modtest5@v0.5.0-alpha
+go mod download github.com/dmitshur-test/modtest5@v0.5.0-alpha.0.20190619023908-3da23a9deb9e
+cmp $GOPATH/pkg/mod/cache/download/github.com/dmitshur-test/modtest5/@v/list $WORK/modtest5.list
+
+env GOSUMDB=off # don't verify go.mod files when loading retractions
+env GOPROXY=file:///$GOPATH/pkg/mod/cache/download
+env GOPATH=$WORK/gopath2
+mkdir $GOPATH
+
+go list -m -f '{{.Path}} {{.Version}} {{.Time.Format "2006-01-02"}}' github.com/dmitshur-test/modtest5@latest
+stdout '^github.com/dmitshur-test/modtest5 v0.5.0-alpha 2019-06-18$'
+
+# If the module proxy contains only pseudo-versions, 'latest' should stat
+# the version with the most recent timestamp — not the highest semantic
+# version — and return its metadata.
+env GOPROXY=file:///$WORK/tinyproxy
+go list -m -f '{{.Path}} {{.Version}} {{.Time.Format "2006-01-02"}}' dmitri.shuralyov.com/test/modtest3@latest
+stdout '^dmitri.shuralyov.com/test/modtest3 v0.0.0-20181023043359-a85b471d5412 2018-10-22$'
+
+-- $WORK/modtest5.list --
+v0.0.0-20190619020302-197a620e0c9a
+v0.5.0-alpha
+v0.5.0-alpha.0.20190619023908-3da23a9deb9e
+-- $WORK/tinyproxy/dmitri.shuralyov.com/test/modtest3/@v/list --
+v0.1.0-0.20161023043300-000000000000
+v0.0.0-20181023043359-a85b471d5412
+-- $WORK/tinyproxy/dmitri.shuralyov.com/test/modtest3/@v/v0.0.0-20181023043359-a85b471d5412.info --
+{
+ "Version": "v0.0.0-20181023043359-a85b471d5412",
+ "Time": "2018-10-22T21:33:59-07:00"
+}
diff --git a/src/cmd/go/testdata/script/mod_list_replace_dir.txt b/src/cmd/go/testdata/script/mod_list_replace_dir.txt
new file mode 100644
index 0000000..b446543
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_list_replace_dir.txt
@@ -0,0 +1,27 @@
+# Test that "go list" succeeds when given a directory in a replacement
+# module within the module cache.
+# Verifies golang.org/issue/29548
+
+# Populate go.sum and download dependencies.
+go get
+
+# Ensure v1.5.2 is also in the cache so we can list it.
+go mod download rsc.io/quote@v1.5.2
+
+! go list $GOPATH/pkg/mod/rsc.io/quote@v1.5.2
+stderr '^directory ..[/\\]pkg[/\\]mod[/\\]rsc.io[/\\]quote@v1.5.2 outside main module or its selected dependencies$'
+
+go list $GOPATH/pkg/mod/rsc.io/quote@v1.5.1
+stdout 'rsc.io/quote'
+
+-- go.mod --
+module example.com/quoter
+
+require rsc.io/quote v1.5.2
+
+replace rsc.io/quote => rsc.io/quote v1.5.1
+
+-- use.go --
+package use
+
+import _ "rsc.io/quote"
diff --git a/src/cmd/go/testdata/script/mod_list_retract.txt b/src/cmd/go/testdata/script/mod_list_retract.txt
new file mode 100644
index 0000000..b7147aa
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_list_retract.txt
@@ -0,0 +1,110 @@
+# 'go list -mod=vendor -retracted' reports an error.
+go mod vendor
+! go list -m -retracted -mod=vendor
+stderr '^go list -retracted cannot be used when vendoring is enabled$'
+rm vendor
+
+# 'go list -retracted' reports an error in GOPATH mode.
+env GO111MODULE=off
+! go list -retracted
+stderr '^go list -retracted can only be used in module-aware mode$'
+env GO111MODULE=
+
+# 'go list pkg' does not show retraction.
+go list -f '{{with .Module}}{{with .Retracted}}retracted{{end}}{{end}}' example.com/retract
+! stdout .
+
+# 'go list -retracted pkg' shows retraction.
+go list -retracted -f '{{with .Module}}{{with .Retracted}}retracted{{end}}{{end}}' example.com/retract
+stdout retracted
+
+# 'go list -m' does not show retraction.
+go list -m -f '{{with .Retracted}}retracted{{end}}' example.com/retract
+! stdout .
+
+# 'go list -m -retracted' shows retraction.
+go list -m -retracted -f '{{with .Retracted}}retracted{{end}}' example.com/retract
+
+# 'go list -m mod@version' does not show retraction.
+go list -m -f '{{with .Retracted}}retracted{{end}}' example.com/retract@v1.0.0-unused
+! stdout .
+
+# 'go list -m -retracted mod@version' does not show an error if the module
+# that would contain the retraction is unavailable. See #45305.
+go list -m -retracted -f '{{.Path}} {{.Version}} {{.Error}}' example.com/retract/missingmod@v1.0.0
+stdout '^example.com/retract/missingmod v1.0.0 <nil>$'
+exists $GOPATH/pkg/mod/cache/download/example.com/retract/missingmod/@v/v1.9.0.info
+! exists $GOPATH/pkg/mod/cache/download/example.com/retract/missingmod/@v/v1.9.0.mod
+
+# 'go list -m -retracted mod@version' shows retractions.
+go list -m -retracted example.com/retract@v1.0.0-unused
+stdout '^example.com/retract v1.0.0-unused \(retracted\)$'
+go list -m -retracted -f '{{with .Retracted}}retracted{{end}}' example.com/retract@v1.0.0-unused
+stdout retracted
+
+# 'go list -m mod@latest' selects a previous release version, not self-retracted latest.
+go list -m -f '{{.Version}}{{with .Retracted}} retracted{{end}}' example.com/retract/self/prev@latest
+stdout '^v1.1.0$'
+
+# 'go list -m -retracted mod@latest' selects the self-retracted latest version.
+go list -m -retracted -f '{{.Version}}{{with .Retracted}} retracted{{end}}' example.com/retract/self/prev@latest
+stdout '^v1.9.0 retracted$'
+
+# 'go list -m mod@latest' selects a pre-release version if all release versions are retracted.
+go list -m -f '{{.Version}}{{with .Retracted}} retracted{{end}}' example.com/retract/self/prerelease@latest
+stdout '^v1.9.1-pre$'
+
+# 'go list -m -retracted mod@latest' selects the self-retracted latest version.
+go list -m -retracted -f '{{.Version}}{{with .Retracted}} retracted{{end}}' example.com/retract/self/prerelease@latest
+stdout '^v1.9.0 retracted$'
+
+# 'go list -m mod@latest' selects a pseudo-version if all versions are retracted.
+# TODO(golang.org/issue/24031): the proxy does not expose the pseudo-version,
+# even if all release versions are retracted.
+go list -m -e -f '{{.Error.Err}}' example.com/retract/self/pseudo@latest
+stdout '^module example.com/retract/self/pseudo: no matching versions for query "latest"$'
+
+# 'go list -m mod@latest' reports an error if all versions are retracted.
+go list -m -e -f '{{.Error.Err}}' example.com/retract/self/all@latest
+stdout '^module example.com/retract/self/all: no matching versions for query "latest"$'
+
+# 'go list -m mod@<v1.10' selects a previous release version, not self-retracted latest.
+# The @latest query is not special with respect to retractions.
+go list -m -f '{{.Version}}{{with .Retracted}} retracted{{end}}' example.com/retract/self/prev@<v1.10
+stdout '^v1.1.0$'
+
+# 'go list -m -versions' hides retracted versions.
+go list -m -versions example.com/retract
+stdout '^example.com/retract v1.0.0-good v1.1.0$'
+
+# 'go list -m -retracted -versions' shows retracted versions.
+go list -m -retracted -versions example.com/retract
+stdout '^example.com/retract v1.0.0-bad v1.0.0-good v1.0.0-unused v1.1.0$'
+
+# 'go list -m -u -versions' loads retractions and does not show retracted versions.
+go list -m -u -versions example.com/retract
+stdout '^example.com/retract v1.0.0-good v1.1.0$'
+go list -m -u -versions -f '{{with .Retracted}}retracted{{end}}' example.com/retract
+stdout retracted
+
+# 'go list -m -u' shows retraction.
+go list -m -u -f '{{with .Retracted}}retracted{{end}}' example.com/retract
+stdout retracted
+
+# 'go list -m -u' does not suggest an update to a self-retracted latest version.
+go list -m -u -f '{{with .Update}}{{.Version}}{{with .Retracted}} retracted{{end}}{{end}}' example.com/retract/self/prev@v1.0.0-bad
+stdout '^v1.1.0$'
+
+-- go.mod --
+module example.com/use
+
+go 1.15
+
+require example.com/retract v1.0.0-bad
+-- go.sum --
+example.com/retract v1.0.0-bad h1:liAW69rbtjY67x2CcNzat668L/w+YGgNX3lhJsWIJis=
+example.com/retract v1.0.0-bad/go.mod h1:0DvGGofJ9hr1q63cBrOY/jSY52OwhRGA0K47NE80I5Y=
+-- use.go --
+package use
+
+import _ "example.com/retract"
diff --git a/src/cmd/go/testdata/script/mod_list_std.txt b/src/cmd/go/testdata/script/mod_list_std.txt
new file mode 100644
index 0000000..7a4fe21
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_list_std.txt
@@ -0,0 +1,93 @@
+env GO111MODULE=on
+env GOPROXY=off
+
+[!compiler:gc] skip
+[short] skip
+
+# Outside of GOROOT, our vendored packages should be reported as part of the standard library.
+go list -f '{{if .Standard}}{{.ImportPath}}{{end}}' std cmd
+stdout ^vendor/golang\.org/x/net/http2/hpack
+stdout ^cmd/vendor/golang\.org/x/arch/x86/x86asm
+! stdout ^golang\.org/x/
+
+# The dependencies of those packages should also be vendored.
+go list -deps vendor/golang.org/x/crypto/chacha20
+stdout ^vendor/golang\.org/x/crypto/internal/alias
+
+# cmd/... should match the same packages it used to match in GOPATH mode.
+go list cmd/...
+stdout ^cmd/compile
+! stdout ^cmd/vendor/golang\.org/x/arch/x86/x86asm
+
+# GOROOT/src/... should list the packages in std as if it were a module
+# dependency: omitting vendored dependencies and stopping at the 'cmd' module
+# boundary.
+
+go list $GOROOT/src/...
+stdout ^bytes$
+! stdout ^builtin$
+! stdout ^cmd/
+! stdout ^vendor/
+! stdout ^golang\.org/x/
+
+
+# Vendored dependencies should appear with their 'vendor/' paths in std (they're
+# in GOROOT/src, but not in the 'std' module following the usual module-boundary
+# rules).
+
+cd $GOROOT/src
+env GOWORK=off
+
+go list std
+stdout ^vendor/golang.org/x/net/http2/hpack
+! stdout ^golang\.org/x
+
+# The dependencies of packages with an explicit 'vendor/' prefix should
+# still themselves resolve to vendored packages.
+go list -deps vendor/golang.org/x/crypto/chacha20
+stdout ^vendor/golang.org/x/crypto/internal/alias
+! stdout ^golang\.org/x
+
+# Within the std module, the dependencies of the non-vendored packages within
+# std should appear to be packages beginning with 'vendor/', not 'golang.org/…'
+# module dependencies.
+
+go list all
+! stdout ^golang.org/x/
+! stdout ^std/
+! stdout ^cmd/
+stdout ^vendor/
+
+go list -deps -f '{{if not .Standard}}{{.ImportPath}}{{end}}' std
+! stdout .
+
+# However, the 'golang.org/…' module dependencies should resolve to those same
+# directories.
+
+go list -f '{{.Dir}}' golang.org/x/net/http2/hpack
+stdout $GOROOT[/\\]src[/\\]vendor
+
+# Within the std module, the packages within the module should omit the 'std/'
+# prefix (they retain their own identities), but should respect normal module
+# boundaries (vendored packages are not included in the module, even though they
+# are included in the 'std' pattern).
+
+go list ./...
+stdout ^bytes$
+! stdout ^builtin$
+! stdout ^cmd/
+! stdout ^vendor/
+! stdout ^golang\.org/x/
+
+
+# Within std, the vendored dependencies of cmd should still appear to be part of cmd.
+
+go list -f '{{if .Standard}}{{.ImportPath}}{{end}}' cmd
+stdout ^cmd/vendor/golang\.org/x/arch/x86/x86asm
+
+go list -f '{{if not .Standard}}{{.ImportPath}}{{end}}' cmd
+! stdout .
+
+go list cmd/...
+stdout ^cmd/compile
+! stdout ^cmd/vendor/golang\.org/x/arch/x86/x86asm
diff --git a/src/cmd/go/testdata/script/mod_list_sums.txt b/src/cmd/go/testdata/script/mod_list_sums.txt
new file mode 100644
index 0000000..cf1c18b
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_list_sums.txt
@@ -0,0 +1,32 @@
+# https://golang.org/issue/41297: 'go list -m' should not require go.sum with
+# -versions or when all args are version queries.
+
+go mod init m
+go mod edit -require=rsc.io/quote@v1.5.1
+
+go list -m -mod=readonly rsc.io/quote@latest
+stdout '^rsc\.io/quote v1\.5\.2$'
+! stderr .
+
+go list -m -mod=readonly -versions rsc.io/quote
+stdout 'rsc\.io/quote v1\.0\.0 .* v1\.5\.3-pre1$'
+! stderr .
+
+# Incidentally fetching the required version of a module records its checksum,
+# just because it happens to be in the build list, and recording the checksum
+# triggers an error under -mod=readonly.
+#
+# TODO(#41297): This should not be an error.
+! go list -m -mod=readonly rsc.io/quote@<v1.5.2
+stderr '^go: updates to go.sum needed, disabled by -mod=readonly$'
+! stderr 'missing go.sum entry'
+
+# Attempting to list the versions of a module that is not a root dependency
+# causes the build list to be resolved (so that the selected version can *also*
+# be identified, even though it is not relevant to this particular output).
+# That, in turn, causes us to need checksums for the go.sum files for the
+# modules in the module graph.
+#
+# TODO(#41297): This should not be an error either.
+! go list -m -mod=readonly -versions rsc.io/sampler
+stderr '^go: rsc\.io/quote@v1\.5\.1: missing go\.sum entry for go.mod file; to add it:\n\tgo mod download rsc\.io/quote$'
diff --git a/src/cmd/go/testdata/script/mod_list_test.txt b/src/cmd/go/testdata/script/mod_list_test.txt
new file mode 100644
index 0000000..f697af6
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_list_test.txt
@@ -0,0 +1,30 @@
+env GO111MODULE=on
+
+# go list -compiled -test must handle test-only packages
+# golang.org/issue/27097.
+go list -compiled -test
+stdout -count=4 '^.' # 4 lines
+stdout '^m$'
+stdout '^m\.test$'
+stdout '^m \[m\.test\]$'
+stdout '^m_test \[m\.test\]$'
+
+# https://golang.org/issue/39974: test packages should have the Module field populated.
+go list -test -f '{{.ImportPath}}{{with .Module}}: {{.Path}}{{end}}'
+stdout -count=4 '^.' # 4 lines
+stdout '^m: m$'
+stdout '^m\.test: m$'
+stdout '^m \[m\.test\]: m$'
+stdout '^m_test \[m\.test\]: m$'
+
+-- go.mod --
+module m
+
+-- x_test.go --
+package x
+import "testing"
+func Test(t *testing.T) {}
+-- x_x_test.go --
+package x_test
+import "testing"
+func Test(t *testing.T) {}
diff --git a/src/cmd/go/testdata/script/mod_list_test_cycle.txt b/src/cmd/go/testdata/script/mod_list_test_cycle.txt
new file mode 100644
index 0000000..755e50b
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_list_test_cycle.txt
@@ -0,0 +1,23 @@
+# https://golang.org/issue/45863: a typo in a test package leading to an
+# import cycle should be diagnosed, instead of causing an infinite loop.
+# The failure mode of this test prior to the fix was a timeout or OOM crash.
+
+go list -e -test -deps ./datastore/sql
+
+-- go.mod --
+module golang.org/issue45863
+
+go 1.17
+-- datastore/datastore_health.go --
+package datastore
+
+import (
+ "golang.org/issue45863/datastore"
+ "golang.org/issue45863/datastore/sql"
+)
+-- datastore/sql/sql.go --
+package sql
+-- datastore/sql/sql_test.go --
+package sql
+
+import _ "golang.org/issue45863/datastore"
diff --git a/src/cmd/go/testdata/script/mod_list_update_nolatest.txt b/src/cmd/go/testdata/script/mod_list_update_nolatest.txt
new file mode 100644
index 0000000..7eebe26
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_list_update_nolatest.txt
@@ -0,0 +1,55 @@
+# Check that if a proxy does not have a version of a module that could be
+# an upgrade, 'go list -m -u' still succeeds.
+# We use a local file proxy, since our test proxy doesn't have the behavior
+# we want to test, and we don't want it to be too clever.
+# Verifies #45305, where proxy.golang.org serves an empty /@v/list (200)
+# but has no /@latest (410) because the go.mod at the tip of the default
+# branch has a different major version suffix.
+env testproxy=$GOPROXY
+env GOPROXY=file:///$WORK/proxy
+env GOSUMDB=off
+
+# If the proxy does not return a list of versions (404/410)
+# or a latest version (404/410), we should see no error.
+go list -m example.com/noversion
+stdout '^example.com/noversion v0.0.0$'
+go list -m -u example.com/noversion
+stdout '^example.com/noversion v0.0.0$'
+
+# If the proxy returns an empty list of versions (200, not 404/410)
+# but does not have a latest version (404/410), we should see no error.
+go list -m example.com/nolatest
+stdout '^example.com/nolatest v0.0.0$'
+go list -m -u example.com/nolatest
+stdout '^example.com/nolatest v0.0.0$'
+
+# If proxy returns an invalid response, we should see an error.
+env GOPROXY=$testproxy/invalid
+! go list -m -u example.com/nolatest
+stderr '^go: loading module retractions for example.com/nolatest@v0.0.0: invalid response from proxy "[^"]*": invalid character ''i'' looking for beginning of value$'
+
+-- go.mod --
+module m
+
+go 1.17
+
+require (
+ example.com/nolatest v0.0.0
+ example.com/noversion v0.0.0
+)
+-- go.sum --
+example.com/nolatest v0.0.0/go.mod h1:HnLrCt6SJga5tCtJ7IzG9dOOCniY3G5C0VT7jfMdS0M=
+example.com/noversion v0.0.0/go.mod h1:2RUfWiCYsygSXPM2Igxx0FD3Kq33OnVdxm34eDDhXbQ=
+-- $WORK/proxy/example.com/nolatest/@v/list --
+-- $WORK/proxy/example.com/nolatest/@v/v0.0.0.info --
+{"Version":"v0.0.0"}
+-- $WORK/proxy/example.com/nolatest/@v/v0.0.0.mod --
+module example.com/nolatest
+
+go 1.17
+-- $WORK/proxy/example.com/noversion/@v/v0.0.0.info --
+{"Version":"v0.0.0"}
+-- $WORK/proxy/example.com/noversion/@v/v0.0.0.mod --
+module example.com/noversion
+
+go 1.17
diff --git a/src/cmd/go/testdata/script/mod_list_upgrade.txt b/src/cmd/go/testdata/script/mod_list_upgrade.txt
new file mode 100644
index 0000000..0cef04b
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_list_upgrade.txt
@@ -0,0 +1,12 @@
+env GO111MODULE=on
+
+# Populate go.sum
+go list -m -mod=mod all
+
+# Check for upgrades.
+go list -m -u all
+stdout 'rsc.io/quote v1.2.0 \[v1\.5\.2\]'
+
+-- go.mod --
+module x
+require rsc.io/quote v1.2.0
diff --git a/src/cmd/go/testdata/script/mod_list_upgrade_pseudo.txt b/src/cmd/go/testdata/script/mod_list_upgrade_pseudo.txt
new file mode 100644
index 0000000..8e51dfc
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_list_upgrade_pseudo.txt
@@ -0,0 +1,26 @@
+env GO111MODULE=on
+
+# For this test module there are three versions:
+# * v0.1.1-0.20190429073117-b5426c86b553
+# * v0.1.0
+# * v0.0.0-20190430073000-30950c05d534
+# Only v0.1.0 is tagged.
+#
+# The v0.1.1 pseudo-version is semantically higher than the latest tag.
+# The v0.0.0 pseudo-version is chronologically newer.
+
+# The latest pseudo-version is semantically higher than the latest tag.
+# 'list -u' should not suggest a lower version as an upgrade.
+
+go get example.com/pseudoupgrade@b5426c8
+go list -m -u all
+stdout '^example.com/pseudoupgrade v0.1.1-0.20190429073117-b5426c86b553$'
+
+go get example.com/pseudoupgrade@v0.0.0-20190430073000-30950c05d534
+go list -m -u all
+stdout '^example.com/pseudoupgrade v0.0.0-20190430073000-30950c05d534$'
+
+-- go.mod --
+module x
+
+go 1.12
diff --git a/src/cmd/go/testdata/script/mod_load_badchain.txt b/src/cmd/go/testdata/script/mod_load_badchain.txt
new file mode 100644
index 0000000..500a954
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_load_badchain.txt
@@ -0,0 +1,110 @@
+[short] skip
+env GO111MODULE=on
+
+# Download everything to avoid "finding" messages in stderr later.
+cp go.mod.orig go.mod
+go mod download
+go mod download example.com@v1.0.0
+go mod download example.com/badchain/a@v1.1.0
+go mod download example.com/badchain/b@v1.1.0
+go mod download example.com/badchain/c@v1.1.0
+
+# Try to update example.com/badchain/a (and its dependencies).
+! go get example.com/badchain/a
+cmp stderr update-a-expected
+cmp go.mod go.mod.orig
+
+# Try to update the main module. This updates everything, including
+# modules that aren't direct requirements, so the error stack is shorter.
+go get -u ./...
+cmp stderr update-main-expected
+cmp go.mod go.mod.withc
+
+# Update manually. Listing modules should produce an error.
+cp go.mod.orig go.mod
+go mod edit -require=example.com/badchain/a@v1.1.0
+! go list -m all
+cmp stderr list-expected
+
+# Try listing a package that imports a package
+# in a module without a requirement.
+go mod edit -droprequire example.com/badchain/a
+! go list -mod=mod m/use
+cmp stderr list-missing-expected
+
+! go list -mod=mod -test m/testuse
+cmp stderr list-missing-test-expected
+
+-- go.mod.orig --
+module m
+
+go 1.13
+
+require example.com/badchain/a v1.0.0
+-- go.mod.withc --
+module m
+
+go 1.13
+
+require (
+ example.com/badchain/a v1.0.0
+ example.com/badchain/c v1.0.0
+)
+-- go.sum --
+example.com/badchain/a v1.0.0 h1:iJDLiHLmpQgr9Zrv+44UqywAE2IG6WkHnH4uG08vf+s=
+example.com/badchain/a v1.0.0/go.mod h1:6/gnCYHdVrs6mUgatUYUSbuHxEY+/yWedmTggLz23EI=
+example.com/badchain/a v1.1.0 h1:cPxQpsOjaIrn05yDfl4dFFgGSbjYmytLqtIIBfTsEqA=
+example.com/badchain/a v1.1.0/go.mod h1:T15b2BEK+RY7h7Lr2dgS38p1pgH5/t7Kf5nQXBlcW/A=
+example.com/badchain/b v1.0.0 h1:kjDVlBxpjQavYxHE7ECCyyXhfwsfhWIqvghfRgPktSA=
+example.com/badchain/b v1.0.0/go.mod h1:sYsH934pMc3/A2vQZh019qrWmp4+k87l3O0VFUYqL+I=
+example.com/badchain/b v1.1.0 h1:iEALV+DRN62FArnYylBR4YwCALn/hCdITvhdagHa0L4=
+example.com/badchain/b v1.1.0/go.mod h1:mlCgKO7lRZ+ijwMFIBFRPCGt5r5oqCcHdhSSE0VL4uY=
+example.com/badchain/c v1.0.0 h1:lOeUHQKR7SboSH7Bj6eIDWoNHaDQXI0T2GfaH2x9fNA=
+example.com/badchain/c v1.0.0/go.mod h1:4U3gzno17SaQ2koSVNxITu9r60CeLSgye9y4/5LnfOE=
+example.com/badchain/c v1.1.0 h1:VtTg1g7fOutWKHQf+ag04KLRpdMGSfQ9s9tagVtGW14=
+example.com/badchain/c v1.1.0/go.mod h1:tyoJj5qh+qtb48sflwdVvk4R+OjPQEY2UJOoibsVLPk=
+-- use/use.go --
+package use
+
+import _ "example.com/badchain/c"
+-- testuse/testuse.go --
+package testuse
+-- testuse/testuse_test.go --
+package testuse
+
+import (
+ "testing"
+ _ "example.com/badchain/c"
+)
+
+func Test(t *testing.T) {}
+-- update-main-expected --
+go: example.com/badchain/c@v1.1.0: parsing go.mod:
+ module declares its path as: badchain.example.com/c
+ but was required as: example.com/badchain/c
+ restoring example.com/badchain/c@v1.0.0
+-- update-a-expected --
+go: example.com/badchain/a@upgrade (v1.1.0) indirectly requires example.com/badchain/c@v1.1.0: parsing go.mod:
+ module declares its path as: badchain.example.com/c
+ but was required as: example.com/badchain/c
+-- list-expected --
+go: example.com/badchain/a@v1.1.0 requires
+ example.com/badchain/b@v1.1.0 requires
+ example.com/badchain/c@v1.1.0: parsing go.mod:
+ module declares its path as: badchain.example.com/c
+ but was required as: example.com/badchain/c
+-- list-missing-expected --
+go: finding module for package example.com/badchain/c
+go: found example.com/badchain/c in example.com/badchain/c v1.1.0
+go: m/use imports
+ example.com/badchain/c: example.com/badchain/c@v1.1.0: parsing go.mod:
+ module declares its path as: badchain.example.com/c
+ but was required as: example.com/badchain/c
+-- list-missing-test-expected --
+go: finding module for package example.com/badchain/c
+go: found example.com/badchain/c in example.com/badchain/c v1.1.0
+go: m/testuse tested by
+ m/testuse.test imports
+ example.com/badchain/c: example.com/badchain/c@v1.1.0: parsing go.mod:
+ module declares its path as: badchain.example.com/c
+ but was required as: example.com/badchain/c
diff --git a/src/cmd/go/testdata/script/mod_load_badmod.txt b/src/cmd/go/testdata/script/mod_load_badmod.txt
new file mode 100644
index 0000000..fa22e18
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_load_badmod.txt
@@ -0,0 +1,25 @@
+# Unknown lines should be ignored in dependency go.mod files.
+go list -m -mod=mod all
+
+# ... and in replaced dependency go.mod files.
+cp go.mod go.mod.usesub
+go list -m -mod=mod all
+
+# ... but not in the main module.
+cp go.mod.bad go.mod
+! go list -m -mod=mod all
+stderr 'unknown directive: hello'
+
+-- go.mod --
+module m
+require rsc.io/badmod v1.0.0
+-- go.mod.bad --
+module m
+hello world
+-- go.mod.usesub --
+module m
+require rsc.io/badmod v1.0.0
+replace rsc.io/badmod v1.0.0 => ./sub
+-- sub/go.mod --
+module sub
+hello world
diff --git a/src/cmd/go/testdata/script/mod_load_badzip.txt b/src/cmd/go/testdata/script/mod_load_badzip.txt
new file mode 100644
index 0000000..58160b4
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_load_badzip.txt
@@ -0,0 +1,13 @@
+# Zip files with unexpected file names inside should be rejected.
+env GO111MODULE=on
+
+! go get rsc.io/badzip
+stderr 'zip for rsc.io/badzip@v1.0.0 has unexpected file rsc.io/badzip@v1.0.0.txt'
+! grep rsc.io/badzip go.mod
+
+go mod edit -require rsc.io/badzip@v1.0.0
+! go build -mod=mod rsc.io/badzip
+stderr 'zip for rsc.io/badzip@v1.0.0 has unexpected file rsc.io/badzip@v1.0.0.txt'
+
+-- go.mod --
+module m
diff --git a/src/cmd/go/testdata/script/mod_load_replace_mismatch.txt b/src/cmd/go/testdata/script/mod_load_replace_mismatch.txt
new file mode 100644
index 0000000..2ca8b3c
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_load_replace_mismatch.txt
@@ -0,0 +1,23 @@
+# If a replacement module declares a module path different from both
+# the original module and its location, report an error with all three paths.
+# In particular, the "required as" path should be the original.
+# Verifies golang.org/issue/38220.
+! go mod download
+cmp stderr want
+
+-- go.mod --
+module m
+
+require rsc.io/quote v1.5.2
+
+replace rsc.io/quote v1.5.2 => example.com/quote v1.5.2
+
+-- use.go --
+package use
+
+import _ "rsc.io/quote"
+
+-- want --
+go: rsc.io/quote@v1.5.2 (replaced by example.com/quote@v1.5.2): parsing go.mod:
+ module declares its path as: rsc.io/Quote
+ but was required as: rsc.io/quote
diff --git a/src/cmd/go/testdata/script/mod_local_replace.txt b/src/cmd/go/testdata/script/mod_local_replace.txt
new file mode 100644
index 0000000..19bc8f3
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_local_replace.txt
@@ -0,0 +1,23 @@
+# Test that local replacements work even with dummy module names.
+# golang.org/issue/24100.
+
+env GO111MODULE=on
+
+cd x/y
+go list -f '{{.Dir}}' zz
+stdout x[/\\]z$
+
+-- x/y/go.mod --
+module x/y
+require zz v1.0.0
+replace zz v1.0.0 => ../z
+
+-- x/y/y.go --
+package y
+import _ "zz"
+
+-- x/z/go.mod --
+module x/z
+
+-- x/z/z.go --
+package z
diff --git a/src/cmd/go/testdata/script/mod_missing_repo.txt b/src/cmd/go/testdata/script/mod_missing_repo.txt
new file mode 100644
index 0000000..d0076f7
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_missing_repo.txt
@@ -0,0 +1,15 @@
+# Regression test for golang.org/issue/34094: modules hosted within gitlab.com
+# subgroups could not be fetched because the server returned bogus go-import
+# tags for prefixes of the module path.
+
+[short] skip
+[!git] skip
+
+env GO111MODULE=on
+env GOPROXY=direct
+env GOSUMDB=off
+
+! go mod download vcs-test.golang.org/go/missingrepo/missingrepo-git@latest
+stderr 'vcs-test.golang.org/go/missingrepo/missingrepo-git: git ls-remote .*: exit status .*'
+
+go mod download vcs-test.golang.org/go/missingrepo/missingrepo-git/notmissing@latest
diff --git a/src/cmd/go/testdata/script/mod_missingpkg_prerelease.txt b/src/cmd/go/testdata/script/mod_missingpkg_prerelease.txt
new file mode 100644
index 0000000..9c250e7
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_missingpkg_prerelease.txt
@@ -0,0 +1,17 @@
+env GO111MODULE=on
+
+! go list -mod=mod -deps use.go
+stderr '^use.go:4:2: package example.com/missingpkg/deprecated provided by example.com/missingpkg at latest version v1.0.0 but not at required version v1.0.1-beta$'
+
+-- go.mod --
+module m
+
+go 1.14
+
+-- use.go --
+package use
+
+import (
+ _ "example.com/missingpkg/deprecated"
+ _ "example.com/usemissingpre"
+)
diff --git a/src/cmd/go/testdata/script/mod_modinfo.txt b/src/cmd/go/testdata/script/mod_modinfo.txt
new file mode 100644
index 0000000..8d77e22
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_modinfo.txt
@@ -0,0 +1,89 @@
+# Test to ensure runtime/debug.ReadBuildInfo parses
+# the modinfo embedded in a binary by the go tool
+# when module is enabled.
+env GO111MODULE=on
+
+cd x
+go mod edit -require=rsc.io/quote@v1.5.2
+go mod edit -replace=rsc.io/quote@v1.5.2=rsc.io/quote@v1.0.0
+go mod tidy # populate go.sum
+
+# Build a binary and ensure that it can output its own debug info.
+# The debug info should be accessible before main starts (golang.org/issue/29628).
+go build
+exec ./x$GOEXE
+stderr 'mod\s+x\s+\(devel\)'
+stderr 'dep\s+rsc.io/quote\s+v1.5.2\s+'
+stderr '=>\s+rsc.io/quote\s+v1.0.0\s+h1:'
+stderr 'Hello, world.'
+
+[short] skip
+
+# Build a binary that accesses its debug info by reading the binary directly
+# (rather than through debug.ReadBuildInfo).
+# The debug info should still be present (golang.org/issue/28753).
+cd unused
+go build
+exec ./unused$GOEXE
+
+-- x/go.mod --
+module x
+
+-- x/lib/lib.go --
+// Package lib accesses runtime/debug.modinfo before package main's init
+// functions have run.
+package lib
+
+import "runtime/debug"
+
+func init() {
+ m, ok := debug.ReadBuildInfo()
+ if !ok {
+ panic("failed debug.ReadBuildInfo")
+ }
+ println("mod", m.Main.Path, m.Main.Version)
+ for _, d := range m.Deps {
+ println("dep", d.Path, d.Version, d.Sum)
+ if r := d.Replace; r != nil {
+ println("=>", r.Path, r.Version, r.Sum)
+ }
+ }
+}
+
+-- x/main.go --
+package main
+
+import (
+ "rsc.io/quote"
+ _ "x/lib"
+)
+
+func main() {
+ println(quote.Hello())
+}
+
+-- x/unused/main.go --
+// The unused binary does not access runtime/debug.modinfo.
+package main
+
+import (
+ "bytes"
+ "encoding/hex"
+ "log"
+ "os"
+
+ _ "rsc.io/quote"
+)
+
+func main() {
+ b, err := os.ReadFile(os.Args[0])
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ infoStart, _ := hex.DecodeString("3077af0c9274080241e1c107e6d618e6")
+ if !bytes.Contains(b, infoStart) {
+ log.Fatal("infoStart not found in binary")
+ }
+ log.Println("ok")
+}
diff --git a/src/cmd/go/testdata/script/mod_multirepo.txt b/src/cmd/go/testdata/script/mod_multirepo.txt
new file mode 100644
index 0000000..bbefb78
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_multirepo.txt
@@ -0,0 +1,41 @@
+env GO111MODULE=on
+
+# initial standalone module should use no downloaded modules
+go list -deps -f {{.Dir}}
+! stdout 'pkg[\\/]mod'
+
+# v2 import should use a downloaded module
+# both without an explicit go.mod entry ...
+cp tmp/use_v2.go x.go
+go get .
+go list -deps -f {{.Dir}}
+stdout 'pkg[\\/]mod[\\/]rsc.io[\\/]quote[\\/]v2@v2.0.1$'
+
+# ... and with one ...
+cp tmp/use_v2.mod go.mod
+go list -deps -f {{.Dir}}
+stdout 'pkg[\\/]mod[\\/]rsc.io[\\/]quote[\\/]v2@v2.0.1$'
+
+# ... and even if there is a v2 module in a subdirectory.
+mkdir v2
+cp x.go v2/x.go
+cp tmp/v2.mod v2/go.mod
+go list -deps -f {{.Dir}}
+stdout 'pkg[\\/]mod[\\/]rsc.io[\\/]quote[\\/]v2@v2.0.1$'
+
+-- go.mod --
+module rsc.io/quote
+
+-- x.go --
+package quote
+
+-- tmp/use_v2.go --
+package quote
+import _ "rsc.io/quote/v2"
+
+-- tmp/use_v2.mod --
+module rsc.io/quote
+require rsc.io/quote/v2 v2.0.1
+
+-- tmp/v2.mod --
+package rsc.io/quote/v2
diff --git a/src/cmd/go/testdata/script/mod_no_gopath.txt b/src/cmd/go/testdata/script/mod_no_gopath.txt
new file mode 100644
index 0000000..ed91f5d
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_no_gopath.txt
@@ -0,0 +1,15 @@
+# https://golang.org/issue/43938: 'go build' should succeed
+# if GOPATH and the variables needed for its default value
+# are all unset but not relevant to the specific command.
+
+env HOME=''
+env home=''
+env GOPATH=''
+
+go list -deps main.go
+stdout '^io$'
+
+-- main.go --
+package main
+
+import _ "io"
diff --git a/src/cmd/go/testdata/script/mod_nomod.txt b/src/cmd/go/testdata/script/mod_nomod.txt
new file mode 100644
index 0000000..7e0f55a
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_nomod.txt
@@ -0,0 +1,43 @@
+# Test go commands with no module.
+env GO111MODULE=on
+
+# go mod edit fails unless given explicit mod file argument
+! go mod edit -json
+go mod edit -json x.mod
+
+# bug succeeds
+[exec:echo] env BROWSER=echo
+[exec:echo] go bug
+
+# commands that load the package in the current directory fail
+! go build
+! go fmt
+! go generate
+! go get
+! go install
+! go list
+! go run
+! go test
+! go vet
+
+# clean succeeds, even with -modcache
+go clean -modcache
+
+# doc succeeds for standard library
+go doc unsafe
+
+# env succeeds
+go env
+
+# tool succeeds
+go tool -n test2json
+
+# version succeeds
+go version
+
+-- x.mod --
+module m
+
+-- x.go --
+package main
+func main() {}
diff --git a/src/cmd/go/testdata/script/mod_notall.txt b/src/cmd/go/testdata/script/mod_notall.txt
new file mode 100644
index 0000000..1657c8d
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_notall.txt
@@ -0,0 +1,99 @@
+# This test demonstrates go commands that combine the 'all' pattern
+# with packages outside of 'all'.
+
+# With -deps, 'all' should include test dependencies of packages in the main
+# module, but not should not include test dependencies of packages imported only
+# by other root patterns.
+
+env GOFLAGS=-mod=mod
+cp go.mod go.mod.orig
+
+go list -deps all x/otherroot
+
+stdout '^x/inall$'
+stdout '^x/inall/fromtest$'
+stdout '^x/inall/fromtestinall$'
+stdout '^x/otherroot$'
+stdout '^x/otherdep$'
+
+! stdout '^x/fromotherroottest$'
+! stdout '^y/fromotherdeptest$'
+
+cmp go.mod go.mod.orig
+
+# With -deps -test, test dependencies of other roots should be included,
+# but test dependencies of non-roots should not.
+
+go list -deps -test all x/otherroot
+stdout '^x/inall$'
+stdout '^x/inall/fromtest$'
+stdout '^x/inall/fromtestinall$'
+stdout '^x/otherroot$'
+stdout '^x/otherdep$'
+
+stdout '^x/fromotherroottest$'
+! stdout '^y/fromotherdeptest$'
+
+cmp go.mod go.mod.orig
+
+-- m.go --
+package m
+
+import _ "x/inall"
+-- m_test.go --
+package m_test
+
+import _ "x/inall/fromtest"
+-- go.mod --
+module m
+
+go 1.15
+
+require x v0.1.0
+
+replace (
+ x v0.1.0 => ./x
+ y v0.1.0 => ./y
+)
+-- x/go.mod --
+module x
+
+go 1.15
+-- x/inall/inall.go --
+package inall
+-- x/inall/inall_test.go --
+package inall_test
+
+import _ "x/inall/fromtestinall"
+-- x/inall/fromtest/fromtest.go --
+package fromtest
+-- x/inall/fromtestinall/fromtestinall.go --
+package fromtestinall
+-- x/otherroot/otherroot.go --
+package otherroot
+
+import _ "x/otherdep"
+-- x/otherroot/otherroot_test.go --
+package otherroot_test
+
+import _ "x/fromotherroottest"
+-- x/fromotherroottest/fromotherroottest.go --
+package fromotherroottest
+-- x/otherdep/otherdep.go --
+package otherdep
+-- x/otherdep/otherdep_test.go --
+package otherdep_test
+
+import _ "y/fromotherdeptest"
+-- x/otherroot/testonly/testonly.go --
+package testonly
+-- y/go.mod --
+module y
+
+go 1.15
+-- y/fromotherdeptest/fromotherdeptest.go --
+// Package fromotherdeptest is a test dependency of x/otherdep that is
+// not declared in x/go.mod. If the loader resolves this package,
+// it will add this module to the main module's go.mod file,
+// and we can detect the mistake.
+package fromotherdeptest
diff --git a/src/cmd/go/testdata/script/mod_off.txt b/src/cmd/go/testdata/script/mod_off.txt
new file mode 100644
index 0000000..a73a58d
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_off.txt
@@ -0,0 +1,35 @@
+env GO111MODULE=off
+
+# This script tests that running go mod with
+# GO111MODULE=off when outside of GOPATH will fatal
+# with an error message, even with some source code in the directory and a go.mod.
+! go mod init
+stderr 'go: modules disabled by GO111MODULE=off; see ''go help modules'''
+! go mod graph
+stderr 'go: modules disabled by GO111MODULE=off; see ''go help modules'''
+! go mod verify
+stderr 'go: modules disabled by GO111MODULE=off; see ''go help modules'''
+! go mod download
+stderr 'go: modules disabled by GO111MODULE=off; see ''go help modules'''
+
+# Same result in an empty directory
+mkdir z
+cd z
+! go mod init
+stderr 'go: modules disabled by GO111MODULE=off; see ''go help modules'''
+! go mod graph
+stderr 'go: modules disabled by GO111MODULE=off; see ''go help modules'''
+! go mod verify
+stderr 'go: modules disabled by GO111MODULE=off; see ''go help modules'''
+! go mod download
+stderr 'go: modules disabled by GO111MODULE=off; see ''go help modules'''
+
+-- sample.go --
+package sample
+
+func main() {}
+
+-- go.mod --
+module sample
+
+go 1.12
diff --git a/src/cmd/go/testdata/script/mod_off_init.txt b/src/cmd/go/testdata/script/mod_off_init.txt
new file mode 100644
index 0000000..2aec0b3
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_off_init.txt
@@ -0,0 +1,5 @@
+# 'go mod init' should refuse to initialize a module if it will be
+# ignored anyway due to GO111MODULE=off.
+env GO111MODULE=off
+! go mod init
+stderr 'go: modules disabled by GO111MODULE=off; see ''go help modules'''
diff --git a/src/cmd/go/testdata/script/mod_outside.txt b/src/cmd/go/testdata/script/mod_outside.txt
new file mode 100644
index 0000000..7a0dc9f
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_outside.txt
@@ -0,0 +1,315 @@
+env GO111MODULE=on
+[short] skip
+
+# This script tests commands in module mode outside of any module.
+#
+# First, ensure that we really are in module mode, and that we really don't have
+# a go.mod file.
+go env GOMOD
+stdout 'NUL|/dev/null'
+
+
+# 'go list' without arguments implicitly operates on the current directory,
+# which is not in a module.
+! go list
+stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
+go list -m
+stdout '^command-line-arguments$'
+# 'go list' in the working directory should fail even if there is a a 'package
+# main' present: without a main module, we do not know its package path.
+! go list ./needmod
+stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
+
+# 'go list all' lists the transitive import graph of the main module,
+# which is empty if there is no main module.
+go list all
+! stdout .
+stderr 'warning: "all" matched no packages'
+
+# 'go list' on standard-library packages should work, since they do not depend
+# on the contents of any module.
+go list -deps cmd
+stdout '^fmt$'
+stdout '^cmd/go$'
+
+go list $GOROOT/src/fmt
+stdout '^fmt$'
+
+# 'go list' should work with file arguments.
+go list ./needmod/needmod.go
+stdout 'command-line-arguments'
+
+# 'go list' on a package from a module should fail.
+! go list example.com/printversion
+stderr '^no required module provides package example.com/printversion: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
+
+
+# 'go list -m' with an explicit version should resolve that version.
+go list -m example.com/version@latest
+stdout 'example.com/version v1.1.0'
+
+# 'go list -m -versions' should succeed even without an explicit version.
+go list -m -versions example.com/version
+stdout 'v1.0.0\s+v1.0.1\s+v1.1.0'
+
+# 'go list -m all' should fail. "all" is not meaningful outside of a module.
+! go list -m all
+stderr 'go: cannot match "all": go.mod file not found in current directory or any parent directory; see ''go help modules''$'
+
+# 'go list -m <mods> all' should also fail.
+! go list -m example.com/printversion@v1.0.0 all
+stderr 'go: cannot match "all": go.mod file not found in current directory or any parent directory; see ''go help modules''$'
+! stdout 'example.com/version'
+
+# 'go list -m <mods>' should fail if any of the mods lacks an explicit version.
+! go list -m example.com/printversion
+stderr 'go: cannot match "example.com/printversion" without -versions or an explicit version: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
+! stdout 'example.com/version'
+
+# 'go list -m' with wildcards should fail. Wildcards match modules in the
+# build list, so they aren't meaningful outside a module.
+! go list -m ...
+stderr 'go: cannot match "...": go.mod file not found in current directory or any parent directory; see ''go help modules''$'
+! go list -m rsc.io/quote/...
+stderr 'go: cannot match "rsc.io/quote/...": go.mod file not found in current directory or any parent directory; see ''go help modules''$'
+
+
+# 'go clean' should skip the current directory if it isn't in a module.
+go clean -n
+! stdout .
+! stderr .
+
+# 'go mod graph' should fail, since there's no module graph.
+! go mod graph
+stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
+
+# 'go mod why' should fail, since there is no main module to depend on anything.
+! go mod why -m example.com/version
+stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
+
+# 'go mod edit', 'go mod tidy', and 'go mod fmt' should fail:
+# there is no go.mod file to edit.
+! go mod tidy
+stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
+! go mod edit -fmt
+stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
+! go mod edit -require example.com/version@v1.0.0
+stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
+
+
+# 'go mod download' without arguments should report an error.
+! go mod download
+stderr 'no modules specified'
+
+# 'go mod download' should download exactly the requested module without dependencies.
+rm -r $GOPATH/pkg/mod/cache/download/example.com
+go mod download example.com/printversion@v1.0.0
+exists $GOPATH/pkg/mod/cache/download/example.com/printversion/@v/v1.0.0.zip
+! exists $GOPATH/pkg/mod/cache/download/example.com/version/@v/v1.0.0.zip
+
+# 'go mod download all' should fail. "all" is not meaningful outside of a module.
+! go mod download all
+stderr 'go: cannot match "all": go.mod file not found in current directory or any parent directory; see ''go help modules''$'
+
+
+# 'go mod vendor' should fail: it starts by clearing the existing vendor
+# directory, and we don't know where that is.
+! go mod vendor
+stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
+
+
+# 'go mod verify' should fail: we have no modules to verify.
+! go mod verify
+stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
+
+
+# 'go get' has no go.mod file to update outside a module and should fail.
+! go get
+stderr '^go: go.mod file not found in current directory or any parent directory.$'
+stderr '^\t''go get'' is no longer supported outside a module.$'
+! go get -u
+stderr '^go: go.mod file not found in current directory or any parent directory.$'
+stderr '^\t''go get'' is no longer supported outside a module.$'
+! go get -u ./needmod
+stderr '^go: go.mod file not found in current directory or any parent directory.$'
+stderr '^\t''go get'' is no longer supported outside a module.$'
+! go get -u all
+stderr '^go: go.mod file not found in current directory or any parent directory.$'
+stderr '^\t''go get'' is no longer supported outside a module.$'
+! go get example.com/printversion@v1.0.0 example.com/version@none
+stderr '^go: go.mod file not found in current directory or any parent directory.$'
+stderr '^\t''go get'' is no longer supported outside a module.$'
+
+# 'go get' should not download anything.
+go clean -modcache
+! go get example.com/printversion@v1.0.0
+stderr '^go: go.mod file not found in current directory or any parent directory.$'
+stderr '^\t''go get'' is no longer supported outside a module.$'
+! exists $GOPATH/pkg/mod/example.com/printversion@v1.0.0
+! exists $GOPATH/pkg/mod/example.com/version@v1.0.0
+
+
+# 'go build' without arguments implicitly operates on the current directory, and should fail.
+cd needmod
+! go build
+stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
+cd ..
+
+# 'go build' of a non-module directory should fail too.
+! go build ./needmod
+stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
+
+# 'go build' of source files should fail if they import anything outside std.
+! go build -n ./needmod/needmod.go
+stderr '^needmod[/\\]needmod.go:10:2: no required module provides package example.com/version: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
+
+# 'go build' of source files should succeed if they do not import anything outside std.
+go build -n -o ignore ./stdonly/stdonly.go
+
+# 'go build' should succeed for standard-library packages.
+go build -n fmt
+
+# 'go build' should use the latest version of the Go language.
+go build ./newgo/newgo.go
+
+# 'go doc' without arguments implicitly operates on the current directory, and should fail.
+# TODO(golang.org/issue/32027): currently, it succeeds.
+cd needmod
+go doc
+cd ..
+
+# 'go doc' of a non-module directory should also succeed.
+go doc ./needmod
+
+# 'go doc' should succeed for standard-library packages.
+go doc fmt
+
+# 'go doc' should fail for a package path outside a module.
+! go doc example.com/version
+stderr 'doc: no required module provides package example.com/version: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
+
+# 'go install' with a version should succeed if all constraints are met.
+# See mod_install_pkg_version.
+rm $GOPATH/bin
+go install example.com/printversion@v0.1.0
+exists $GOPATH/bin/printversion$GOEXE
+
+# 'go install' should fail if a package argument must be resolved to a module.
+! go install example.com/printversion
+stderr '^go: ''go install'' requires a version when current directory is not in a module\n\tTry ''go install example.com/printversion@latest'' to install the latest version$'
+
+# 'go install' should fail if a source file imports a package that must be
+# resolved to a module.
+! go install ./needmod/needmod.go
+stderr 'needmod[/\\]needmod.go:10:2: no required module provides package example.com/version: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
+
+# 'go run' should fail if a package argument must be resolved to a module.
+! go run example.com/printversion
+stderr '^no required module provides package example.com/printversion: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
+
+# 'go run' should fail if a source file imports a package that must be
+# resolved to a module.
+! go run ./needmod/needmod.go
+stderr '^needmod[/\\]needmod.go:10:2: no required module provides package example.com/version: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
+
+
+# 'go fmt' should be able to format files outside of a module.
+go fmt needmod/needmod.go
+
+
+# The remainder of the test checks dependencies by linking and running binaries.
+
+# 'go run' should work with file arguments if they don't import anything
+# outside std.
+go run ./stdonly/stdonly.go
+stdout 'path is command-line-arguments$'
+stdout 'main is $'
+
+# 'go generate' should work with file arguments.
+[exec:touch] go generate ./needmod/needmod.go
+[exec:touch] exists ./needmod/gen.txt
+
+# 'go install' should work with file arguments.
+go install ./stdonly/stdonly.go
+
+# 'go test' should work with file arguments.
+go test -v ./stdonly/stdonly_test.go
+stdout 'stdonly was tested'
+
+# 'go vet' should work with file arguments.
+go vet ./stdonly/stdonly.go
+
+
+-- README.txt --
+There is no go.mod file in the working directory.
+
+-- needmod/needmod.go --
+//go:generate touch gen.txt
+
+package main
+
+import (
+ "fmt"
+ "os"
+ "runtime/debug"
+
+ _ "example.com/version"
+)
+
+func main() {
+ info, ok := debug.ReadBuildInfo()
+ if !ok {
+ panic("missing build info")
+ }
+ fmt.Fprintf(os.Stdout, "path is %s\n", info.Path)
+ fmt.Fprintf(os.Stdout, "main is %s %s\n", info.Main.Path, info.Main.Version)
+ for _, m := range info.Deps {
+ fmt.Fprintf(os.Stdout, "using %s %s\n", m.Path, m.Version)
+ }
+}
+
+-- stdonly/stdonly.go --
+package main
+
+import (
+ "fmt"
+ "os"
+ "runtime/debug"
+)
+
+func main() {
+ info, ok := debug.ReadBuildInfo()
+ if !ok {
+ panic("missing build info")
+ }
+ fmt.Fprintf(os.Stdout, "path is %s\n", info.Path)
+ fmt.Fprintf(os.Stdout, "main is %s %s\n", info.Main.Path, info.Main.Version)
+ for _, m := range info.Deps {
+ fmt.Fprintf(os.Stdout, "using %s %s\n", m.Path, m.Version)
+ }
+}
+
+-- stdonly/stdonly_test.go --
+package main
+
+import (
+ "fmt"
+ "testing"
+)
+
+func Test(t *testing.T) {
+ fmt.Println("stdonly was tested")
+}
+
+-- newgo/newgo.go --
+// Package newgo requires Go 1.14 or newer.
+package newgo
+
+import "io"
+
+const C = 299_792_458
+
+type ReadWriteCloser interface {
+ io.ReadCloser
+ io.WriteCloser
+}
diff --git a/src/cmd/go/testdata/script/mod_overlay.txt b/src/cmd/go/testdata/script/mod_overlay.txt
new file mode 100644
index 0000000..da35be6
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_overlay.txt
@@ -0,0 +1,254 @@
+# Test overlays that affect go.mod files
+
+# The go.mod file can exist only in the overlay.
+cd $WORK/gopath/src/no-go-mod
+go list -overlay overlay.json .
+stdout example.com/simple
+
+# Check content of overlaid go.mod is used.
+cd $WORK/gopath/src/overlay-go-mod
+go list -overlay overlay.json .
+stdout use.this/module/name
+
+# Check content of overlaid go.mod in a replacement module is used.
+# The go.mod in the replacement module is missing a requirement
+# that the overlay has, so it will fail to list without the overlay.
+cd $WORK/gopath/src/overlay-replaced-go-mod
+! go list -deps .
+go list -deps -overlay overlay.json .
+
+# Overlaid go.mod is not rewritten by 'go get'.
+cd $WORK/gopath/src/get-doesnt-add-dep
+cp $WORK/overlay/get_doesnt_add_dep_go_mod $WORK/want_go_mod
+! go get -overlay overlay.json .
+stderr '^go: updates to go.mod needed, but go.mod is part of the overlay specified with -overlay$'
+cmp $WORK/overlay/get_doesnt_add_dep_go_mod $WORK/want_go_mod
+
+# Content of overlaid go.sum is used.
+# The go.sum in the module directory has garbage values for its
+# hashes, but the overlaid file has the correct values. If
+# the correct go.sum is used with the overlay, 'go get .' should
+# not report a security error.
+cd $WORK/gopath/src/overlay-sum-used
+! go get .
+stderr 'SECURITY ERROR'
+! go mod verify
+stderr 'SECURITY ERROR'
+go get -overlay overlay.json .
+go mod verify -overlay overlay.json
+# Overlaid go.sum is not rewritten.
+# Copy an incomplete file to the overlay file, and expect an error
+# attempting to update the file
+cp incomplete-sum-file $WORK/overlay/overlay-sum-used-correct-sums
+! go get -overlay overlay.json .
+stderr '^go: updates to go.sum needed, but go.sum is part of the overlay specified with -overlay$'
+cmp incomplete-sum-file $WORK/overlay/overlay-sum-used-correct-sums
+! go mod tidy -overlay overlay.json
+stderr '^go: updates to go.sum needed, but go.sum is part of the overlay specified with -overlay$'
+cmp incomplete-sum-file $WORK/overlay/overlay-sum-used-correct-sums
+
+# -overlay works with -modfile.
+# There's an empty go.mod file in the directory, and the file alternate.mod is
+# overlaid to the true go.mod file, so the -modfile flag and the overlay
+# mechanism need to work together to determine the name of the module.
+cd $WORK/gopath/src/overlay-and-dash-modfile
+go list -modfile=alternate.mod -overlay overlay.json .
+stdout 'found.the/module'
+# Even with -modfile, overlaid files can't be opened for write.
+! go get -modfile=alternate.mod -overlay overlay.json rsc.io/quote
+stderr '^go: updates to go.mod needed, but go.mod is part of the overlay specified with -overlay$'
+
+# Carving out a module by adding an overlaid go.mod file
+cd $WORK/gopath/src/carve
+go list ./... # without an overlay, hasmod is carved out and nomod isn't
+stdout carve/nomod
+! stdout carve/hasmod
+go list -overlay overlay_carve_module.json ./... # The overlay carves out nomod, leaving nothing
+! stdout .
+stderr 'matched no packages'
+go list -overlay overlay_uncarve_module.json ./... # The overlay uncarves out hasmod
+stdout carve/nomod
+stdout carve/hasmod
+
+# Carving out a module by adding an overlaid go.mod file and using
+# -modfile to write to that file.
+cd $WORK/gopath/src/carve2/nomod
+go list -overlay overlay.json all
+! stdout ^carve2$
+stdout ^carve2/nomod$
+# Editing go.mod file fails because overlay is read only
+! go get -overlay overlay.json rsc.io/quote
+stderr '^go: updates to go.mod needed, but go.mod is part of the overlay specified with -overlay$'
+! grep rsc.io/quote $WORK/overlay/carve2-nomod-go.mod
+# Editing go.mod file succeeds because we use -modfile to redirect to same file
+go get -overlay overlay.json -modfile $WORK/overlay/carve2-nomod-go.mod rsc.io/quote
+grep rsc.io/quote $WORK/overlay/carve2-nomod-go.mod
+
+-- no-go-mod/file.go --
+package simple
+-- no-go-mod/overlay.json --
+{
+ "Replace": {
+ "go.mod": "../../../overlay/simple_go_mod"
+ }
+}
+-- $WORK/overlay/simple_go_mod --
+module example.com/simple
+-- overlay-go-mod/file.go --
+package name
+-- overlay-go-mod/go.mod --
+module dont.use/this/module/name
+-- overlay-go-mod/overlay.json --
+{
+ "Replace": {
+ "go.mod": "../../../overlay/use_this_go_mod"
+ }
+}
+-- $WORK/overlay/use_this_go_mod --
+module use.this/module/name
+-- overlay-replaced-go-mod/go.mod --
+module m
+
+go 1.15
+
+require replaced/mod v1.0.0
+replace replaced/mod v1.0.0 => ../replaced-mod
+replace dep/mod v1.0.0 => ../dep-mod
+-- overlay-replaced-go-mod/source.go --
+package m
+
+import "replaced/mod/foo"
+
+func main() {
+ foo.f()
+}
+-- overlay-replaced-go-mod/overlay.json --
+{
+ "Replace": {
+ "../replaced-mod/go.mod": "../../../overlay/replacement_module_go_mod"
+ }
+}
+-- replaced-mod/go.mod --
+module replaced/mod
+-- replaced-mod/foo/foo.go --
+package foo
+
+import "dep/mod/foo"
+
+func f() { foo.g() }
+-- dep-mod/go.mod --
+invalid
+-- dep-mod/foo/foo.go --
+package foo
+
+func g() { fmt.Println("hello") }
+-- $WORK/overlay/replacement_module_go_mod --
+module replaced/mod
+
+require dep/mod v1.0.0
+
+-- get-doesnt-add-dep/overlay.json --
+{
+ "Replace": {
+ "go.mod": "../../../overlay/get_doesnt_add_dep_go_mod"
+ }
+}
+-- get-doesnt-add-dep/p.go --
+package p
+
+import "dependency/mod"
+
+func f() { mod.G() }
+-- get-doesnt-add-dep-dependency/go.mod --
+module dependency/mod
+-- get-doesnt-add-dep-dependency/mod.go --
+package mod
+
+func G() {}
+-- $WORK/overlay/get_doesnt_add_dep_go_mod --
+module get.doesnt/add/dep
+
+replace dependency/mod v1.0.0 => ../get-doesnt-add-dep-dependency
+-- overlay-sum-used/go.mod --
+module overlay.sum/used
+
+require rsc.io/quote v1.5.0
+-- overlay-sum-used/p.go --
+package p
+
+import "rsc.io/quote"
+
+func f() string {
+ return quote.Hello()
+}
+-- overlay-sum-used/incomplete-sum-file --
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw=
+rsc.io/quote v1.5.0 h1:6fJa6E+wGadANKkUMlZ0DhXFpoKlslOQDCo259XtdIE=
+rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII=
+-- overlay-sum-used/overlay.json --
+{
+ "Replace": {
+ "go.sum": "../../../overlay/overlay-sum-used-correct-sums"
+ }
+}
+-- overlay-sum-used/go.sum --
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:garbage+hash
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:garbage+hash
+rsc.io/quote v1.5.0 h1:garbage+hash
+rsc.io/quote v1.5.0/go.mod h1:garbage+hash
+rsc.io/sampler v1.3.0 h1:garbage+hash
+rsc.io/sampler v1.3.0/go.mod h1:garbage+hash
+-- $WORK/overlay/overlay-sum-used-correct-sums --
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw=
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+rsc.io/quote v1.5.0 h1:6fJa6E+wGadANKkUMlZ0DhXFpoKlslOQDCo259XtdIE=
+rsc.io/quote v1.5.0/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
+rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+-- overlay-and-dash-modfile/p.go --
+package module
+-- overlay-and-dash-modfile/go.mod --
+-- overlay-and-dash-modfile/overlay.json --
+{
+ "Replace": {
+ "alternate.mod": "../../../overlay/overlay-and-dash-modfile-alternate-mod"
+ }
+}
+-- $WORK/overlay/overlay-and-dash-modfile-alternate-mod --
+module found.the/module
+-- carve/go.mod --
+module carve
+-- carve/overlay_carve_module.json --
+{
+ "Replace": {
+ "nomod/go.mod": "../../../overlay/carve-nomod-go-mod"
+ }
+}
+-- carve/overlay_uncarve_module.json --
+{
+ "Replace": {
+ "hasmod/go.mod": ""
+ }
+}
+-- carve/hasmod/a.go --
+package hasmod
+-- carve/hasmod/go.mod --
+module carve/hasmod
+-- carve/nomod/b.go --
+package nomod
+-- $WORK/overlay/carve-nomod-go-mod --
+module carve/nomod
+-- carve2/go.mod --
+module carve2
+-- carve2/p.go --
+package p
+-- carve2/nomod/overlay.json --
+{
+ "Replace": {
+ "go.mod": "../../../../overlay/carve2-nomod-go.mod"
+ }
+}
+-- carve2/nomod/b.go --
+package nomod
+-- $WORK/overlay/carve2-nomod-go.mod --
+module carve2/nomod
diff --git a/src/cmd/go/testdata/script/mod_patterns.txt b/src/cmd/go/testdata/script/mod_patterns.txt
new file mode 100644
index 0000000..1b4b438
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_patterns.txt
@@ -0,0 +1,78 @@
+env GO111MODULE=on
+[short] skip
+
+cd m
+
+# 'go list all' should list all of the packages used (directly or indirectly) by
+# the packages in the main module, but no other packages from the standard
+# library or active modules.
+#
+# 'go list ...' should list packages in all active modules and the standard library.
+#
+# 'go list example.com/m/...' should list packages in all modules that begin with 'example.com/m/'.
+#
+# 'go list ./...' should list only packages in the current module, not other active modules.
+#
+# Warnings about unmatched patterns should only be printed once.
+#
+# And the go command should be able to keep track of all this!
+go list -f '{{.ImportPath}}: {{.Match}}' all ... example.com/m/... ./... ./xyz...
+stdout 'example.com/m/useunicode: \[all \.\.\. example.com/m/... ./...\]'
+stdout 'example.com/m/useunsafe: \[all \.\.\. example.com/m/... ./...\]'
+[cgo] stdout 'example.com/m/useC: \[all \.\.\. example.com/m/... ./...\]'
+[!cgo] ! stdout example.com/m/useC
+stdout 'example.com/unused/useerrors: \[\.\.\.\]' # but not "all"
+stdout 'example.com/m/nested/useencoding: \[\.\.\. example.com/m/...\]' # but NOT "all" or "./..."
+stdout '^unicode: \[all \.\.\.\]'
+stdout '^unsafe: \[all \.\.\.\]'
+stdout 'index/suffixarray: \[\.\.\.\]'
+stdout 'cmd/pprof: \[\.\.\.\]'
+
+stderr -count=1 '^go: warning: "./xyz..." matched no packages$'
+
+# 'go list ./...' should not try to resolve the main module.
+cd ../empty
+go list -deps ./...
+! stdout .
+! stderr 'finding'
+stderr -count=1 '^go: warning: "./..." matched no packages'
+
+# disabling cgo should drop useC
+[short] skip
+env CGO_ENABLED=0
+go list -f '{{.ImportPath}}: {{.Match}}' all ... example.com/m/... ./... ./xyz...
+! stdout example.com/m/useC
+
+-- m/go.mod --
+module example.com/m
+
+require example.com/unused v0.0.0 // indirect
+replace example.com/unused => ../unused
+
+require example.com/m/nested v0.0.0 // indirect
+replace example.com/m/nested => ../nested
+
+-- m/useC/useC.go --
+package useC
+import _ "C" // "C" is a pseudo-package, not an actual one
+-- m/useunicode/useunicode.go --
+package useunicode
+import _ "unicode"
+-- m/useunsafe/useunsafe.go --
+package useunsafe
+import _ "unsafe"
+
+-- unused/go.mod --
+module example.com/unused
+-- unused/useerrors/useerrors.go --
+package useerrors
+import _ "errors"
+
+-- nested/go.mod --
+module example.com/m/nested
+-- nested/useencoding/useencoding.go --
+package useencoding
+import _ "encoding"
+
+-- empty/go.mod --
+module example.com/empty
diff --git a/src/cmd/go/testdata/script/mod_patterns_vendor.txt b/src/cmd/go/testdata/script/mod_patterns_vendor.txt
new file mode 100644
index 0000000..b4dc401
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_patterns_vendor.txt
@@ -0,0 +1,28 @@
+env GO111MODULE=on
+
+go list -mod=vendor example.com/...
+stdout ^example.com/x$
+stdout ^example.com/x/y$
+! stdout ^example.com/x/vendor
+
+-- go.mod --
+module example.com/m
+
+-- vendor/modules.txt --
+# example.com/x v0.0.0
+example.com/x
+# example.com/x/y v0.1.0
+example.com/x/y
+
+-- vendor/example.com/x/go.mod --
+module example.com/x
+-- vendor/example.com/x/x.go --
+package x
+
+-- vendor/example.com/x/y/go.mod --
+module example.com/x/y
+-- vendor/example.com/x/y/y.go --
+package y
+
+-- vendor/example.com/x/vendor/z/z.go --
+package z
diff --git a/src/cmd/go/testdata/script/mod_perm.txt b/src/cmd/go/testdata/script/mod_perm.txt
new file mode 100644
index 0000000..2972f46
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_perm.txt
@@ -0,0 +1,23 @@
+# go list should work in ordinary conditions.
+go list ./...
+! stdout _data
+
+# skip in conditions where chmod 0 may not work.
+# plan9 should be fine, but copied from list_perm.txt unchanged.
+[root] skip
+[GOOS:windows] skip
+[GOOS:plan9] skip
+
+# go list should work with unreadable _data directory.
+chmod 0 _data
+go list ./...
+! stdout _data
+
+-- go.mod --
+module m
+
+-- x.go --
+package m
+
+-- _data/x.go --
+package p
diff --git a/src/cmd/go/testdata/script/mod_permissions.txt b/src/cmd/go/testdata/script/mod_permissions.txt
new file mode 100644
index 0000000..b523e6a
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_permissions.txt
@@ -0,0 +1,57 @@
+# Regression test for golang.org/issue/34634: permissions for the go.sum and
+# go.mod files should be preserved when overwriting them.
+
+env GO111MODULE=on
+[short] skip
+
+# Skip platforms that do not have Unix-style file permissions.
+[GOOS:windows] skip
+[GOOS:plan9] skip
+
+chmod 0640 go.mod
+chmod 0604 go.sum
+go mod edit -module=golang.org/issue/34634
+
+go get
+cmp go.mod go.mod.want
+cmp go.sum go.sum.want
+
+go run .
+stdout 'go.mod: 0640'
+stdout 'go.sum: 0604'
+
+-- read_perm.go --
+package main
+
+import (
+ "fmt"
+ "os"
+ _ "rsc.io/sampler"
+)
+
+func main() {
+ for _, name := range []string{"go.mod", "go.sum"} {
+ fi, err := os.Stat(name)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "%s: %v\n", err)
+ continue
+ }
+ fmt.Printf("%s: 0%o\n", name, fi.Mode().Perm())
+ }
+}
+-- go.mod --
+module TODO
+
+go 1.14
+-- go.sum --
+-- go.mod.want --
+module golang.org/issue/34634
+
+go 1.14
+
+require rsc.io/sampler v1.99.99
+-- go.sum.want --
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw=
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+rsc.io/sampler v1.99.99 h1:iMG9lbEG/8MdeR4lgL+Q8IcwbLNw7ijW7fTiK8Miqts=
+rsc.io/sampler v1.99.99/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
diff --git a/src/cmd/go/testdata/script/mod_prefer_compatible.txt b/src/cmd/go/testdata/script/mod_prefer_compatible.txt
new file mode 100644
index 0000000..4d583ff
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_prefer_compatible.txt
@@ -0,0 +1,80 @@
+# Regression test for golang.org/issue/34189 and golang.org/issue/34165:
+# @latest, @upgrade, and @patch should prefer compatible versions over
+# +incompatible ones, even if offered by a proxy.
+
+[!net:github.com] skip
+[!net:proxy.golang.org] skip
+
+env GO111MODULE=on
+env GOPROXY=
+env GOSUMDB=
+
+# github.com/russross/blackfriday v2.0.0+incompatible exists,
+# and should be resolved if we ask for it explicitly.
+
+go list -m github.com/russross/blackfriday@v2.0.0+incompatible
+stdout '^github.com/russross/blackfriday v2\.0\.0\+incompatible$'
+
+# blackfriday v1.5.2 has a go.mod file, so v1.5.2 should be preferred over
+# v2.0.0+incompatible when resolving latest, upgrade, and patch.
+
+go list -m github.com/russross/blackfriday@latest
+stdout '^github.com/russross/blackfriday v1\.'
+
+go list -m github.com/russross/blackfriday@upgrade
+stdout '^github.com/russross/blackfriday v1\.'
+
+! go list -m github.com/russross/blackfriday@patch
+stderr '^go: github.com/russross/blackfriday@patch: can''t query version "patch" of module github.com/russross/blackfriday: no existing version is required$'
+
+
+# If we're fetching directly from version control, ignored +incompatible
+# versions should also be omitted by 'go list'.
+
+# (Note that they may still be included in results from a proxy: in proxy mode,
+# we would need to fetch the whole zipfile for the latest compatible version in
+# order to determine whether it contains a go.mod file, and part of the point of
+# the proxy is to avoid fetching unnecessary data.)
+
+[!git] stop
+env GOPROXY=direct
+
+go list -versions -m github.com/russross/blackfriday
+stdout '^github.com/russross/blackfriday v1\.5\.1 v1\.5\.2' # and possibly others
+! stdout ' v2\.'
+
+# For this module, v2.1.0 exists and has a go.mod file.
+# 'go list -m github.com/russross/blackfriday@v2.0' will check
+# the latest v2.0 tag, discover that it isn't the right module, and stop there
+# (instead of spending the time to check O(N) previous tags).
+
+! go list -m github.com/russross/blackfriday@v2.0
+stderr '^go: module github.com/russross/blackfriday: no matching versions for query "v2\.0\"'
+
+# (But asking for exactly v2.0.0+incompatible should still succeed.)
+go list -m github.com/russross/blackfriday@v2.0.0+incompatible
+stdout '^github.com/russross/blackfriday v2\.0\.0\+incompatible$'
+
+
+# However, if the latest compatible version does not include a go.mod file,
+# +incompatible versions should still be listed, as they may still reflect the
+# intent of the module author.
+
+go list -versions -m github.com/rsc/legacytest
+stdout '^github.com/rsc/legacytest v1\.0\.0 v1\.1\.0-pre v1\.2\.0 v2\.0\.0\+incompatible'
+
+# If we're fetching directly from version control, asking for a commit hash
+# corresponding to a +incompatible version should continue to produce the
+# +incompatible version tagged for that commit, even if it is no longer listed.
+
+go list -m github.com/russross/blackfriday@cadec560ec52
+stdout '^github.com/russross/blackfriday v2\.0\.0\+incompatible$'
+
+# Similarly, requesting an untagged commit should continue to produce a +incompatible
+# pseudo-version.
+
+go list -m github.com/rsc/legacytest@7303f7796364
+stdout '^github.com/rsc/legacytest v2\.0\.1-0\.20180717164253-7303f7796364\+incompatible$'
+
+-- go.mod --
+module github.com/golang.org/issue/34165
diff --git a/src/cmd/go/testdata/script/mod_proxy_errors.txt b/src/cmd/go/testdata/script/mod_proxy_errors.txt
new file mode 100644
index 0000000..99a4ef1
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_proxy_errors.txt
@@ -0,0 +1,19 @@
+[short] skip
+
+env GO111MODULE=on
+env GOSUMDB=off
+env GOPROXY=direct
+
+# Server responses should be truncated to some reasonable number of lines.
+# (For now, exactly eight.)
+! go list -m vcs-test.golang.org/auth/ormanylines@latest
+stderr '\tserver response:\n(.|\n)*\tline 8\n\t\[Truncated: too many lines.\]$'
+
+# Server responses should be truncated to some reasonable number of characters.
+! go list -m vcs-test.golang.org/auth/oronelongline@latest
+! stderr 'blah{40}'
+stderr '\tserver response: \[Truncated: too long\.\]$'
+
+# Responses from servers using the 'mod' protocol should be propagated.
+! go list -m vcs-test.golang.org/go/modauth404@latest
+stderr '\tserver response: File\? What file\?'
diff --git a/src/cmd/go/testdata/script/mod_proxy_https.txt b/src/cmd/go/testdata/script/mod_proxy_https.txt
new file mode 100644
index 0000000..c87a0d9
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_proxy_https.txt
@@ -0,0 +1,20 @@
+env GO111MODULE=on
+
+# GOPROXY file paths must provide the "file://" prefix explicitly.
+env GOPROXY=$WORK/proxydir
+! go list -versions -m golang.org/x/text
+stderr 'invalid proxy URL.*proxydir'
+
+[!net:proxy.golang.org] stop
+
+# GOPROXY HTTPS paths may elide the "https://" prefix.
+# (See golang.org/issue/32191.)
+env GOPROXY=proxy.golang.org
+env GOSUMDB=
+go list -versions -m golang.org/x/text
+
+-- go.mod --
+module example.com
+go 1.13
+-- $WORK/proxydir/README.md --
+This proxy contains no data.
diff --git a/src/cmd/go/testdata/script/mod_proxy_invalid.txt b/src/cmd/go/testdata/script/mod_proxy_invalid.txt
new file mode 100644
index 0000000..63980b8
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_proxy_invalid.txt
@@ -0,0 +1,8 @@
+env GO111MODULE=on
+env GOPROXY=$GOPROXY/invalid
+
+! go list -m rsc.io/quote@latest
+stderr '^go: module rsc.io/quote: invalid response from proxy "'$GOPROXY'": invalid character ''i'' looking for beginning of value$'
+
+! go list -m rsc.io/quote@1.5.2
+stderr '^go: rsc.io/quote@1.5.2: invalid version: invalid response from proxy "'$GOPROXY'": invalid character ''i'' looking for beginning of value$'
diff --git a/src/cmd/go/testdata/script/mod_proxy_list.txt b/src/cmd/go/testdata/script/mod_proxy_list.txt
new file mode 100644
index 0000000..849cf2c
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_proxy_list.txt
@@ -0,0 +1,37 @@
+env GO111MODULE=on
+env proxy=$GOPROXY
+
+# Proxy that can't serve should fail.
+env GOPROXY=$proxy/404
+! go get rsc.io/quote@v1.0.0
+stderr '404 Not Found'
+
+# get should walk down the proxy list past 404 and 410 responses.
+env GOPROXY=$proxy/404,$proxy/410,$proxy
+go get rsc.io/quote@v1.1.0
+
+# get should not walk past other 4xx errors if proxies are separated with ','.
+env GOPROXY=$proxy/403,$proxy
+! go get rsc.io/quote@v1.2.0
+stderr 'reading.*/403/rsc.io/.*: 403 Forbidden'
+
+# get should not walk past non-4xx errors if proxies are separated with ','.
+env GOPROXY=$proxy/500,$proxy
+! go get rsc.io/quote@v1.3.0
+stderr 'reading.*/500/rsc.io/.*: 500 Internal Server Error'
+
+# get should walk past other 4xx errors if proxies are separated with '|'.
+env GOPROXY=$proxy/403|https://0.0.0.0|$proxy
+go get rsc.io/quote@v1.2.0
+
+# get should walk past non-4xx errors if proxies are separated with '|'.
+env GOPROXY=$proxy/500|https://0.0.0.0|$proxy
+go get rsc.io/quote@v1.3.0
+
+# get should return the final error if that's all we have.
+env GOPROXY=$proxy/404,$proxy/410
+! go get rsc.io/quote@v1.4.0
+stderr 'reading.*/410/rsc.io/.*: 410 Gone'
+
+-- go.mod --
+module x
diff --git a/src/cmd/go/testdata/script/mod_pseudo_cache.txt b/src/cmd/go/testdata/script/mod_pseudo_cache.txt
new file mode 100644
index 0000000..bcaefa2
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_pseudo_cache.txt
@@ -0,0 +1,29 @@
+[!net:golang.org] skip
+[!git] skip
+
+env GO111MODULE=on
+env GOPROXY=direct
+env GOSUMDB=off
+
+# Regression test for golang.org/issue/27171: after resolving an older
+# pseudo-version of a commit, future resolution of that commit by hash should
+# choose the highest appropriate pseudo-version instead of the cached one.
+
+go mod download -json golang.org/x/text@v0.0.0-20171215141712-a1b916ed6726
+stdout '"Version": "v0.0.0-20171215141712-a1b916ed6726",'
+
+# If GOPROXY is 'off', lookups should use whatever pseudo-version is available.
+env GOPROXY=off
+go mod download -json golang.org/x/text@a1b916ed6726
+stdout '"Version": "v0.0.0-20171215141712-a1b916ed6726",'
+
+# If we can re-resolve the commit to a pseudo-version, fetching the commit by
+# hash should use the highest such pseudo-version appropriate to the commit.
+env GOPROXY=direct
+go mod download -json golang.org/x/text@a1b916ed6726
+stdout '"Version": "v0.3.1-0.20171215141712-a1b916ed6726",'
+
+# If GOPROXY is 'off', lookups should use the highest pseudo-version in the cache.
+env GOPROXY=off
+go mod download -json golang.org/x/text@a1b916ed6726
+stdout '"Version": "v0.3.1-0.20171215141712-a1b916ed6726",'
diff --git a/src/cmd/go/testdata/script/mod_query.txt b/src/cmd/go/testdata/script/mod_query.txt
new file mode 100644
index 0000000..3758732
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_query.txt
@@ -0,0 +1,43 @@
+env GO111MODULE=on
+
+# TODO(golang.org/issue/41297): we shouldn't need go.sum. None of the commands
+# below depend on the build list.
+
+go list -m -versions rsc.io/quote
+stdout '^rsc.io/quote v1.0.0 v1.1.0 v1.2.0 v1.2.1 v1.3.0 v1.4.0 v1.5.0 v1.5.1 v1.5.2 v1.5.3-pre1$'
+
+# Latest rsc.io/quote should be v1.5.2, not v1.5.3-pre1.
+go list -m rsc.io/quote@latest
+stdout 'rsc.io/quote v1.5.2$'
+
+# Same for rsc.io/quote@v1 and rsc.io/quote@v1.5 (with no patch version).
+go list -m rsc.io/quote@v1
+stdout 'rsc.io/quote v1.5.2$'
+go list -m rsc.io/quote@v1.5
+stdout 'rsc.io/quote v1.5.2$'
+
+# We should fall back to prereleases if no release tags match...
+go list -m rsc.io/quote@>v1.5.2
+stdout 'rsc.io/quote v1.5.3-pre1$'
+
+# ...but prefer release versions when given the option.
+go list -m rsc.io/quote@<v1.5.4
+stdout 'rsc.io/quote v1.5.2$'
+
+! go list -m rsc.io/quote@>v1.5.3
+stderr 'go: module rsc.io/quote: no matching versions for query ">v1.5.3"'
+
+go list -m -e -f '{{.Error.Err}}' rsc.io/quote@>v1.5.3
+stdout 'no matching versions for query ">v1.5.3"'
+
+-- go.mod --
+module x
+require rsc.io/quote v1.0.0
+
+-- go.sum --
+rsc.io/quote v1.0.0 h1:kQ3IZQzPTiDJxSZI98YaWgxFEhlNdYASHvh+MplbViw=
+rsc.io/quote v1.0.0/go.mod h1:v83Ri/njykPcgJltBc/gEkJTmjTsNgtO1Y7vyIK1CQA=
+-- use.go --
+package use
+
+import _ "rsc.io/quote"
diff --git a/src/cmd/go/testdata/script/mod_query_empty.txt b/src/cmd/go/testdata/script/mod_query_empty.txt
new file mode 100644
index 0000000..1c39eae
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_query_empty.txt
@@ -0,0 +1,73 @@
+env GO111MODULE=on
+env GOSUMDB=off
+
+go mod download example.com/join@v1.1.0
+
+# If the proxy serves a bogus result for the @latest version,
+# reading that version should cause 'go get' to fail.
+env GOPROXY=file:///$WORK/badproxy
+cp go.mod.orig go.mod
+! go get example.com/join/subpkg
+stderr 'go: example.com/join/subpkg@v0.0.0-20190624000000-123456abcdef: .*'
+
+# If @v/list is empty, the 'go' command should still try to resolve
+# other module paths.
+env GOPROXY=file:///$WORK/emptysub
+cp go.mod.orig go.mod
+go get example.com/join/subpkg
+go list -m example.com/join/...
+! stdout 'example.com/join/subpkg'
+stdout 'example.com/join v1.1.0'
+
+# If @v/list includes a version that the proxy does not actually serve,
+# that version is treated as nonexistent.
+env GOPROXY=file:///$WORK/notfound
+cp go.mod.orig go.mod
+go get example.com/join/subpkg
+go list -m example.com/join/...
+! stdout 'example.com/join/subpkg'
+stdout 'example.com/join v1.1.0'
+
+# If the proxy provides an empty @v/list but rejects @latest with
+# some other explicit error (for example, a "permission denied" error),
+# that error should be reported to the user (and override a successful
+# result for other possible module paths).
+#
+# Depending on how the specific platform enforces permissions, the 'go get' may
+# fail either due to the intended permission error or due to a parse error.
+# We accept either failure message.
+env GOPROXY=file:///$WORK/gatekeeper
+chmod 0000 $WORK/gatekeeper/example.com/join/subpkg/@latest
+cp go.mod.orig go.mod
+! go get example.com/join/subpkg
+stderr 'go: module example.com/join/subpkg: (invalid response from proxy ".+": invalid character .+|reading file://.*/gatekeeper/example.com/join/subpkg/@latest: .+)'
+
+-- go.mod.orig --
+module example.com/othermodule
+go 1.13
+-- $WORK/badproxy/example.com/join/subpkg/@v/list --
+v0.0.0-20190624000000-123456abcdef
+-- $WORK/badproxy/example.com/join/subpkg/@v/v0.0.0-20190624000000-123456abcdef.info --
+This file is not valid JSON.
+-- $WORK/badproxy/example.com/join/@v/list --
+v1.1.0
+-- $WORK/badproxy/example.com/join/@v/v1.1.0.info --
+{"Version": "v1.1.0"}
+-- $WORK/emptysub/example.com/join/subpkg/@v/list --
+-- $WORK/emptysub/example.com/join/@v/list --
+v1.1.0
+-- $WORK/emptysub/example.com/join/@v/v1.1.0.info --
+{"Version": "v1.1.0"}
+-- $WORK/notfound/example.com/join/subpkg/@v/list --
+v1.0.0-does-not-exist
+-- $WORK/notfound/example.com/join/@v/list --
+v1.1.0
+-- $WORK/notfound/example.com/join/@v/v1.1.0.info --
+{"Version": "v1.1.0"}
+-- $WORK/gatekeeper/example.com/join/subpkg/@v/list --
+-- $WORK/gatekeeper/example.com/join/subpkg/@latest --
+ERROR: Latest version is forbidden.
+-- $WORK/gatekeeper/example.com/join/@v/list --
+v1.1.0
+-- $WORK/gatekeeper/example.com/join/@v/v1.1.0.info --
+{"Version": "v1.1.0"}
diff --git a/src/cmd/go/testdata/script/mod_query_exclude.txt b/src/cmd/go/testdata/script/mod_query_exclude.txt
new file mode 100644
index 0000000..f76b20c
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_query_exclude.txt
@@ -0,0 +1,46 @@
+env GO111MODULE=on
+
+# list excluded version
+go list -modfile=go.exclude.mod -m rsc.io/quote@v1.5.0
+stdout '^rsc.io/quote v1.5.0$'
+
+# list versions should not print excluded versions
+go list -m -versions rsc.io/quote
+stdout '\bv1.5.0\b'
+go list -modfile=go.exclude.mod -m -versions rsc.io/quote
+! stdout '\bv1.5.0\b'
+
+# list query with excluded version
+go list -m rsc.io/quote@>=v1.5
+stdout '^rsc.io/quote v1.5.0$'
+go list -modfile=go.exclude.mod -m rsc.io/quote@>=v1.5
+stdout '^rsc.io/quote v1.5.1$'
+
+# get excluded version
+cp go.exclude.mod go.exclude.mod.orig
+! go get -modfile=go.exclude.mod rsc.io/quote@v1.5.0
+stderr '^go: rsc.io/quote@v1.5.0: excluded by go.mod$'
+
+# get non-excluded version
+cp go.exclude.mod.orig go.exclude.mod
+go get -modfile=go.exclude.mod rsc.io/quote@v1.5.1
+stderr 'rsc.io/quote v1.5.1'
+
+# get query with excluded version
+cp go.exclude.mod.orig go.exclude.mod
+go get -modfile=go.exclude.mod rsc.io/quote@>=v1.5
+go list -modfile=go.exclude.mod -m ...quote
+stdout 'rsc.io/quote v1.5.[1-9]'
+
+-- go.mod --
+module x
+
+-- go.exclude.mod --
+module x
+
+exclude rsc.io/quote v1.5.0
+
+-- x.go --
+package x
+import _ "rsc.io/quote"
+
diff --git a/src/cmd/go/testdata/script/mod_query_main.txt b/src/cmd/go/testdata/script/mod_query_main.txt
new file mode 100644
index 0000000..2a2fa42
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_query_main.txt
@@ -0,0 +1,43 @@
+# 'go mod download' can download specific versions of the main module.
+go mod download rsc.io/quote@5d9f230b
+go mod download rsc.io/quote@v1.5.2
+go mod download rsc.io/quote@latest
+
+# 'go mod download' will not download @upgrade or @patch, since they always
+# resolve to the main module.
+go mod download rsc.io/quote@upgrade
+stderr '^go: skipping download of rsc.io/quote@upgrade that resolves to the main module$'
+go mod download rsc.io/quote@patch
+stderr '^go: skipping download of rsc.io/quote@patch that resolves to the main module$'
+
+# 'go list -m' can show a version of the main module.
+go list -m rsc.io/quote@5d9f230b
+stdout '^rsc.io/quote v0.0.0-20180710144737-5d9f230bcfba$'
+go list -m rsc.io/quote@v1.5.2
+stdout '^rsc.io/quote v1.5.2$'
+go list -m rsc.io/quote@latest
+stdout '^rsc.io/quote v1.5.2$'
+
+# 'go list -m -versions' shows available versions.
+go list -m -versions rsc.io/quote
+stdout '^rsc.io/quote.*v1.5.2'
+
+# 'go list -m' resolves @upgrade and @patch to the main module.
+go list -m rsc.io/quote@upgrade
+stdout '^rsc.io/quote$'
+go list -m rsc.io/quote@patch
+stdout '^rsc.io/quote$'
+
+# 'go get' will not attempt to upgrade the main module to any specific version.
+# See also: mod_get_main.txt.
+! go get rsc.io/quote@5d9f230b
+stderr '^go: can''t request version "5d9f230b" of the main module \(rsc.io/quote\)$'
+! go get rsc.io/quote@v1.5.2
+stderr '^go: can''t request version "v1.5.2" of the main module \(rsc.io/quote\)$'
+! go get rsc.io/quote@latest
+stderr '^go: can''t request version "latest" of the main module \(rsc.io/quote\)$'
+
+-- go.mod --
+module rsc.io/quote
+
+go 1.16
diff --git a/src/cmd/go/testdata/script/mod_readonly.txt b/src/cmd/go/testdata/script/mod_readonly.txt
new file mode 100644
index 0000000..9e950c3
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_readonly.txt
@@ -0,0 +1,131 @@
+env GO111MODULE=on
+[short] skip
+
+# -mod=readonly must not resolve missing modules nor update go.mod
+env GOFLAGS=-mod=readonly
+go mod edit -fmt
+cp go.mod go.mod.empty
+! go list all
+stderr '^x.go:2:8: cannot find module providing package rsc\.io/quote: import lookup disabled by -mod=readonly'
+! stderr '\(\)' # If we don't have a reason for -mod=readonly, don't log an empty one.
+cmp go.mod go.mod.empty
+
+# -mod=readonly should be set by default.
+env GOFLAGS=
+! go list all
+stderr '^x.go:2:8: no required module provides package rsc\.io/quote; to add it:\n\tgo get rsc\.io/quote$'
+cmp go.mod go.mod.empty
+
+env GOFLAGS=-mod=readonly
+
+# update go.mod - go get allowed
+go get rsc.io/quote
+grep rsc.io/quote go.mod
+
+# update go.mod - go mod tidy allowed
+cp go.mod.empty go.mod
+go mod tidy
+cp go.mod go.mod.tidy
+
+# -mod=readonly must succeed once go.mod is up-to-date...
+go list all
+
+# ... even if it needs downloads
+go clean -modcache
+go list all
+
+# -mod=readonly must not cause 'go list -m' to fail.
+# (golang.org/issue/36478)
+go list -m all
+! stderr 'cannot query module'
+
+# -mod=readonly should reject inconsistent go.mod files
+# (ones that would be rewritten).
+go get rsc.io/sampler@v1.2.0
+go mod edit -require rsc.io/quote@v1.5.2
+cp go.mod go.mod.inconsistent
+! go list
+stderr 'go: updates to go.mod needed, disabled by -mod=readonly'
+cmp go.mod go.mod.inconsistent
+
+# We get a different message when -mod=readonly is used by default.
+env GOFLAGS=
+! go list
+stderr '^go: updates to go.mod needed; to update it:\n\tgo mod tidy'
+
+# However, it should not reject files missing a 'go' directive,
+# since that was not always required.
+cp go.mod.nogo go.mod
+go list all
+cmp go.mod go.mod.nogo
+
+# Nor should it reject files with redundant (not incorrect)
+# requirements.
+cp go.mod.redundant go.mod
+go list all
+cmp go.mod go.mod.redundant
+
+cp go.mod.indirect go.mod
+go list all
+cmp go.mod go.mod.indirect
+
+
+# If we identify a missing package as a dependency of some other package in the
+# main module, we should suggest 'go mod tidy' instead of resolving it.
+
+cp go.mod.untidy go.mod
+! go list all
+stderr '^x.go:2:8: no required module provides package rsc.io/quote; to add it:\n\tgo get rsc.io/quote$'
+
+! go list -deps .
+stderr '^x.go:2:8: no required module provides package rsc.io/quote; to add it:\n\tgo get rsc.io/quote$'
+
+# However, if we didn't see an import from the main module, we should suggest
+# 'go get' instead, because we don't know whether 'go mod tidy' would add it.
+! go list rsc.io/quote
+stderr '^no required module provides package rsc.io/quote; to add it:\n\tgo get rsc.io/quote$'
+
+
+-- go.mod --
+module m
+
+go 1.16
+
+-- x.go --
+package x
+import _ "rsc.io/quote"
+-- go.mod.nogo --
+module m
+
+require (
+ rsc.io/quote v1.5.2
+ rsc.io/testonly v1.0.0 // indirect
+)
+-- go.mod.redundant --
+module m
+
+go 1.16
+
+require (
+ rsc.io/quote v1.5.2
+ rsc.io/sampler v1.3.0 // indirect
+ rsc.io/testonly v1.0.0 // indirect
+)
+-- go.mod.indirect --
+module m
+
+go 1.16
+
+require (
+ rsc.io/quote v1.5.2 // indirect
+ rsc.io/sampler v1.3.0 // indirect
+ rsc.io/testonly v1.0.0 // indirect
+)
+-- go.mod.untidy --
+module m
+
+go 1.16
+
+require (
+ rsc.io/sampler v1.3.0 // indirect
+)
diff --git a/src/cmd/go/testdata/script/mod_replace.txt b/src/cmd/go/testdata/script/mod_replace.txt
new file mode 100644
index 0000000..26b1551
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_replace.txt
@@ -0,0 +1,129 @@
+env GO111MODULE=on
+[short] skip
+
+cp go.mod go.mod.orig
+
+# Make sure the test builds without replacement.
+go build -mod=mod -o a1.exe .
+exec ./a1.exe
+stdout 'Don''t communicate by sharing memory'
+
+# Modules can be replaced by local packages.
+cp go.mod.orig go.mod
+go mod edit -replace=rsc.io/quote/v3=./local/rsc.io/quote/v3
+go build -o a2.exe .
+exec ./a2.exe
+stdout 'Concurrency is not parallelism.'
+
+# The module path of the replacement doesn't need to match.
+# (For example, it could be a long-running fork with its own import path.)
+cp go.mod.orig go.mod
+go mod edit -replace=rsc.io/quote/v3=./local/not-rsc.io/quote/v3
+go build -o a3.exe .
+exec ./a3.exe
+stdout 'Clear is better than clever.'
+
+# However, the same module can't be used as two different paths.
+cp go.mod.orig go.mod
+go mod edit -replace=not-rsc.io/quote/v3@v3.0.0=rsc.io/quote/v3@v3.0.0 -require=not-rsc.io/quote/v3@v3.0.0
+! go build -o a4.exe .
+stderr 'rsc.io/quote/v3@v3.0.0 used for two different module paths \(not-rsc.io/quote/v3 and rsc.io/quote/v3\)'
+
+# Modules that do not (yet) exist upstream can be replaced too.
+cp go.mod.orig go.mod
+go mod edit -replace=not-rsc.io/quote/v3@v3.1.0=./local/rsc.io/quote/v3
+go build -mod=mod -o a5.exe ./usenewmodule
+! stderr 'finding not-rsc.io/quote/v3'
+grep 'not-rsc.io/quote/v3 v3.1.0' go.mod
+exec ./a5.exe
+stdout 'Concurrency is not parallelism.'
+
+# Error messages for modules not found in replacements should
+# indicate the replacement module.
+cp go.mod.orig go.mod
+go mod edit -replace=rsc.io/quote/v3=./local/rsc.io/quote/v3
+! go get rsc.io/quote/v3/missing-package
+stderr 'module rsc.io/quote/v3@upgrade found \(v3.0.0, replaced by ./local/rsc.io/quote/v3\), but does not contain package'
+
+# The reported Dir and GoMod for a replaced module should be accurate.
+cp go.mod.orig go.mod
+go mod edit -replace=rsc.io/quote/v3=not-rsc.io/quote@v0.1.0-nomod
+go mod download rsc.io/quote/v3
+go list -m -f '{{.Path}} {{.Version}} {{.Dir}} {{.GoMod}}{{with .Replace}} => {{.Path}} {{.Version}} {{.Dir}} {{.GoMod}}{{end}}' rsc.io/quote/v3
+stdout '^rsc.io/quote/v3 v3.0.0 '$GOPATH'[/\\]pkg[/\\]mod[/\\]not-rsc.io[/\\]quote@v0.1.0-nomod '$GOPATH'[/\\]pkg[/\\]mod[/\\]cache[/\\]download[/\\]not-rsc.io[/\\]quote[/\\]@v[/\\]v0.1.0-nomod.mod => not-rsc.io/quote v0.1.0-nomod '$GOPATH'[/\\]pkg[/\\]mod[/\\]not-rsc.io[/\\]quote@v0.1.0-nomod '$GOPATH'[/\\]pkg[/\\]mod[/\\]cache[/\\]download[/\\]not-rsc.io[/\\]quote[/\\]@v[/\\]v0.1.0-nomod.mod$'
+
+-- go.mod --
+module quoter
+
+require rsc.io/quote/v3 v3.0.0
+
+-- main.go --
+package main
+
+import (
+ "fmt"
+ "rsc.io/quote/v3"
+)
+
+func main() {
+ fmt.Println(quote.GoV3())
+}
+
+-- usenewmodule/main.go --
+package main
+
+import (
+ "fmt"
+ "not-rsc.io/quote/v3"
+)
+
+func main() {
+ fmt.Println(quote.GoV3())
+}
+
+-- local/rsc.io/quote/v3/go.mod --
+module rsc.io/quote/v3
+
+require rsc.io/sampler v1.3.0
+
+-- local/rsc.io/quote/v3/quote.go --
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package quote collects pithy sayings.
+package quote
+
+import "rsc.io/sampler"
+
+// Hello returns a greeting.
+func HelloV3() string {
+ return sampler.Hello()
+}
+
+// Glass returns a useful phrase for world travelers.
+func GlassV3() string {
+ // See http://www.oocities.org/nodotus/hbglass.html.
+ return "I can eat glass and it doesn't hurt me."
+}
+
+// Go returns a REPLACED Go proverb.
+func GoV3() string {
+ return "Concurrency is not parallelism."
+}
+
+// Opt returns a optimization truth.
+func OptV3() string {
+ // Wisdom from ken.
+ return "If a program is too slow, it must have a loop."
+}
+
+-- local/not-rsc.io/quote/v3/go.mod --
+module not-rsc.io/quote/v3
+
+-- local/not-rsc.io/quote/v3/quote.go --
+package quote
+
+func GoV3() string {
+ return "Clear is better than clever."
+}
diff --git a/src/cmd/go/testdata/script/mod_replace_gopkgin.txt b/src/cmd/go/testdata/script/mod_replace_gopkgin.txt
new file mode 100644
index 0000000..91008f9
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_replace_gopkgin.txt
@@ -0,0 +1,82 @@
+# Regression test for golang.org/issue/34254:
+# a clone of gopkg.in/[…].vN should be replaceable by
+# a fork hosted at corp.example.com/[…]/vN,
+# even if there is an explicit go.mod file containing the
+# gopkg.in path.
+
+skip 'skipping test that depends on an unreliable third-party server; see https://go.dev/issue/54503'
+ # TODO(#54043): Make this test hermetic and re-enable it.
+
+[!net:gopkg.in] skip
+[!git] skip
+
+env GO111MODULE=on
+env GOPROXY=direct
+env GOSUMDB=off
+env GOFLAGS=-mod=mod
+
+# Replacing gopkg.in/[…].vN with a repository with a root go.mod file
+# specifying […].vN and a compatible version should succeed, even if
+# the replacement path is not a gopkg.in path.
+cd 4-to-4
+go list -m gopkg.in/src-d/go-git.v4
+
+# Previous versions of the "go" command accepted v0 and v1 pseudo-versions
+# as replacements for gopkg.in/[…].v4.
+# As a special case, we continue to accept those.
+
+cd ../4-to-0
+go list -m gopkg.in/src-d/go-git.v4
+
+cd ../4-to-1
+go list -m gopkg.in/src-d/go-git.v4
+
+cd ../4-to-incompatible
+go list -m gopkg.in/src-d/go-git.v4
+
+# A mismatched gopkg.in path should not be able to replace a different major version.
+cd ../3-to-gomod-4
+! go list -m gopkg.in/src-d/go-git.v3
+stderr '^go: gopkg\.in/src-d/go-git\.v3@v3\.2\.0 \(replaced by gopkg\.in/src-d/go-git\.v3@v3\.0\.0-20190801152248-0d1a009cbb60\): version "v3\.0\.0-20190801152248-0d1a009cbb60" invalid: go\.mod has non-\.\.\.\.v3 module path "gopkg\.in/src-d/go-git\.v4" at revision 0d1a009cbb60$'
+
+-- 4-to-4/go.mod --
+module golang.org/issue/34254
+
+go 1.13
+
+require gopkg.in/src-d/go-git.v4 v4.13.1
+
+replace gopkg.in/src-d/go-git.v4 v4.13.1 => github.com/src-d/go-git/v4 v4.13.1
+-- 4-to-1/go.mod --
+module golang.org/issue/34254
+
+go 1.13
+
+require gopkg.in/src-d/go-git.v4 v4.13.1
+
+replace gopkg.in/src-d/go-git.v4 v4.13.1 => github.com/src-d/go-git v1.0.1-0.20190801152248-0d1a009cbb60
+-- 4-to-0/go.mod --
+module golang.org/issue/34254
+
+go 1.13
+
+require gopkg.in/src-d/go-git.v4 v4.13.1
+
+replace gopkg.in/src-d/go-git.v4 v4.13.1 => github.com/src-d/go-git v0.0.0-20190801152248-0d1a009cbb60
+-- 4-to-incompatible/go.mod --
+module golang.org/issue/34254
+
+go 1.13
+
+require gopkg.in/src-d/go-git.v4 v4.13.1
+
+replace gopkg.in/src-d/go-git.v4 v4.13.1 => github.com/src-d/go-git v4.6.0+incompatible
+-- 3-to-gomod-4/go.mod --
+module golang.org/issue/34254
+go 1.13
+
+require gopkg.in/src-d/go-git.v3 v3.2.0
+
+// This replacement has a go.mod file declaring its path to be
+// gopkg.in/src-d/go-git.v4, so it cannot be used as a replacement for v3.
+replace gopkg.in/src-d/go-git.v3 v3.2.0 => gopkg.in/src-d/go-git.v3 v3.0.0-20190801152248-0d1a009cbb60
diff --git a/src/cmd/go/testdata/script/mod_replace_import.txt b/src/cmd/go/testdata/script/mod_replace_import.txt
new file mode 100644
index 0000000..753071f
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_replace_import.txt
@@ -0,0 +1,144 @@
+env GO111MODULE=on
+
+# 'go list' should not add requirements even if they can be resolved locally.
+cp go.mod go.mod.orig
+! go list all
+cmp go.mod go.mod.orig
+
+# 'go list' should resolve imports using replacements.
+go get
+go list all
+stdout 'example.com/a/b$'
+stdout 'example.com/x/v3$'
+stdout 'example.com/y/z/w$'
+stdout 'example.com/v'
+
+# The selected modules should prefer longer paths,
+# but should try shorter paths if needed.
+# Modules with a major-version suffix should have a corresponding pseudo-version.
+# Replacements that specify a version should use the latest such version.
+go list -m all
+stdout 'example.com/a/b v0.0.0-00010101000000-000000000000 => ./b'
+stdout 'example.com/y v0.0.0-00010101000000-000000000000 => ./y'
+stdout 'example.com/x/v3 v3.0.0-00010101000000-000000000000 => ./v3'
+stdout 'example.com/v v1.12.0 => ./v12'
+
+# The go command should print an informative error when the matched
+# module does not contain a package.
+# TODO(#26909): Ideally these errors should include line numbers for the imports within the main module.
+cd fail
+! go mod tidy
+stderr '^go: localhost.fail imports\n\tw: module w@latest found \(v0.0.0-00010101000000-000000000000, replaced by ../w\), but does not contain package w$'
+stderr '^go: localhost.fail imports\n\tnonexist: nonexist@v0.1.0: replacement directory ../nonexist does not exist$'
+
+-- go.mod --
+module example.com/m
+
+replace (
+ example.com/a => ./a
+ example.com/a/b => ./b
+)
+
+replace (
+ example.com/x => ./x
+ example.com/x/v3 => ./v3
+)
+
+replace (
+ example.com/y/z/w => ./w
+ example.com/y => ./y
+)
+
+replace (
+ example.com/v v1.11.0 => ./v11
+ example.com/v v1.12.0 => ./v12
+ example.com/v => ./v
+)
+
+replace (
+ example.com/i v2.0.0+incompatible => ./i2
+)
+
+-- m.go --
+package main
+import (
+ _ "example.com/a/b"
+ _ "example.com/x/v3"
+ _ "example.com/y/z/w"
+ _ "example.com/v"
+ _ "example.com/i"
+)
+func main() {}
+
+-- a/go.mod --
+module a.localhost
+-- a/a.go --
+package a
+-- a/b/b.go--
+package b
+
+-- b/go.mod --
+module a.localhost/b
+-- b/b.go --
+package b
+
+-- x/go.mod --
+module x.localhost
+-- x/x.go --
+package x
+-- x/v3.go --
+package v3
+import _ "x.localhost/v3"
+
+-- v3/go.mod --
+module x.localhost/v3
+-- v3/x.go --
+package x
+
+-- w/go.mod --
+module w.localhost
+-- w/skip/skip.go --
+// Package skip is nested below nonexistent package w.
+package skip
+
+-- y/go.mod --
+module y.localhost
+-- y/z/w/w.go --
+package w
+
+-- v12/go.mod --
+module v.localhost
+-- v12/v.go --
+package v
+
+-- v11/go.mod --
+module v.localhost
+-- v11/v.go --
+package v
+
+-- v/go.mod --
+module v.localhost
+-- v/v.go --
+package v
+
+-- i2/go.mod --
+module example.com/i
+-- i2/i.go --
+package i
+
+-- fail/m.go --
+package main
+
+import (
+ _ "w"
+ _ "nonexist"
+)
+
+func main() {}
+
+-- fail/go.mod --
+module localhost.fail
+
+replace w => ../w
+
+replace nonexist v0.1.0 => ../nonexist
diff --git a/src/cmd/go/testdata/script/mod_replace_readonly.txt b/src/cmd/go/testdata/script/mod_replace_readonly.txt
new file mode 100644
index 0000000..5c1226b
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_replace_readonly.txt
@@ -0,0 +1,62 @@
+# Check that with -mod=readonly, when we load a package in a module that is
+# replaced but not required, we emit an error with the command to add the
+# requirement.
+# Verifies golang.org/issue/41416, golang.org/issue/41577.
+cp go.mod go.mod.orig
+
+# Replace all versions of a module without requiring it.
+# With -mod=mod, we'd add a requirement for a "zero" pseudo-version, but we
+# can't in readonly mode, since its go.mod may alter the build list.
+go mod edit -replace rsc.io/quote=./quote
+! go list rsc.io/quote
+stderr '^module rsc.io/quote provides package rsc.io/quote and is replaced but not required; to add it:\n\tgo get rsc.io/quote$'
+go get rsc.io/quote
+cmp go.mod go.mod.latest
+go list rsc.io/quote
+cp go.mod.orig go.mod
+
+# Same test with a specific version.
+go mod edit -replace rsc.io/quote@v1.0.0-doesnotexist=./quote
+! go list rsc.io/quote
+stderr '^module rsc.io/quote provides package rsc.io/quote and is replaced but not required; to add it:\n\tgo get rsc.io/quote@v1.0.0-doesnotexist$'
+go get rsc.io/quote@v1.0.0-doesnotexist
+cmp go.mod go.mod.specific
+go list rsc.io/quote
+cp go.mod.orig go.mod
+
+# If there are multiple versions, the highest is suggested.
+go mod edit -replace rsc.io/quote@v1.0.0-doesnotexist=./quote
+go mod edit -replace rsc.io/quote@v1.1.0-doesnotexist=./quote
+! go list rsc.io/quote
+stderr '^module rsc.io/quote provides package rsc.io/quote and is replaced but not required; to add it:\n\tgo get rsc.io/quote@v1.1.0-doesnotexist$'
+
+-- go.mod --
+module m
+
+go 1.16
+-- go.mod.latest --
+module m
+
+go 1.16
+
+replace rsc.io/quote => ./quote
+
+require rsc.io/quote v1.5.2 // indirect
+-- go.mod.specific --
+module m
+
+go 1.16
+
+replace rsc.io/quote v1.0.0-doesnotexist => ./quote
+
+require rsc.io/quote v1.0.0-doesnotexist // indirect
+-- use.go --
+package use
+
+import _ "rsc.io/quote"
+-- quote/go.mod --
+module rsc.io/quote
+
+go 1.16
+-- quote/quote.go --
+package quote
diff --git a/src/cmd/go/testdata/script/mod_require_exclude.txt b/src/cmd/go/testdata/script/mod_require_exclude.txt
new file mode 100644
index 0000000..0946dbf
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_require_exclude.txt
@@ -0,0 +1,96 @@
+# build with no newer version to satisfy exclude
+env GO111MODULE=on
+cp go.mod go.mod.orig
+
+# With the selected version excluded, commands that query that version without
+# updating go.mod should fail.
+
+! go list -mod=readonly -m all
+stderr '^go: ignoring requirement on excluded version rsc.io/sampler v1\.99\.99$'
+stderr '^go: updates to go.mod needed, disabled by -mod=readonly; to update it:\n\tgo mod tidy$'
+! stdout '^rsc.io/sampler v1.99.99'
+cmp go.mod go.mod.orig
+
+! go list -mod=vendor -m rsc.io/sampler
+stderr '^go: ignoring requirement on excluded version rsc.io/sampler v1\.99\.99$'
+stderr '^go: updates to go.mod needed, disabled by -mod=vendor; to update it:\n\tgo mod tidy$'
+! stdout '^rsc.io/sampler v1.99.99'
+cmp go.mod go.mod.orig
+
+# The failure message should be clear when -mod=vendor is implicit.
+
+go mod edit -go=1.14
+! go list -m rsc.io/sampler
+stderr '^go: ignoring requirement on excluded version rsc.io/sampler v1\.99\.99$'
+stderr '^go: updates to go.mod needed, disabled by -mod=vendor\n\t\(Go version in go.mod is at least 1.14 and vendor directory exists\.\)\n\tto update it:\n\tgo mod tidy$'
+! stdout '^rsc.io/sampler v1.99.99'
+go mod edit -go=1.13
+cmp go.mod go.mod.orig
+
+
+# With the selected version excluded, commands that load only modules should
+# drop the excluded module.
+
+go list -m -mod=mod all
+stderr '^go: dropping requirement on excluded version rsc.io/sampler v1\.99\.99$'
+stdout '^x$'
+! stdout '^rsc.io/sampler'
+cmp go.mod go.moddrop
+
+# With the latest version excluded, 'go list' should resolve needed packages
+# from the next-highest version.
+
+cp go.mod.orig go.mod
+go list -mod=mod -f '{{with .Module}}{{.Path}} {{.Version}}{{end}}' all
+stderr '^go: dropping requirement on excluded version rsc.io/sampler v1\.99\.99$'
+stdout '^x $'
+! stdout '^rsc.io/sampler v1.99.99'
+stdout '^rsc.io/sampler v1.3.0'
+
+# build with newer version available
+cp go.mod2 go.mod
+go list -mod=mod -f '{{with .Module}}{{.Path}} {{.Version}}{{end}}' all
+stderr '^go: dropping requirement on excluded version rsc.io/quote v1\.5\.1$'
+stdout 'rsc.io/quote v1.5.2'
+
+# build with excluded newer version
+cp go.mod3 go.mod
+go list -mod=mod -f '{{with .Module}}{{.Path}} {{.Version}}{{end}}' all
+! stderr '^go: dropping requirement'
+stdout 'rsc.io/quote v1.5.1'
+
+-- x.go --
+package x
+import _ "rsc.io/quote"
+
+-- go.mod --
+module x
+
+go 1.13
+
+exclude rsc.io/sampler v1.99.99
+
+require rsc.io/sampler v1.99.99
+-- vendor/modules.txt --
+# rsc.io/sampler v1.99.99
+## explicit
+-- go.moddrop --
+module x
+
+go 1.13
+
+exclude rsc.io/sampler v1.99.99
+-- go.mod2 --
+module x
+
+go 1.13
+
+exclude rsc.io/quote v1.5.1
+require rsc.io/quote v1.5.1
+-- go.mod3 --
+module x
+
+go 1.13
+
+exclude rsc.io/quote v1.5.2
+require rsc.io/quote v1.5.1
diff --git a/src/cmd/go/testdata/script/mod_retention.txt b/src/cmd/go/testdata/script/mod_retention.txt
new file mode 100644
index 0000000..9d30026
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_retention.txt
@@ -0,0 +1,150 @@
+# Regression test for golang.org/issue/34822: the 'go' command should prefer not
+# to update the go.mod file if the changes only affect formatting, and should only
+# remove redundant requirements in 'go mod tidy'.
+
+env GO111MODULE=on
+[short] skip
+
+# Control case: verify that go.mod.tidy is actually tidy.
+cp go.mod.tidy go.mod
+go list -mod=mod all
+cmp go.mod go.mod.tidy
+
+
+# If the only difference in the go.mod file is the line endings,
+# it should not be overwritten automatically.
+cp go.mod.crlf go.mod
+go list all
+cmp go.mod go.mod.crlf
+
+# However, 'go mod tidy' should fix whitespace even if there are no other changes.
+go mod tidy
+cmp go.mod go.mod.tidy
+
+
+# Out-of-order requirements should not be overwritten automatically...
+cp go.mod.unsorted go.mod
+go list all
+cmp go.mod go.mod.unsorted
+
+# ...but 'go mod edit -fmt' should sort them.
+go mod edit -fmt
+cmp go.mod go.mod.tidy
+
+
+# "// indirect" comments should be removed if direct dependencies are seen.
+# changes.
+cp go.mod.indirect go.mod
+go list -mod=mod all
+cmp go.mod go.mod.tidy
+
+# "// indirect" comments should be added if appropriate.
+# TODO(#42504): add case for 'go list -mod=mod -tags=any all' when -tags=any
+# is supported. Only a command that loads "all" without build constraints
+# (except "ignore") has enough information to add "// indirect" comments.
+# 'go mod tidy' and 'go mod vendor' are the only commands that do that,
+# but 'go mod vendor' cannot write go.mod.
+cp go.mod.toodirect go.mod
+go list all
+cmp go.mod go.mod.toodirect
+
+
+# Redundant requirements should be preserved...
+cp go.mod.redundant go.mod
+go list all
+cmp go.mod go.mod.redundant
+go mod vendor
+cmp go.mod go.mod.redundant
+rm -r vendor
+
+# ...except by 'go mod tidy'.
+go mod tidy
+cmp go.mod go.mod.tidy
+
+
+# A missing "go" version directive should be added.
+# However, that should not remove other redundant requirements.
+# In fact, it may *add* redundant requirements due to activating lazy loading.
+cp go.mod.nogo go.mod
+go list -mod=mod all
+cmpenv go.mod go.mod.addedgo
+
+
+-- go.mod.tidy --
+module m
+
+go 1.14
+
+require (
+ rsc.io/quote v1.5.2
+ rsc.io/testonly v1.0.0 // indirect
+)
+-- x.go --
+package x
+import _ "rsc.io/quote"
+-- go.mod.crlf --
+module m
+
+go 1.14
+
+require (
+ rsc.io/quote v1.5.2
+ rsc.io/testonly v1.0.0 // indirect
+)
+-- go.mod.unsorted --
+module m
+
+go 1.14
+
+require (
+ rsc.io/testonly v1.0.0 // indirect
+ rsc.io/quote v1.5.2
+)
+-- go.mod.indirect --
+module m
+
+go 1.14
+
+require (
+ rsc.io/quote v1.5.2 // indirect
+ rsc.io/testonly v1.0.0 // indirect
+)
+-- go.mod.toodirect --
+module m
+
+go 1.14
+
+require (
+ rsc.io/quote v1.5.2
+ rsc.io/testonly v1.0.0
+)
+-- go.mod.redundant --
+module m
+
+go 1.14
+
+require (
+ rsc.io/quote v1.5.2
+ rsc.io/sampler v1.3.0 // indirect
+ rsc.io/testonly v1.0.0 // indirect
+)
+-- go.mod.nogo --
+module m
+
+require (
+ rsc.io/quote v1.5.2
+ rsc.io/sampler v1.3.0 // indirect
+ rsc.io/testonly v1.0.0 // indirect
+)
+-- go.mod.addedgo --
+module m
+
+go $goversion
+
+require rsc.io/quote v1.5.2
+
+require (
+ golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c // indirect
+ rsc.io/sampler v1.3.0 // indirect
+ rsc.io/testonly v1.0.0 // indirect
+)
diff --git a/src/cmd/go/testdata/script/mod_retract.txt b/src/cmd/go/testdata/script/mod_retract.txt
new file mode 100644
index 0000000..37aae48
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_retract.txt
@@ -0,0 +1,45 @@
+cp go.mod go.mod.orig
+
+# 'go list pkg' does not report an error when a retracted version is used.
+go list -e -f '{{if .Error}}{{.Error}}{{end}}' ./use
+! stdout .
+cmp go.mod go.mod.orig
+
+# Nor does 'go build'.
+[!short] go build ./use
+[!short] ! stderr .
+[!short] cmp go.mod go.mod.orig
+
+# Neither 'go list' nor 'go build' should download go.mod from the version
+# that would list retractions.
+exists $GOPATH/pkg/mod/cache/download/example.com/retract/@v/v1.0.0-bad.mod
+! exists $GOPATH/pkg/mod/cache/download/example.com/retract/@v/v1.1.0.mod
+
+# Importing a package from a module with a retracted latest version will
+# select the latest non-retracted version.
+go get ./use_self_prev
+go list -m example.com/retract/self/prev
+stdout '^example.com/retract/self/prev v1.1.0$'
+exists $GOPATH/pkg/mod/cache/download/example.com/retract/self/prev/@v/v1.9.0.mod
+
+-- go.mod --
+module example.com/use
+
+go 1.15
+
+require example.com/retract v1.0.0-bad
+
+-- go.sum --
+example.com/retract v1.0.0-bad h1:liAW69rbtjY67x2CcNzat668L/w+YGgNX3lhJsWIJis=
+example.com/retract v1.0.0-bad/go.mod h1:0DvGGofJ9hr1q63cBrOY/jSY52OwhRGA0K47NE80I5Y=
+example.com/retract/self/prev v1.1.0 h1:0/8I/GTG+1eJTFeDQ/fUbgrMsVHHyKhh3Z8DSZp1fuA=
+example.com/retract/self/prev v1.1.0/go.mod h1:xl2EcklWuZZHVtHWcpzfSJQmnzAGpKZYpA/Wto7SZN4=
+-- use/use.go --
+package use
+
+import _ "example.com/retract"
+
+-- use_self_prev/use.go --
+package use_self_prev
+
+import _ "example.com/retract/self/prev"
diff --git a/src/cmd/go/testdata/script/mod_retract_fix_version.txt b/src/cmd/go/testdata/script/mod_retract_fix_version.txt
new file mode 100644
index 0000000..9ae49f5
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_retract_fix_version.txt
@@ -0,0 +1,48 @@
+# retract must not be used without a module directive.
+! go list -m all
+stderr 'go.mod:3: no module directive found, so retract cannot be used$'
+
+# Commands that update go.mod should fix non-canonical versions in
+# retract directives.
+# Verifies #44494.
+go mod edit -module=rsc.io/quote/v2
+! go list -m all
+stderr '^go: updates to go.mod needed; to update it:\n\tgo mod tidy$'
+go mod tidy
+go list -m all
+cmp go.mod go.mod.want
+
+# If a retracted version doesn't match the module's major version suffx,
+# an error should be reported.
+! go mod edit -retract=v3.0.1
+stderr '^go: -retract=v3.0.1: version "v3.0.1" invalid: should be v2, not v3$'
+cp go.mod.mismatch-v2 go.mod
+! go list -m all
+stderr 'go.mod:3: retract rsc.io/quote/v2: version "v3.0.1" invalid: should be v2, not v3$'
+
+cp go.mod.mismatch-v1 go.mod
+! go list -m all
+stderr 'go.mod:3: retract rsc.io/quote: version "v3.0.1" invalid: should be v0 or v1, not v3$'
+
+-- go.mod --
+go 1.16
+
+retract latest
+-- go.mod.want --
+go 1.16
+
+retract v2.0.1
+
+module rsc.io/quote/v2
+-- go.mod.mismatch-v2 --
+go 1.16
+
+retract v3.0.1
+
+module rsc.io/quote/v2
+-- go.mod.mismatch-v1 --
+go 1.16
+
+retract v3.0.1
+
+module rsc.io/quote
diff --git a/src/cmd/go/testdata/script/mod_retract_incompatible.txt b/src/cmd/go/testdata/script/mod_retract_incompatible.txt
new file mode 100644
index 0000000..5d09532
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_retract_incompatible.txt
@@ -0,0 +1,15 @@
+# The current version of a module should not be considered when loading
+# retractions. If the current version is +incompatible, we should not prefer
+# +incompatible versions when looking for retractions.
+# Verifies #42601.
+
+go mod init m
+
+# Request a +incompatible version retracted in v1.0.0.
+go get example.com/retract/incompatible@v2.0.0+incompatible
+stderr '^go: warning: example.com/retract/incompatible@v2.0.0\+incompatible: retracted by module author$'
+
+# We should still see a warning if the +incompatible was previously in the
+# build list.
+go get example.com/retract/incompatible@v2.0.0+incompatible
+stderr '^go: warning: example.com/retract/incompatible@v2.0.0\+incompatible: retracted by module author$'
diff --git a/src/cmd/go/testdata/script/mod_retract_noupgrade.txt b/src/cmd/go/testdata/script/mod_retract_noupgrade.txt
new file mode 100644
index 0000000..67de79f
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_retract_noupgrade.txt
@@ -0,0 +1,11 @@
+go list -m -u example.com/retract/noupgrade
+stdout '^example.com/retract/noupgrade v1.0.0 \(retracted\)$'
+
+-- go.mod --
+module use
+
+go 1.19
+
+require example.com/retract/noupgrade v1.0.0
+-- go.sum --
+example.com/retract/noupgrade v1.0.0/go.mod h1:q2/HnBejUQ83RcUo4stf2U++/Zr9R/Ky3BsodjKBkQ4=
diff --git a/src/cmd/go/testdata/script/mod_retract_pseudo_base.txt b/src/cmd/go/testdata/script/mod_retract_pseudo_base.txt
new file mode 100644
index 0000000..87b440d
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_retract_pseudo_base.txt
@@ -0,0 +1,62 @@
+# When converting a commit to a pseudo-version, don't use a retracted version
+# as the base.
+# Verifies golang.org/issue/41700.
+
+[short] skip
+[!git] skip
+env GOPROXY=direct
+env GOSUMDB=off
+go mod init m
+
+# Control: check that v1.0.0 is the only version and is retracted.
+go list -m -versions vcs-test.golang.org/git/retract-pseudo.git
+stdout '^vcs-test.golang.org/git/retract-pseudo.git$'
+go list -m -versions -retracted vcs-test.golang.org/git/retract-pseudo.git
+stdout '^vcs-test.golang.org/git/retract-pseudo.git v1.0.0$'
+
+# 713affd19d7b is a commit after v1.0.0. Don't use v1.0.0 as the base.
+go list -m vcs-test.golang.org/git/retract-pseudo.git@713affd19d7b
+stdout '^vcs-test.golang.org/git/retract-pseudo.git v0.0.0-20201009173747-713affd19d7b$'
+
+# 64c061ed4371 is the commit v1.0.0 refers to. Don't convert to v1.0.0.
+go list -m vcs-test.golang.org/git/retract-pseudo.git@64c061ed4371
+stdout '^vcs-test.golang.org/git/retract-pseudo.git v0.0.0-20201009173747-64c061ed4371'
+
+# A retracted version is a valid base. Retraction should not validate existing
+# pseudo-versions, nor should it turn invalid pseudo-versions valid.
+go get vcs-test.golang.org/git/retract-pseudo.git@v1.0.1-0.20201009173747-713affd19d7b
+go list -m vcs-test.golang.org/git/retract-pseudo.git
+stdout '^vcs-test.golang.org/git/retract-pseudo.git v1.0.1-0.20201009173747-713affd19d7b$'
+
+! go get vcs-test.golang.org/git/retract-pseudo.git@v1.0.1-0.20201009173747-64c061ed4371
+stderr '^go: vcs-test.golang.org/git/retract-pseudo.git@v1.0.1-0.20201009173747-64c061ed4371: invalid pseudo-version: tag \(v1.0.0\) found on revision 64c061ed4371 is already canonical, so should not be replaced with a pseudo-version derived from that tag$'
+
+-- retract-pseudo.sh --
+#!/bin/bash
+
+# This is not part of the test.
+# Run this to generate and update the repository on vcs-test.golang.org.
+
+set -euo pipefail
+
+rm -rf retract-pseudo
+mkdir retract-pseudo
+cd retract-pseudo
+git init
+
+# Create the module.
+# Retract v1.0.0 and tag v1.0.0 at the same commit.
+# The module has no unretracted release versions.
+go mod init vcs-test.golang.org/git/retract-pseudo.git
+go mod edit -retract v1.0.0
+echo 'package p' >p.go
+git add -A
+git commit -m 'create module retract-pseudo'
+git tag v1.0.0
+
+# Commit a trivial change so the default branch does not point to v1.0.0.
+git mv p.go q.go
+git commit -m 'trivial change'
+
+zip -r ../retract-pseudo.zip .
+gsutil cp ../retract-pseudo.zip gs://vcs-test/git/retract-pseudo.zip
diff --git a/src/cmd/go/testdata/script/mod_retract_rationale.txt b/src/cmd/go/testdata/script/mod_retract_rationale.txt
new file mode 100644
index 0000000..92e9b7d
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_retract_rationale.txt
@@ -0,0 +1,79 @@
+# When there is no rationale, 'go get' should print a hard-coded message.
+go get example.com/retract/rationale@v1.0.0-empty
+stderr '^go: warning: example.com/retract/rationale@v1.0.0-empty: retracted by module author$'
+
+# 'go list' should print the same hard-coded message.
+go list -m -retracted -f '{{.Retracted}}' example.com/retract/rationale
+stdout '^\[retracted by module author\]$'
+
+
+# When there is a multi-line message, 'go get' should print the first line.
+go get example.com/retract/rationale@v1.0.0-multiline1
+stderr '^go: warning: example.com/retract/rationale@v1.0.0-multiline1: retracted by module author: short description$'
+! stderr 'detail'
+
+# 'go list' should show the full message.
+go list -m -retracted -f '{{.Retracted}}' example.com/retract/rationale
+cmp stdout multiline
+
+# 'go get' output should be the same whether the retraction appears at top-level
+# or in a block.
+go get example.com/retract/rationale@v1.0.0-multiline2
+stderr '^go: warning: example.com/retract/rationale@v1.0.0-multiline2: retracted by module author: short description$'
+! stderr 'detail'
+
+# Same for 'go list'.
+go list -m -retracted -f '{{.Retracted}}' example.com/retract/rationale
+cmp stdout multiline
+
+
+# 'go get' should omit long messages.
+go get example.com/retract/rationale@v1.0.0-long
+stderr '^go: warning: example.com/retract/rationale@v1.0.0-long: retracted by module author: \(message omitted: too long\)'
+
+# 'go list' should show the full message.
+go list -m -retracted -f '{{.Retracted}}' example.com/retract/rationale
+stdout '^\[lo{500}ng\]$'
+
+
+# 'go get' should omit messages with unprintable characters.
+go get example.com/retract/rationale@v1.0.0-unprintable
+stderr '^go: warning: example.com/retract/rationale@v1.0.0-unprintable: retracted by module author: \(message omitted: contains non-printable characters\)'
+
+# 'go list' should show the full message.
+go list -m -retracted -f '{{.Retracted}}' example.com/retract/rationale
+stdout '^\[Ends with a BEL character. Beep!\x07\]$'
+
+
+# When there is a comment on a block, but not on individual retractions within
+# the block, the rationale should come from the block comment.
+go list -m -retracted -f '{{.Retracted}}' example.com/retract/rationale@v1.0.0-block
+stdout '^\[block comment\]$'
+go list -m -retracted -f '{{.Retracted}}' example.com/retract/rationale@v1.0.0-blockwithcomment
+stdout '^\[inner comment\]$'
+
+
+# When a version is covered by multiple retractions, all retractions should
+# be reported in the order they appear in the file.
+go list -m -retracted -f '{{range .Retracted}}{{.}},{{end}}' example.com/retract/rationale@v1.0.0-order
+stdout '^degenerate range,single version,$'
+go list -m -retracted -f '{{range .Retracted}}{{.}},{{end}}' example.com/retract/rationale@v1.0.1-order
+stdout '^single version,degenerate range,$'
+
+# 'go get' will only report the first retraction to avoid being too verbose.
+go get example.com/retract/rationale@v1.0.0-order
+stderr '^go: warning: example.com/retract/rationale@v1.0.0-order: retracted by module author: degenerate range$'
+go get example.com/retract/rationale@v1.0.1-order
+stderr '^go: warning: example.com/retract/rationale@v1.0.1-order: retracted by module author: single version$'
+
+-- go.mod --
+module m
+
+go 1.14
+
+-- multiline --
+[short description
+more
+
+detail
+suffix]
diff --git a/src/cmd/go/testdata/script/mod_retract_rename.txt b/src/cmd/go/testdata/script/mod_retract_rename.txt
new file mode 100644
index 0000000..38986f3
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_retract_rename.txt
@@ -0,0 +1,28 @@
+# Populate go.sum.
+go get
+
+# 'go list -m -retracted' should load retractions, even if the version
+# containing retractions has a different module path.
+go list -m -retracted -f '{{with .Retracted}}retracted{{end}}' example.com/retract/rename
+
+# 'go list -m -u' should load retractions, too.
+go list -m -u -f '{{with .Retracted}}retracted{{end}}' example.com/retract/rename
+
+# 'go get' should warn about the retracted version.
+go get
+stderr '^go: warning: example.com/retract/rename@v1.0.0-bad: retracted by module author: bad$'
+
+# We can't upgrade, since this latest version has a different module path.
+! go get example.com/retract/rename
+stderr 'module declares its path as: example.com/retract/newname'
+
+-- go.mod --
+module example.com/use
+
+go 1.16
+
+require example.com/retract/rename v1.0.0-bad
+-- use.go --
+package use
+
+import _ "example.com/retract/rename"
diff --git a/src/cmd/go/testdata/script/mod_retract_replace.txt b/src/cmd/go/testdata/script/mod_retract_replace.txt
new file mode 100644
index 0000000..788968f
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_retract_replace.txt
@@ -0,0 +1,63 @@
+# If the latest unretracted version of a module is replaced, 'go list' should
+# obtain retractions from the replacement.
+
+# Populate go.sum.
+go get
+
+# The latest version, v1.9.0, is not available on the proxy.
+go list -m -retracted example.com/retract/missingmod
+stdout '^example.com/retract/missingmod v1.0.0$'
+exists $GOPATH/pkg/mod/cache/download/example.com/retract/missingmod/@v/v1.9.0.info
+! exists $GOPATH/pkg/mod/cache/download/example.com/retract/missingmod/@v/v1.9.0.mod
+
+# If we replace that version, we should see retractions.
+go mod edit -replace=example.com/retract/missingmod@v1.9.0=./missingmod-v1.9.0
+go list -m -retracted -f '{{range .Retracted}}{{.}}{{end}}' example.com/retract/missingmod
+stdout '^bad version$'
+
+# If we replace the retracted version, we should not see a retraction.
+go mod edit -replace=example.com/retract/missingmod=./missingmod-v1.9.0
+go list -m -retracted -f '{{if not .Retracted}}good version{{end}}' example.com/retract/missingmod
+stdout '^good version$'
+
+
+# If a replacement version is retracted, we should see a retraction.
+# It should appear in both the replaced module and the replacement, as other
+# fields like GoMod do.
+go list -m -retracted -f '{{range .Retracted}}{{.}}{{end}}' example.com/retract
+! stdout .
+go list -m -retracted -f '{{if .Replace}}replaced{{end}}' example.com/retract
+! stdout .
+go mod edit -replace example.com/retract@v1.0.0-good=example.com/retract@v1.0.0-bad
+go list -m -mod=mod -retracted -f '{{range .Retracted}}{{.}}{{end}}' example.com/retract
+stdout '^bad$'
+go list -m -mod=mod -retracted -f '{{with .Replace}}{{range .Retracted}}{{.}}{{end}}{{end}}' example.com/retract
+stdout '^bad$'
+
+-- go.mod --
+module m
+
+go 1.14
+
+require (
+ example.com/retract v1.0.0-good
+ example.com/retract/missingmod v1.0.0
+)
+-- use.go --
+package use
+
+import (
+ _ "example.com/retract"
+ _ "example.com/retract/missingmod"
+)
+-- missingmod-v1.0.0/go.mod --
+module example.com/retract/missingmod
+
+go 1.14
+-- missingmod-v1.9.0/go.mod --
+module example.com/retract/missingmod
+
+go 1.14
+
+// bad version
+retract v1.0.0
diff --git a/src/cmd/go/testdata/script/mod_retract_versions.txt b/src/cmd/go/testdata/script/mod_retract_versions.txt
new file mode 100644
index 0000000..012fa15
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_retract_versions.txt
@@ -0,0 +1,22 @@
+# https://golang.org/issue/44296: the --versions flag should not affect
+# the version reported by 'go list' in case of retractions.
+
+env FMT='{{.Path}}{{with .Error}}: {{printf "%q" .Err}}{{end}} {{printf "%q" .Version}}{{with .Versions}} {{.}}{{end}}'
+
+go list -m -e -f $FMT example.com/retract/self/pseudo
+stdout '^example.com/retract/self/pseudo: "module example.com/retract/self/pseudo: not a known dependency" ""$'
+
+go list -m -e -f $FMT example.com/retract/self/pseudo@latest
+stdout '^example.com/retract/self/pseudo: "module example.com/retract/self/pseudo: no matching versions for query \\"latest\\"" "latest"$'
+
+
+go list -m -e -f $FMT --versions example.com/retract/self/pseudo
+stdout '^example.com/retract/self/pseudo ""$'
+
+go list -m -e -f $FMT --versions example.com/retract/self/pseudo@latest
+stdout '^example.com/retract/self/pseudo: "module example.com/retract/self/pseudo: no matching versions for query \\"latest\\"" "latest"$'
+
+-- go.mod --
+module test
+
+go 1.17
diff --git a/src/cmd/go/testdata/script/mod_run_issue52331.txt b/src/cmd/go/testdata/script/mod_run_issue52331.txt
new file mode 100644
index 0000000..917e890
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_run_issue52331.txt
@@ -0,0 +1,35 @@
+# Regression test for https://go.dev/issue/52331: 'go run -mod=mod'
+# failed to write go.mod and go.sum with the resolved dependencies.
+
+[short] skip
+
+! go run main.go
+# stderr '^main\.go:6:2: no required module provides package example\.com/version; to add it:\n\tgo get example\.com/version\n\z'
+
+go run -mod=mod main.go
+cmp go.mod go.mod.want
+grep -count=1 '^example\.com/version v1.1.0 h1:' go.sum
+grep -count=1 '^example\.com/version v1.1.0/go.mod h1:' go.sum
+
+-- go.mod --
+module example
+
+go 1.17
+-- go.mod.want --
+module example
+
+go 1.17
+
+require example.com/version v1.1.0 // indirect
+-- main.go --
+package main
+
+import (
+ "fmt"
+
+ "example.com/version"
+)
+
+func main() {
+ fmt.Println(version.V)
+}
diff --git a/src/cmd/go/testdata/script/mod_run_nonmain.txt b/src/cmd/go/testdata/script/mod_run_nonmain.txt
new file mode 100644
index 0000000..8435fc0
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_run_nonmain.txt
@@ -0,0 +1,18 @@
+! go run $PWD
+! stderr 'no packages loaded'
+stderr '^package example.net/nonmain is not a main package$'
+
+! go run .
+stderr '^package example.net/nonmain is not a main package$'
+
+! go run ./...
+stderr '^go: warning: "\./\.\.\." matched only non-main packages$'
+stderr '^go: no packages loaded from \./\.\.\.$'
+
+-- go.mod --
+module example.net/nonmain
+
+go 1.17
+-- nonmain.go --
+// Package nonmain is not a main package.
+package nonmain
diff --git a/src/cmd/go/testdata/script/mod_run_path.txt b/src/cmd/go/testdata/script/mod_run_path.txt
new file mode 100644
index 0000000..4369ee4
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_run_path.txt
@@ -0,0 +1,15 @@
+# Test that go run does not get confused by conflict
+# between go.mod's module path and what you'd
+# expect from GOPATH. golang.org/issue/26046.
+
+env GO111MODULE=on
+
+cd $GOPATH/src/example.com/hello
+go run main.go
+
+-- $GOPATH/src/example.com/hello/go.mod --
+module example.com/hello/v2
+
+-- $GOPATH/src/example.com/hello/main.go --
+package main
+func main() {}
diff --git a/src/cmd/go/testdata/script/mod_run_pkg_version.txt b/src/cmd/go/testdata/script/mod_run_pkg_version.txt
new file mode 100644
index 0000000..969852c
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_run_pkg_version.txt
@@ -0,0 +1,104 @@
+# This test checks the behavior of 'go run' with a 'cmd@version' argument.
+# Most of 'go run' is covered in other tests.
+# mod_install_pkg_version covers most of the package loading functionality.
+# This test focuses on 'go run' behavior specific to this mode.
+[short] skip
+
+# 'go run pkg@version' works outside a module.
+env GO111MODULE=auto
+go run example.com/cmd/a@v1.0.0
+stdout '^a@v1.0.0$'
+
+
+# 'go run pkg@version' reports an error if modules are disabled.
+env GO111MODULE=off
+! go run example.com/cmd/a@v1.0.0
+stderr '^go: modules disabled by GO111MODULE=off; see ''go help modules''$'
+env GO111MODULE=on
+
+
+# 'go run pkg@version' ignores go.mod in the current directory.
+cd m
+cp go.mod go.mod.orig
+! go list -m all
+stderr '^go: example.com/cmd@v1.1.0-doesnotexist: reading http.*/mod/example\.com/cmd/@v/v1.1.0-doesnotexist.info: 404 Not Found\n\tserver response: 404 page not found$'
+stderr '^go: example.com/cmd@v1.1.0-doesnotexist: missing go.sum entry for go.mod file; to add it:\n\tgo mod download example.com/cmd$'
+go run example.com/cmd/a@v1.0.0
+stdout '^a@v1.0.0$'
+cmp go.mod go.mod.orig
+cd ..
+
+
+# 'go install pkg@version' works on a module that doesn't have a go.mod file
+# and with a module whose go.mod file has missing requirements.
+# With a proxy, the two cases are indistinguishable.
+go run rsc.io/fortune@v1.0.0
+stderr '^go: found rsc.io/quote in rsc.io/quote v1.5.2$'
+stderr '^Hello, world.$'
+
+
+# 'go run pkg@version' should report an error if pkg is not a main package.
+! go run example.com/cmd/err@v1.0.0
+stderr '^package example.com/cmd/err is not a main package$'
+
+
+# 'go run pkg@version' should report errors if the module contains
+# replace or exclude directives.
+go mod download example.com/cmd@v1.0.0-replace
+! go run example.com/cmd/a@v1.0.0-replace
+cmp stderr replace-err
+
+go mod download example.com/cmd@v1.0.0-exclude
+! go run example.com/cmd/a@v1.0.0-exclude
+cmp stderr exclude-err
+
+
+# 'go run dir@version' works like a normal 'go run' command if
+# dir is a relative or absolute path.
+go mod download rsc.io/fortune@v1.0.0
+! go run $GOPATH/pkg/mod/rsc.io/fortune@v1.0.0
+stderr '^go: go\.mod file not found in current directory or any parent directory; see ''go help modules''$'
+! go run ../pkg/mod/rsc.io/fortune@v1.0.0
+stderr '^go: go\.mod file not found in current directory or any parent directory; see ''go help modules''$'
+mkdir tmp
+cd tmp
+go mod init tmp
+go mod edit -require=rsc.io/fortune@v1.0.0
+! go run -mod=readonly $GOPATH/pkg/mod/rsc.io/fortune@v1.0.0
+stderr '^missing go\.sum entry for module providing package rsc\.io/fortune; to add:\n\tgo mod download rsc\.io/fortune$'
+! go run -mod=readonly ../../pkg/mod/rsc.io/fortune@v1.0.0
+stderr '^missing go\.sum entry for module providing package rsc\.io/fortune; to add:\n\tgo mod download rsc\.io/fortune$'
+cd ..
+rm tmp
+
+
+# 'go run' does not interpret @version arguments after the first.
+go run example.com/cmd/a@v1.0.0 example.com/doesnotexist@v1.0.0
+stdout '^a@v1.0.0$'
+
+
+# 'go run pkg@version' succeeds when -mod=readonly is set explicitly.
+# Verifies #43278.
+go run -mod=readonly example.com/cmd/a@v1.0.0
+stdout '^a@v1.0.0$'
+
+-- m/go.mod --
+module m
+
+go 1.16
+
+require example.com/cmd v1.1.0-doesnotexist
+-- x/x.go --
+package main
+
+func main() {}
+-- replace-err --
+go: example.com/cmd/a@v1.0.0-replace (in example.com/cmd@v1.0.0-replace):
+ The go.mod file for the module providing named packages contains one or
+ more replace directives. It must not contain directives that would cause
+ it to be interpreted differently than if it were the main module.
+-- exclude-err --
+go: example.com/cmd/a@v1.0.0-exclude (in example.com/cmd@v1.0.0-exclude):
+ The go.mod file for the module providing named packages contains one or
+ more exclude directives. It must not contain directives that would cause
+ it to be interpreted differently than if it were the main module.
diff --git a/src/cmd/go/testdata/script/mod_run_pkgerror.txt b/src/cmd/go/testdata/script/mod_run_pkgerror.txt
new file mode 100644
index 0000000..48f900d
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_run_pkgerror.txt
@@ -0,0 +1,32 @@
+# https://golang.org/issue/39986: files reported as invalid by go/build should
+# be listed in InvalidGoFiles.
+
+go list -e -f '{{.Incomplete}}{{"\n"}}{{.Error}}{{"\n"}}{{.InvalidGoFiles}}{{"\n"}}' .
+stdout '^true\nfound packages m \(m\.go\) and main \(main\.go\) in '$PWD'\n\[main.go\]\n'
+
+
+# https://golang.org/issue/45827: 'go run .' should report the same package
+# errors as 'go build' and 'go list'.
+
+! go build
+stderr '^found packages m \(m\.go\) and main \(main\.go\) in '$PWD'$'
+
+! go list .
+stderr '^found packages m \(m\.go\) and main \(main\.go\) in '$PWD'$'
+
+! go run .
+! stderr 'no packages loaded'
+stderr '^found packages m \(m\.go\) and main \(main\.go\) in '$PWD'$'
+
+! go run ./...
+! stderr 'no packages loaded'
+stderr '^found packages m \(m\.go\) and main \(main\.go\) in '$PWD'$'
+
+-- go.mod --
+module m
+
+go 1.17
+-- m.go --
+package m
+-- main.go --
+package main
diff --git a/src/cmd/go/testdata/script/mod_skip_write.txt b/src/cmd/go/testdata/script/mod_skip_write.txt
new file mode 100644
index 0000000..db47b9c
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_skip_write.txt
@@ -0,0 +1,93 @@
+# Commands used to debug the module graph should not write go.mod or go.sum
+# or report errors when those files need to be updated.
+
+# Everything's okay initially.
+go list -m all
+
+# Downgrading sampler makes go.mod inconsistent, but 'go mod graph',
+# 'go mod verify', and 'go mod why' still work.
+cp go.mod go.mod.orig
+go mod edit -require=rsc.io/sampler@v1.2.0
+cp go.mod go.mod.edit
+! go list -m all
+stderr 'updates to go.mod needed'
+
+go mod graph
+cmp stdout graph.want
+cmp go.mod go.mod.edit
+
+go mod verify
+stdout '^all modules verified$'
+cmp go.mod go.mod.edit
+
+go mod why rsc.io/sampler
+cmp stdout why.want
+cmp go.mod go.mod.edit
+
+go mod why -m rsc.io/sampler
+cmp stdout why.want
+cmp go.mod go.mod.edit
+
+cp go.mod.orig go.mod
+
+# Removing go.sum breaks other commands, but 'go mod graph' and
+# 'go mod why' still work.
+rm go.sum
+! go list -m all
+stderr 'missing go.sum entry'
+
+go mod graph
+cmp stdout graph.want
+! exists go.sum
+
+go mod verify
+stdout '^all modules verified$'
+! exists go.sum
+
+go mod why rsc.io/sampler
+cmp stdout why.want
+! exists go.sum
+
+go mod why -m rsc.io/sampler
+cmp stdout why.want
+! exists go.sum
+
+-- go.mod --
+module m
+
+go 1.18
+
+require rsc.io/quote v1.5.2
+
+require (
+ golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c // indirect
+ rsc.io/sampler v1.3.0 // indirect
+ rsc.io/testonly v1.0.0 // indirect
+)
+-- go.sum --
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw=
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0=
+rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
+rsc.io/sampler v1.2.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+rsc.io/testonly v1.0.0 h1:K/VWHdO+Jv7woUXG0GzVNx1czBXUt3Ib1deaMn+xk64=
+rsc.io/testonly v1.0.0/go.mod h1:OqmGbIFOcF+XrFReLOGZ6BhMM7uMBiQwZsyNmh74SzY=
+-- use.go --
+package use
+
+import _ "rsc.io/quote"
+-- graph.want --
+m go@1.18
+m golang.org/x/text@v0.0.0-20170915032832-14c0d48ead0c
+m rsc.io/quote@v1.5.2
+m rsc.io/sampler@v1.3.0
+m rsc.io/testonly@v1.0.0
+rsc.io/quote@v1.5.2 rsc.io/sampler@v1.3.0
+rsc.io/sampler@v1.3.0 golang.org/x/text@v0.0.0-20170915032832-14c0d48ead0c
+-- why.want --
+# rsc.io/sampler
+m
+rsc.io/quote
+rsc.io/sampler
diff --git a/src/cmd/go/testdata/script/mod_stale.txt b/src/cmd/go/testdata/script/mod_stale.txt
new file mode 100644
index 0000000..c6ab27d
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_stale.txt
@@ -0,0 +1,15 @@
+[short] skip
+
+env GOCACHE=$WORK/cache
+go list -f '{{.Stale}}' .
+stdout true
+go install .
+go list -f '{{.Stale}}' .
+stdout false
+
+-- go.mod --
+module example.com/mod
+
+go 1.20
+-- m.go --
+package m
diff --git a/src/cmd/go/testdata/script/mod_std_vendor.txt b/src/cmd/go/testdata/script/mod_std_vendor.txt
new file mode 100644
index 0000000..ed47542
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_std_vendor.txt
@@ -0,0 +1,77 @@
+env GO111MODULE=on
+env GOPROXY=off
+
+[!compiler:gc] skip
+
+# 'go list' should report imports from _test.go in the TestImports field.
+go list -f '{{.TestImports}}'
+stdout net/http # from .TestImports
+
+# 'go list' should find standard-vendored packages.
+go list -f '{{.Dir}}' vendor/golang.org/x/net/http2/hpack
+stdout $GOROOT[/\\]src[/\\]vendor
+
+# 'go list -test' should report vendored transitive dependencies of _test.go
+# imports in the Deps field.
+go list -test -f '{{range .Deps}}{{.}}{{"\n"}}{{end}}'
+stdout ^vendor/golang.org/x/crypto # dep of .TestImports
+
+
+# Modules outside the standard library should not use the packages vendored there...
+cd broken
+! go build -mod=readonly
+stderr 'disabled by -mod=readonly'
+! go build -mod=vendor
+stderr 'http.go:5:2: cannot find module providing package golang.org/x/net/http2/hpack: import lookup disabled by -mod=vendor'
+
+# ...even if they explicitly use the "cmd/vendor/" or "vendor/" prefix.
+cd ../importcmd
+! go build .
+stderr 'use of vendored package'
+
+cd ../importstd
+! go build .
+stderr 'use of vendored package'
+
+
+# When run within the 'std' module, 'go list -test' should report vendored
+# transitive dependencies at their vendored paths.
+cd $GOROOT/src
+go list -test -f '{{range .Deps}}{{.}}{{"\n"}}{{end}}' net/http
+! stdout ^golang.org/x/net/http2/hpack
+stdout ^vendor/golang.org/x/net/http2/hpack
+
+-- go.mod --
+module m
+
+-- x.go --
+package x
+
+-- x_test.go --
+package x
+import "testing"
+import _ "net/http"
+func Test(t *testing.T) {}
+
+-- broken/go.mod --
+module broken
+-- broken/http.go --
+package broken
+
+import (
+ _ "net/http"
+ _ "golang.org/x/net/http2/hpack"
+)
+
+-- importcmd/go.mod --
+module importcmd
+-- importcmd/x.go --
+package importcmd
+
+import _ "cmd/vendor/golang.org/x/tools/go/analysis"
+-- importstd/go.mod --
+module importvendor
+-- importstd/x.go --
+package importstd
+
+import _ "vendor/golang.org/x/net/http2/hpack"
diff --git a/src/cmd/go/testdata/script/mod_string_alias.txt b/src/cmd/go/testdata/script/mod_string_alias.txt
new file mode 100644
index 0000000..5c3d428
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_string_alias.txt
@@ -0,0 +1,14 @@
+[short] skip
+
+env GO111MODULE=on
+
+go mod init golang.org/issue/27584
+
+go build .
+
+-- main.go --
+package main
+
+type string = []int
+
+func main() {}
diff --git a/src/cmd/go/testdata/script/mod_sum_ambiguous.txt b/src/cmd/go/testdata/script/mod_sum_ambiguous.txt
new file mode 100644
index 0000000..07c6659
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_sum_ambiguous.txt
@@ -0,0 +1,62 @@
+# Confirm our build list.
+cp go.sum.buildlist-only go.sum
+go list -m all
+stdout '^example.com/ambiguous/a v1.0.0$'
+stdout '^example.com/ambiguous/a/b v0.0.0-empty$'
+
+# If two modules could provide a package, but only one does,
+# 'go mod tidy' should retain sums for both zips.
+go mod tidy
+grep '^example.com/ambiguous/a v1.0.0 h1:' go.sum
+grep '^example.com/ambiguous/a/b v0.0.0-empty h1:' go.sum
+
+# 'go mod download' should also add sums.
+cp go.sum.buildlist-only go.sum
+go mod download example.com/ambiguous/a
+grep '^example.com/ambiguous/a v1.0.0 h1:' go.sum
+! grep '^example.com/ambiguous/a/b v0.0.0-empty h1:' go.sum
+go mod download example.com/ambiguous/a/b
+grep '^example.com/ambiguous/a/b v0.0.0-empty h1:' go.sum
+
+# If two modules could provide a package, and we're missing a sum for one,
+# we should see a missing sum error, even if we have a sum for a module that
+# provides the package.
+cp go.sum.a-only go.sum
+! go list example.com/ambiguous/a/b
+stderr '^missing go.sum entry needed to verify package example.com/ambiguous/a/b is provided by exactly one module; to add:\n\tgo mod download example.com/ambiguous/a/b$'
+! go list -deps .
+stderr '^use.go:3:8: missing go.sum entry needed to verify package example.com/ambiguous/a/b \(imported by m\) is provided by exactly one module; to add:\n\tgo get m$'
+
+cp go.sum.b-only go.sum
+! go list example.com/ambiguous/a/b
+stderr '^missing go.sum entry for module providing package example.com/ambiguous/a/b; to add:\n\tgo mod download example.com/ambiguous/a$'
+! go list -deps .
+stderr '^use.go:3:8: missing go.sum entry for module providing package example.com/ambiguous/a/b \(imported by m\); to add:\n\tgo get m$'
+
+cp go.sum.buildlist-only go.sum
+! go list example.com/ambiguous/a/b
+stderr '^missing go.sum entry for module providing package example.com/ambiguous/a/b; to add:\n\tgo mod download example.com/ambiguous/a example.com/ambiguous/a/b$'
+! go list -deps .
+stderr '^use.go:3:8: missing go.sum entry for module providing package example.com/ambiguous/a/b \(imported by m\); to add:\n\tgo get m$'
+
+-- go.mod --
+module m
+
+go 1.15
+
+require example.com/ambiguous/a v1.0.0
+-- go.sum.buildlist-only --
+example.com/ambiguous/a v1.0.0/go.mod h1:TrBl/3xTPFJ2gmMIYz53h2gkNtg0dokszEMuyS1QEb0=
+example.com/ambiguous/a/b v0.0.0-empty/go.mod h1:MajJq5jPEBnnXP+NTWIeXX7kwaPS1sbVEJdooTmsePQ=
+-- go.sum.a-only --
+example.com/ambiguous/a v1.0.0 h1:pGZhTXy6+titE2rNfwHwJykSjXDR4plO52PfZrBM0T8=
+example.com/ambiguous/a v1.0.0/go.mod h1:TrBl/3xTPFJ2gmMIYz53h2gkNtg0dokszEMuyS1QEb0=
+example.com/ambiguous/a/b v0.0.0-empty/go.mod h1:MajJq5jPEBnnXP+NTWIeXX7kwaPS1sbVEJdooTmsePQ=
+-- go.sum.b-only --
+example.com/ambiguous/a v1.0.0/go.mod h1:TrBl/3xTPFJ2gmMIYz53h2gkNtg0dokszEMuyS1QEb0=
+example.com/ambiguous/a/b v0.0.0-empty h1:xS29ReXXuhjT7jc79mo91h/PevaZ2oS9PciF1DucXtg=
+example.com/ambiguous/a/b v0.0.0-empty/go.mod h1:MajJq5jPEBnnXP+NTWIeXX7kwaPS1sbVEJdooTmsePQ=
+-- use.go --
+package use
+
+import _ "example.com/ambiguous/a/b"
diff --git a/src/cmd/go/testdata/script/mod_sum_issue56222.txt b/src/cmd/go/testdata/script/mod_sum_issue56222.txt
new file mode 100644
index 0000000..12848c9
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_sum_issue56222.txt
@@ -0,0 +1,91 @@
+# Regression test for #56222: 'go get -t' and 'go mod tidy'
+# should save enough checksums to run 'go test' on the named
+# packages or any package in "all" respectively.
+
+# 'go mod tidy' in a module at go 1.21 or higher should preserve
+# checksums needed to run 'go test all'.
+cd m1
+go mod tidy
+
+go list -f '{{if eq .ImportPath "example.com/generics"}}{{.Module.GoVersion}}{{end}}' -deps -test example.com/m2/q
+stdout 1.18
+[!short] go test -o $devnull -c all
+
+cat go.sum
+replace 'example.com/generics v1.0.0/go.mod' 'example.com/notgenerics v1.0.0/go.mod' go.sum
+
+! go list -f '{{if eq .ImportPath "example.com/generics"}}{{.Module.GoVersion}}{{end}}' -deps -test example.com/m2/q
+stderr '^go: can''t load test package: \.\.'${/}m2${/}q${/}'q_test.go:3:8: example\.com/generics@v1\.0\.0: missing go.sum entry for go.mod file; to add it:\n\tgo mod download example\.com/generics$'
+
+go mod download -json example.com/generics
+stdout '"GoModSum":'
+go list -f '{{if eq .ImportPath "example.com/generics"}}{{.Module.GoVersion}}{{end}}' -deps -test example.com/m2/q
+stdout 1.18
+
+
+# At go 1.20 or earlier, 'go mod tidy' should preserve the historical go.sum
+# contents, but 'go test' should flag the missing checksums (instead of trying
+# to build the test dependency with the wrong language version).
+
+go mod tidy -go=1.20
+! go test -o $devnull -c all
+stderr '^# example.com/m2/q\n'..${/}m2${/}q${/}'q_test.go:3:8: example.com/generics@v1.0.0: missing go.sum entry for go.mod file; to add it:\n\tgo mod download example.com/generics$'
+
+go mod download -json example.com/generics
+go list -f '{{if eq .ImportPath "example.com/generics"}}{{.Module.GoVersion}}{{end}}' -deps -test example.com/m2/q
+stdout 1.18
+
+
+# Even at go 1.20 or earlier, 'go mod tidy' shouldn't need go.mod files or
+# checksums that it won't record.
+
+go mod tidy -go=1.20
+go clean -modcache # Remove checksums from the module cache, so that only go.sum is used.
+
+# Issue 60667: 'go list' without -mod=mod shouldn't report the checksums as
+# dirty either.
+go list -m -u all
+
+env OLDSUMDB=$GOSUMDB
+env GOSUMDB=bad
+go mod tidy
+
+env GOSUMDB=$OLDSUMDB
+
+
+# Regardless of the go version in go.mod, 'go get -t' should fetch
+# enough checksums to run 'go test' on the named package.
+
+rm p
+go mod tidy -go=1.20
+go list -m all
+! stdout example.com/generics
+go get -t example.com/m2/q@v1.0.0
+go list -f '{{if eq .ImportPath "example.com/generics"}}{{.Module.GoVersion}}{{end}}' -deps -test example.com/m2/q
+stdout 1.18
+[!short] go test -o $devnull -c example.com/m2/q
+
+
+-- m1/go.mod --
+module example.com/m1
+
+go 1.21
+
+require example.com/m2 v1.0.0
+replace example.com/m2 => ../m2
+-- m1/p/p.go --
+package p
+
+import _ "example.com/m2/q"
+-- m2/go.mod --
+module example.com/m2
+
+go 1.19
+
+require example.com/generics v1.0.0
+-- m2/q/q.go --
+package q
+-- m2/q/q_test.go --
+package q
+
+import _ "example.com/generics"
diff --git a/src/cmd/go/testdata/script/mod_sum_lookup.txt b/src/cmd/go/testdata/script/mod_sum_lookup.txt
new file mode 100644
index 0000000..7513f7f
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_sum_lookup.txt
@@ -0,0 +1,34 @@
+# When we attempt to resolve an import that doesn't exist, we should not save
+# hashes for downloaded modules.
+# Verifies golang.org/issue/36260.
+# TODO(golang.org/issue/26603): use 'go mod tidy -e' when implemented.
+go list -e -mod=mod -tags=ignore ./noexist
+! exists go.sum
+
+# When an import is resolved successfully, we should only save hashes for
+# the module that provides the package, not for other modules looked up.
+# Verifies golang.org/issue/31580.
+go get ./exist
+grep '^example.com/join v1.1.0 h1:' go.sum
+! grep '^example.com/join/subpkg' go.sum
+cp go.sum go.list.sum
+go mod tidy
+cmp go.sum go.list.sum
+
+-- go.mod --
+module m
+
+go 1.15
+
+-- noexist/use.go --
+// ignore tags prevents errors in 'go mod tidy'
+// +build ignore
+
+package use
+
+import _ "example.com/join/subpkg/noexist"
+
+-- exist/use.go --
+package use
+
+import _ "example.com/join/subpkg"
diff --git a/src/cmd/go/testdata/script/mod_sum_readonly.txt b/src/cmd/go/testdata/script/mod_sum_readonly.txt
new file mode 100644
index 0000000..c426073
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_sum_readonly.txt
@@ -0,0 +1,87 @@
+# Test that go.sum does not get updated when -mod=readonly flag is set
+env GO111MODULE=on
+
+# When a sum is needed to load the build list, we get an error for the
+# specific module. The .mod file is not downloaded, and go.sum is not written.
+! go list -m all
+stderr '^go: rsc.io/quote@v1.5.2: missing go.sum entry for go.mod file; to add it:\n\tgo mod download rsc.io/quote$'
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.mod
+! exists go.sum
+
+# If go.sum exists but contains hashes from an algorithm we don't know about,
+# we should see the same error.
+cp go.sum.h2only go.sum
+! go list -m all
+stderr '^go: rsc.io/quote@v1.5.2: missing go.sum entry for go.mod file; to add it:\n\tgo mod download rsc.io/quote$'
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.mod
+cmp go.sum go.sum.h2only
+rm go.sum
+
+# If we replace a module, we should see a missing sum error for the replacement.
+cp go.mod go.mod.orig
+go mod edit -replace rsc.io/quote@v1.5.2=rsc.io/quote@v1.5.1
+! go list -m all
+stderr '^go: rsc.io/quote@v1.5.2 \(replaced by rsc.io/quote@v1.5.1\): missing go.sum entry for go.mod file; to add it:\n\tgo mod download rsc.io/quote$'
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.1.mod
+! exists go.sum
+cp go.mod.orig go.mod
+
+# Control: when sums are present, loading the build list downloads .mod files.
+cp go.sum.buildlistonly go.sum
+go list -m all
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.mod
+
+
+# When a sum is needed to load a .mod file for a package outside the build list,
+# we get a generic missing import error.
+! go list example.com/doesnotexist
+stderr '^no required module provides package example.com/doesnotexist; to add it:\n\tgo get example.com/doesnotexist$'
+
+# When a sum is needed to load a .zip file, we get a more specific error.
+# The .zip file is not downloaded.
+! go list rsc.io/quote
+stderr '^missing go.sum entry for module providing package rsc.io/quote; to add:\n\tgo mod download rsc.io/quote$'
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip
+
+# The error is attached to the package from the missing module. We can load
+# a package that imports it without that error.
+go list -e -deps -f '{{.ImportPath}}{{with .Error}} {{.Err}}{{end}}' .
+stdout '^m$'
+stdout '^rsc.io/quote missing go.sum entry for module providing package rsc.io/quote \(imported by m\); to add:\n\tgo get m$'
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip
+
+# go.sum should not have been written.
+cmp go.sum go.sum.buildlistonly
+
+# Control: when sums are present, 'go list' downloads .zip files.
+cp go.sum.tidy go.sum
+go list .
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip
+
+-- go.mod --
+module m
+
+go 1.15
+
+require rsc.io/quote v1.5.2
+-- use.go --
+package use
+
+import _ "rsc.io/quote"
+-- go.sum.h2only --
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h2:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+rsc.io/quote v1.5.2/go.mod h2:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
+rsc.io/sampler v1.3.0/go.mod h2:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+-- go.sum.buildlistonly --
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+-- go.sum.tidy --
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw=
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0=
+rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
+rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+rsc.io/testonly v1.0.0 h1:K/VWHdO+Jv7woUXG0GzVNx1czBXUt3Ib1deaMn+xk64=
+rsc.io/testonly v1.0.0/go.mod h1:OqmGbIFOcF+XrFReLOGZ6BhMM7uMBiQwZsyNmh74SzY=
diff --git a/src/cmd/go/testdata/script/mod_sum_replaced.txt b/src/cmd/go/testdata/script/mod_sum_replaced.txt
new file mode 100644
index 0000000..6c322a0
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_sum_replaced.txt
@@ -0,0 +1,28 @@
+env GO111MODULE=on
+
+# After 'go get', the go.sum file should contain the sum for the module.
+go get rsc.io/quote@v1.5.0
+grep 'rsc.io/quote v1.5.0' go.sum
+
+# If we replace the module and run 'go mod tidy', we should get a sum for the replacement.
+go mod edit -replace rsc.io/quote@v1.5.0=rsc.io/quote@v1.5.1
+go mod tidy
+grep 'rsc.io/quote v1.5.1' go.sum
+cp go.sum go.sum.tidy
+
+# 'go mod vendor' should preserve that sum, and should not need to add any new entries.
+go mod vendor
+grep 'rsc.io/quote v1.5.1' go.sum
+cmp go.sum go.sum.tidy
+
+-- go.mod --
+module golang.org/issue/27868
+
+require rsc.io/quote v1.5.0
+
+-- main.go --
+package main
+
+import _ "rsc.io/quote"
+
+func main() {}
diff --git a/src/cmd/go/testdata/script/mod_sumdb.txt b/src/cmd/go/testdata/script/mod_sumdb.txt
new file mode 100644
index 0000000..d06db4a
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_sumdb.txt
@@ -0,0 +1,45 @@
+env GO111MODULE=on
+env sumdb=$GOSUMDB
+env proxy=$GOPROXY
+env GOPROXY GONOPROXY GOSUMDB GONOSUMDB
+env dbname=localhost.localdev/sumdb
+
+# disagreeing with the sumdb produces security errors
+# (this also populates tiles on the sumdb server).
+cp go.mod.orig go.mod
+env GOSUMDB=$sumdb' '$proxy/sumdb-wrong
+! go get rsc.io/quote
+stderr 'go: rsc.io/quote@v1.5.2: verifying module: checksum mismatch'
+stderr 'downloaded: h1:3fEy'
+stderr 'localhost.localdev/sumdb: h1:wrong'
+stderr 'SECURITY ERROR\nThis download does NOT match the one reported by the checksum server.'
+! go get rsc.io/sampler
+! go get golang.org/x/text
+
+go mod edit -require rsc.io/quote@v1.5.2
+! go mod tidy
+stderr 'go: rsc.io/quote@v1.5.2: verifying go.mod: checksum mismatch'
+stderr 'SECURITY ERROR\n'
+
+rm go.sum
+
+# switching to truthful sumdb detects timeline inconsistency
+cp go.mod.orig go.mod
+env GOSUMDB=$sumdb
+! go get rsc.io/fortune
+stderr 'SECURITY ERROR\ngo.sum database server misbehavior detected!'
+stderr 'proof of misbehavior:'
+
+# removing the cached wrong tree head and cached tiles clears the bad data
+rm $GOPATH/pkg/sumdb/$dbname/latest
+go clean -modcache
+go get rsc.io/fortune
+
+-- go.mod.orig --
+module m
+
+go 1.16
+-- m.go --
+package m
+
+import _ "rsc.io/quote"
diff --git a/src/cmd/go/testdata/script/mod_sumdb_cache.txt b/src/cmd/go/testdata/script/mod_sumdb_cache.txt
new file mode 100644
index 0000000..063fd20
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_sumdb_cache.txt
@@ -0,0 +1,47 @@
+env GO111MODULE=on
+env sumdb=$GOSUMDB
+env proxy=$GOPROXY
+env GOPROXY GONOPROXY GOSUMDB GONOSUMDB
+
+# rejected proxy fails verification
+cp go.mod.orig go.mod
+rm go.sum
+env GOPROXY=$proxy/sumdb-503
+! go get rsc.io/quote
+stderr 503
+
+# fetch through working proxy is OK
+cp go.mod.orig go.mod
+rm go.sum
+env GOPROXY=$proxy
+go get rsc.io/quote
+
+# repeated fetch works entirely from cache, does not consult sumdb
+cp go.mod.orig go.mod
+rm go.sum
+env GOPROXY=$proxy/sumdb-503
+go get rsc.io/quote
+rm go.sum
+
+# fetch specific module can work without proxy, using cache or go.sum
+cp go.mod.orig go.mod
+rm go.sum
+env GOPROXY=off
+go get rsc.io/quote@v1.5.2 # using cache
+rm $GOPATH/pkg/mod/cache/download/sumdb/localhost.localdev/sumdb/lookup/rsc.io/quote@v1.5.2
+go get rsc.io/quote@v1.5.2 # using go.sum
+
+# fetch fails once we lose access to both cache and go.sum
+rm go.sum
+env GOPROXY=$proxy/sumdb-504
+! go get rsc.io/quote@v1.5.2
+stderr 504
+
+# GOINSECURE does not bypass checksum lookup
+env GOINSECURE=rsc.io
+env GOPROXY=$proxy/sumdb-504
+! go get rsc.io/quote@v1.5.2
+stderr 504
+
+-- go.mod.orig --
+module m
diff --git a/src/cmd/go/testdata/script/mod_sumdb_file_path.txt b/src/cmd/go/testdata/script/mod_sumdb_file_path.txt
new file mode 100644
index 0000000..2f42cb5
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_sumdb_file_path.txt
@@ -0,0 +1,58 @@
+[!net:proxy.golang.org] skip
+[!net:sum.golang.org] skip
+
+env GO111MODULE=on
+[go-builder] env GOSUMDB=
+[!go-builder] env GOSUMDB=sum.golang.org # Set explicitly in case GOROOT/go.env is modified.
+env GOPATH=$WORK/gopath1
+
+# With a file-based proxy with an empty checksum directory,
+# downloading a new module should fail, even if a subsequent
+# proxy contains a more complete mirror of the sum database.
+#
+# TODO(bcmills): The error message here is a bit redundant.
+# It comes from the sumweb package, which isn't yet producing structured errors.
+[GOOS:windows] env GOPROXY=file:///$WORK/sumproxy,https://proxy.golang.org
+[!GOOS:windows] env GOPROXY=file://$WORK/sumproxy,https://proxy.golang.org
+! go get golang.org/x/text@v0.3.2
+stderr '^go: golang.org/x/text@v0.3.2: verifying module: golang.org/x/text@v0.3.2: reading file://.*/sumdb/sum.golang.org/lookup/golang.org/x/text@v0.3.2: (no such file or directory|.*cannot find the path specified.*)'
+
+# If the proxy does not claim to support the database,
+# checksum verification should fall through to the next proxy,
+# and downloading should succeed.
+[GOOS:windows] env GOPROXY=file:///$WORK/emptyproxy,https://proxy.golang.org
+[!GOOS:windows] env GOPROXY=file://$WORK/emptyproxy,https://proxy.golang.org
+go get golang.org/x/text@v0.3.2
+
+# After a successful sumdb lookup, the lookup can be repeated
+# using the download cache as a proxy.
+cp supported $GOPATH/pkg/mod/cache/download/sumdb/sum.golang.org/supported
+[GOOS:windows] env GOPROXY=file:///$WORK/gopath1/pkg/mod/cache/download,file:///$WORK/sumproxy
+[!GOOS:windows] env GOPROXY=file://$WORK/gopath1/pkg/mod/cache/download,file://$WORK/sumproxy
+env GOPATH=$WORK/gopath2
+rm go.sum
+go get -x -v golang.org/x/text@v0.3.2
+
+# Once the checksum is present in the go.sum file,
+# an empty file-based sumdb can be used in conjunction with
+# a fallback module mirror.
+grep golang.org/x/text go.sum
+env GOPATH=$WORK/gopath3
+[GOOS:windows] env GOPROXY=file:///$WORK/sumproxy
+[!GOOS:windows] env GOPROXY=file://$WORK/sumproxy
+! go get golang.org/x/text@v0.3.2
+[GOOS:windows] env GOPROXY=file:///$WORK/sumproxy,https://proxy.golang.org
+[!GOOS:windows] env GOPROXY=file://$WORK/sumproxy,https://proxy.golang.org
+go get golang.org/x/text@v0.3.2
+
+-- supported --
+
+-- go.mod --
+module example.com
+go 1.13
+-- $WORK/emptyproxy/README.md --
+This proxy contains no modules.
+-- $WORK/sumproxy/README.md --
+This proxy contains no modules.
+-- $WORK/sumproxy/sumdb/sum.golang.org/supported --
+This proxy blocks checksum downloads from sum.golang.org.
diff --git a/src/cmd/go/testdata/script/mod_sumdb_golang.txt b/src/cmd/go/testdata/script/mod_sumdb_golang.txt
new file mode 100644
index 0000000..067e2e3
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_sumdb_golang.txt
@@ -0,0 +1,83 @@
+# Test default GOPROXY and GOSUMDB
+[go-builder] env GOPROXY=
+[go-builder] env GOSUMDB=
+[go-builder] go env GOPROXY
+[go-builder] stdout '^https://proxy.golang.org,direct$'
+[go-builder] go env GOSUMDB
+[go-builder] stdout '^sum.golang.org$'
+[go-builder] env GOPROXY=https://proxy.golang.org
+[go-builder] go env GOSUMDB
+[go-builder] stdout '^sum.golang.org$'
+
+# Download direct from github.
+
+[!net:proxy.golang.org] skip
+[!net:sum.golang.org] skip
+[!git] skip
+env GOSUMDB=sum.golang.org
+env GOPROXY=direct
+
+go get rsc.io/quote@v1.5.2
+cp go.sum saved.sum
+
+
+# Download from proxy.golang.org with go.sum entry already.
+# Use 'go list' instead of 'go get' since the latter may download extra go.mod
+# files not listed in go.sum.
+
+go clean -modcache
+env GOSUMDB=sum.golang.org
+env GOPROXY=https://proxy.golang.org,direct
+
+go list -x -m all # Download go.mod files.
+! stderr github
+stderr proxy.golang.org/rsc.io/quote
+! stderr sum.golang.org/tile
+! stderr sum.golang.org/lookup/rsc.io/quote
+
+go list -x -deps rsc.io/quote # Download module source.
+! stderr github
+stderr proxy.golang.org/rsc.io/quote
+! stderr sum.golang.org/tile
+! stderr sum.golang.org/lookup/rsc.io/quote
+
+cmp go.sum saved.sum
+
+
+# Download again.
+# Should use the checksum database to validate new go.sum lines,
+# but not need to fetch any new data from the proxy.
+
+rm go.sum
+
+go list -mod=mod -x -m all # Add checksums for go.mod files.
+stderr sum.golang.org/tile
+! stderr github
+! stderr proxy.golang.org/rsc.io/quote
+stderr sum.golang.org/lookup/rsc.io/quote
+
+go list -mod=mod -x rsc.io/quote # Add checksums for module source.
+! stderr . # Adds checksums, but for entities already in the module cache.
+
+cmp go.sum saved.sum
+
+
+# test fallback to direct
+
+env TESTGOPROXY404=1
+go clean -modcache
+rm go.sum
+
+go list -mod=mod -x -m all # Download go.mod files
+stderr 'proxy.golang.org.*404 testing'
+stderr github.com/rsc
+
+go list -mod=mod -x rsc.io/quote # Download module source.
+stderr 'proxy.golang.org.*404 testing'
+stderr github.com/rsc
+
+cmp go.sum saved.sum
+
+
+-- go.mod --
+module m
diff --git a/src/cmd/go/testdata/script/mod_sumdb_proxy.txt b/src/cmd/go/testdata/script/mod_sumdb_proxy.txt
new file mode 100644
index 0000000..194c0c9
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_sumdb_proxy.txt
@@ -0,0 +1,65 @@
+env GO111MODULE=on
+env sumdb=$GOSUMDB
+env proxy=$GOPROXY
+env GOPROXY GONOPROXY GOSUMDB GONOSUMDB
+
+# basic fetch (through proxy) works
+cp go.mod.orig go.mod
+go get rsc.io/fortune@v1.0.0 # note: must use test proxy, does not exist in real world
+rm $GOPATH/pkg/mod/cache/download/sumdb # rm sumdb cache but NOT package download cache
+rm go.sum
+
+# can fetch by explicit URL
+cp go.mod.orig go.mod
+env GOSUMDB=$sumdb' '$proxy/sumdb-direct
+go get rsc.io/fortune@v1.0.0
+rm $GOPATH/pkg/mod/cache/download/sumdb
+rm go.sum
+
+# direct access fails (because localhost.localdev does not exist)
+# web.get is providing the error message - there's no actual network access.
+cp go.mod.orig go.mod
+env GOSUMDB=$sumdb
+env GOPROXY=direct
+! go get rsc.io/fortune@v1.0.0
+stderr 'verifying module: rsc.io/fortune@v1.0.0: .*: no such host localhost.localdev'
+rm $GOPATH/pkg/mod/cache/download/sumdb
+rm go.sum
+
+# proxy 404 falls back to direct access (which fails)
+cp go.mod.orig go.mod
+env GOSUMDB=$sumdb
+env GOPROXY=$proxy/sumdb-404
+! go get rsc.io/fortune@v1.0.0
+stderr 'verifying.*localhost.localdev'
+rm $GOPATH/pkg/mod/cache/download/sumdb
+rm go.sum
+
+# proxy non-200/404/410 stops direct access
+cp go.mod.orig go.mod
+env GOSUMDB=$sumdb
+env GOPROXY=$proxy/sumdb-503
+! go get rsc.io/fortune@v1.0.0
+stderr '503 Service Unavailable'
+rm $GOPATH/pkg/mod/cache/download/sumdb
+rm go.sum
+
+# the error from the last attempted proxy should be returned.
+cp go.mod.orig go.mod
+env GOSUMDB=$sumdb
+env GOPROXY=$proxy/sumdb-404,$proxy/sumdb-503
+! go get rsc.io/fortune@v1.0.0
+stderr '503 Service Unavailable'
+rm $GOPATH/pkg/mod/cache/download/sumdb
+rm go.sum
+
+# if proxies are separated with '|', fallback is allowed on any error.
+cp go.mod.orig go.mod
+env GOSUMDB=$sumdb
+env GOPROXY=$proxy/sumdb-503|https://0.0.0.0|$proxy
+go get rsc.io/fortune@v1.0.0
+rm $GOPATH/pkg/mod/cache/download/sumdb
+rm go.sum
+
+-- go.mod.orig --
+module m
diff --git a/src/cmd/go/testdata/script/mod_symlink.txt b/src/cmd/go/testdata/script/mod_symlink.txt
new file mode 100644
index 0000000..0604e1a
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_symlink.txt
@@ -0,0 +1,45 @@
+env GO111MODULE=on
+[!symlink] skip
+
+# 'go get' should resolve modules of imported packages.
+go get
+go list -deps -f '{{.Module}}' .
+stdout golang.org/x/text
+
+go get ./subpkg
+go list -deps -f '{{.Module}}' ./subpkg
+stdout golang.org/x/text
+
+# Create a copy of the module using symlinks in src/links.
+mkdir links
+symlink links/go.mod -> $GOPATH/src/go.mod
+symlink links/go.sum -> $GOPATH/src/go.sum
+symlink links/issue.go -> $GOPATH/src/issue.go
+mkdir links/subpkg
+symlink links/subpkg/issue.go -> $GOPATH/src/subpkg/issue.go
+
+# We should see the copy as a valid module root.
+cd links
+go env GOMOD
+stdout links[/\\]go.mod
+go list -m
+stdout golang.org/issue/28107
+
+# The symlink-based copy should contain the same packages
+# and have the same dependencies as the original.
+go list -deps -f '{{.Module}}' .
+stdout golang.org/x/text
+go list -deps -f '{{.Module}}' ./subpkg
+stdout golang.org/x/text
+
+-- go.mod --
+module golang.org/issue/28107
+
+-- issue.go --
+package issue
+
+import _ "golang.org/x/text/language"
+-- subpkg/issue.go --
+package issue
+
+import _ "golang.org/x/text/language"
diff --git a/src/cmd/go/testdata/script/mod_symlink_dotgo.txt b/src/cmd/go/testdata/script/mod_symlink_dotgo.txt
new file mode 100644
index 0000000..d4cc143
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_symlink_dotgo.txt
@@ -0,0 +1,17 @@
+env GO111MODULE=on
+[!symlink] skip
+
+symlink dir.go -> dir
+
+# Issue #39841: symlinks to directories should be ignored, not treated as source files.
+go list -f '{{range .GoFiles}}{{.}}{{"\n"}}{{end}}' .
+stdout 'p\.go$'
+! stdout 'dir\.go$'
+
+-- go.mod --
+module example.com
+go 1.15
+-- p.go --
+package p
+-- dir/README.txt --
+This file exists to ensure that dir is a directory.
diff --git a/src/cmd/go/testdata/script/mod_tagged_import_cycle.txt b/src/cmd/go/testdata/script/mod_tagged_import_cycle.txt
new file mode 100644
index 0000000..0491acb
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_tagged_import_cycle.txt
@@ -0,0 +1,106 @@
+# Because 'go mod' subcommands ignore build constraints, they can encounter
+# package-import cycles that are not possible in an ordinary build. This test
+# verifies that such cycles are handled even when they cross module boundaries.
+
+# First, verify that the import graph depends on build tags as expected.
+go list -deps example.com/left
+stdout '^example.com/right$'
+go list -deps example.com/right
+! stdout left
+
+env GOFLAGS=-tags=mirror
+go list -deps example.com/left
+! stdout right
+go list -deps example.com/right
+stdout '^example.com/left$'
+env GOFLAGS=''
+
+# 'go mod why' should be agnostic to build tags.
+go mod why example.com/left
+stdout '^example.com/chiral$\n^example.com/left$'
+go mod why example.com/right
+stdout '^example.com/chiral$\n^example.com/right$'
+
+env GOFLAGS='-tags=mirror'
+go mod why example.com/left
+stdout '^example.com/chiral$\n^example.com/left$'
+go mod why example.com/right
+stdout '^example.com/chiral$\n^example.com/right$'
+env GOFLAGS=''
+
+# 'go mod tidy' should successfully handle the cycle.
+env GOFLAGS=-mod=readonly
+go mod tidy
+
+# 'go mod vendor' should copy in both packages without crashing.
+go mod vendor
+exists vendor/example.com/left/default.go
+exists vendor/example.com/left/mirror.go
+exists vendor/example.com/right/default.go
+exists vendor/example.com/right/mirror.go
+
+-- go.mod --
+module example.com/chiral
+
+go 1.14
+
+require (
+ example.com/left v0.1.0
+ example.com/right v0.1.0
+)
+
+replace (
+ example.com/left => ./left
+ example.com/right => ./right
+)
+-- chiral.go --
+// Package chiral imports packages in an order that depends on build tags.
+package chiral
+-- default.go --
+// +build !mirror
+
+package chiral
+
+import _ "example.com/left"
+-- mirror.go --
+// +build mirror
+
+package chiral
+
+import _ "example.com/right"
+-- left/go.mod --
+module example.com/left
+
+go 1.14
+
+require example.com/right v0.1.0
+
+replace example.com/right v0.1.0 => ../right
+-- left/default.go --
+// +build !mirror
+
+package left
+
+import _ "example.com/right"
+-- left/mirror.go --
+// +build mirror
+
+package left
+-- right/go.mod --
+module example.com/right
+
+go 1.14
+
+require example.com/left v0.1.0
+
+replace example.com/left v0.1.0 => ../left
+-- right/default.go --
+// +build !mirror
+
+package right
+-- right/mirror.go --
+// +build mirror
+
+package right
+
+import _ "example.com/left"
diff --git a/src/cmd/go/testdata/script/mod_test.txt b/src/cmd/go/testdata/script/mod_test.txt
new file mode 100644
index 0000000..76f1d7a
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_test.txt
@@ -0,0 +1,130 @@
+env GO111MODULE=on
+env GOFLAGS=-mod=mod
+[short] skip
+
+# TODO(bcmills): Convert the 'go test' calls below to 'go list -test' once 'go
+# list' is more sensitive to package loading errors.
+
+# A test in the module's root package should work.
+cd a/
+cp go.mod.empty go.mod
+go list -test
+! stderr error
+
+cp go.mod.empty go.mod
+go list -deps
+! stdout ^testing$
+
+# list all should include test dependencies, like testing
+cp go.mod.empty go.mod
+go list all
+stdout ^testing$
+stdout ^rsc.io/quote$
+stdout ^rsc.io/testonly$
+
+# list -deps -tests should also include testing
+# but not deps of tests of deps (rsc.io/testonly).
+go list -deps -test
+stdout ^testing$
+stdout ^rsc.io/quote$
+! stdout ^rsc.io/testonly$
+
+# list -test all should succeed
+cp go.mod.empty go.mod
+go list -test all
+stdout '^testing'
+
+cp go.mod.empty go.mod
+go list -test
+! stderr error
+
+# A test with the "_test" suffix in the module root should also work.
+cd ../b/
+go list -test
+! stderr error
+
+# A test with the "_test" suffix of a *package* with a "_test" suffix should
+# even work (not that you should ever do that).
+cd ../c_test
+go list -test
+! stderr error
+
+cd ../d_test
+go list -test
+! stderr error
+
+cd ../e
+go list -test
+! stderr error
+
+-- a/go.mod.empty --
+module example.com/user/a
+
+go 1.11
+
+-- a/a.go --
+package a
+
+-- a/a_test.go --
+package a
+
+import "testing"
+import _ "rsc.io/quote"
+
+func Test(t *testing.T) {}
+
+-- b/go.mod --
+module example.com/user/b
+
+-- b/b.go --
+package b
+
+-- b/b_test.go --
+package b_test
+
+import "testing"
+
+func Test(t *testing.T) {}
+
+-- c_test/go.mod --
+module example.com/c_test
+
+-- c_test/umm.go --
+// Package c_test is the non-test package for its import path!
+package c_test
+
+-- c_test/c_test_test.go --
+package c_test_test
+
+import "testing"
+
+func Test(t *testing.T) {}
+
+-- d_test/go.mod --
+// Package d is an ordinary package in a deceptively-named directory.
+module example.com/d
+
+-- d_test/d.go --
+package d
+
+-- d_test/d_test.go --
+package d_test
+
+import "testing"
+
+func Test(t *testing.T) {}
+
+-- e/go.mod --
+module example.com/e_test
+
+-- e/wat.go --
+// Package e_test is the non-test package for its import path,
+// in a deceptively-named directory!
+package e_test
+
+-- e/e_test.go --
+package e_test_test
+
+import "testing"
+
+func Test(t *testing.T) {}
diff --git a/src/cmd/go/testdata/script/mod_test_cached.txt b/src/cmd/go/testdata/script/mod_test_cached.txt
new file mode 100644
index 0000000..3da4358
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_test_cached.txt
@@ -0,0 +1,76 @@
+[short] skip
+
+env GO111MODULE=on
+env GOCACHE=$WORK/gocache
+env GODEBUG=gocachetest=1
+
+# The first run of a test should not be cached.
+# The second run should be.
+go test -run=WriteTmp .
+! stdout '(cached)'
+go test -run=WriteTmp .
+stdout '(cached)'
+
+# 'go test' without arguments should never be cached.
+go test -run=WriteTmp
+! stdout '(cached)'
+go test -run=WriteTmp
+! stdout '(cached)'
+
+# We should never cache a test run from command-line files.
+go test -run=WriteTmp ./foo_test.go
+! stdout '(cached)'
+go test -run=WriteTmp ./foo_test.go
+! stdout '(cached)'
+
+[!exec:sleep] stop
+# The go command refuses to cache access to files younger than 2s, so sleep that long.
+exec sleep 2
+
+# Touching a file that the test reads from within its testdata should invalidate the cache.
+go test -run=ReadTestdata .
+! stdout '(cached)'
+go test -run=ReadTestdata .
+stdout '(cached)'
+cp testdata/bar.txt testdata/foo.txt
+go test -run=ReadTestdata .
+! stdout '(cached)'
+
+-- go.mod --
+module golang.org/issue/29111/foo
+
+-- foo.go --
+package foo
+
+-- testdata/foo.txt --
+foo
+-- testdata/bar.txt --
+bar
+
+-- foo_test.go --
+package foo_test
+
+import (
+ "os"
+ "path/filepath"
+ "testing"
+)
+
+func TestWriteTmp(t *testing.T) {
+ dir, err := os.MkdirTemp("", "")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(dir)
+ err = os.WriteFile(filepath.Join(dir, "x"), nil, 0666)
+ if err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestReadTestdata(t *testing.T) {
+ _, err := os.ReadFile("testdata/foo.txt")
+ if err != nil {
+ t.Fatal(err)
+ }
+}
diff --git a/src/cmd/go/testdata/script/mod_test_files.txt b/src/cmd/go/testdata/script/mod_test_files.txt
new file mode 100644
index 0000000..6f520c7
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_test_files.txt
@@ -0,0 +1,50 @@
+env GO111MODULE=on
+
+cd foo
+
+# Testing an explicit source file should use the same import visibility as the
+# package in the same directory.
+go list -test -deps
+go list -test -deps foo_test.go
+
+# If the file is inside the main module's vendor directory, it should have
+# visibility based on the vendor-relative import path.
+mkdir vendor/example.com/foo
+cp foo_test.go vendor/example.com/foo
+go list -test -deps vendor/example.com/foo/foo_test.go
+
+# If the file is outside the main module entirely, it should be treated as outside.
+cp foo_test.go ../foo_test.go
+! go list -test -deps ../foo_test.go
+stderr 'use of internal package'
+
+-- foo/go.mod --
+module example.com/foo
+go 1.12
+require example.com/internal v0.0.0
+replace example.com/internal => ../internal
+
+-- foo/internal.go --
+package foo
+import _ "example.com/internal"
+
+-- foo/foo_test.go --
+package foo_test
+
+import (
+ "testing"
+ "example.com/internal"
+)
+
+func TestHacksEnabled(t *testing.T) {
+ if !internal.Hacks {
+ t.Fatal("hacks not enabled")
+ }
+}
+
+-- internal/go.mod --
+module example.com/internal
+
+-- internal/internal.go --
+package internal
+const Hacks = true
diff --git a/src/cmd/go/testdata/script/mod_tidy.txt b/src/cmd/go/testdata/script/mod_tidy.txt
new file mode 100644
index 0000000..b1d9371
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_tidy.txt
@@ -0,0 +1,72 @@
+env GO111MODULE=on
+
+# tidy removes unused y, but everything else is used
+go mod tidy -v
+stderr '^unused y.1'
+! stderr '^unused [^y]'
+
+grep 'go 1.10' go.mod
+
+go list -m all
+! stdout '^y'
+stdout '^w.1 v1.2.0'
+stdout '^z.1 v1.2.0'
+
+# empty tidy should not crash
+cd triv
+! grep 'go ' go.mod
+go mod tidy
+
+# tidy should add missing go line
+grep 'go ' go.mod
+
+-- go.mod --
+module m
+
+go 1.10
+
+require (
+ x.1 v1.0.0
+ y.1 v1.0.0
+ w.1 v1.2.0
+)
+
+replace x.1 v1.0.0 => ./x
+replace y.1 v1.0.0 => ./y
+replace z.1 v1.1.0 => ./z
+replace z.1 v1.2.0 => ./z
+replace w.1 => ./w
+
+-- m.go --
+package m
+
+import _ "x.1"
+import _ "z.1/sub"
+
+-- w/go.mod --
+module w
+
+-- w/w.go --
+package w
+
+-- x/go.mod --
+module x
+require w.1 v1.1.0
+require z.1 v1.1.0
+
+-- x/x.go --
+package x
+import _ "w.1"
+
+-- y/go.mod --
+module y
+require z.1 v1.2.0
+
+-- z/go.mod --
+module z
+
+-- z/sub/sub.go --
+package sub
+
+-- triv/go.mod --
+module triv
diff --git a/src/cmd/go/testdata/script/mod_tidy_compat.txt b/src/cmd/go/testdata/script/mod_tidy_compat.txt
new file mode 100644
index 0000000..724c83e
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_tidy_compat.txt
@@ -0,0 +1,95 @@
+# https://golang.org/issue/46141: 'go mod tidy' for a Go 1.17 module should by
+# default preserve enough checksums for the module to be used by Go 1.16.
+#
+# We don't have a copy of Go 1.16 handy, but we can simulate it by editing the
+# 'go' version in the go.mod file to 1.16, without actually updating the
+# requirements to match.
+
+[short] skip
+
+env MODFMT='{{with .Module}}{{.Path}} {{.Version}}{{end}}'
+
+
+# This module has the same module dependency graph in Go 1.16 as in Go 1.17,
+# but in 1.16 requires (checksums for) additional (irrelevant) go.mod files.
+#
+# The module graph under both versions looks like:
+#
+# m ---- example.com/version v1.1.0
+# |
+# + ---- example.net/lazy v0.1.0 ---- example.com/version v1.0.1
+#
+# Go 1.17 avoids loading the go.mod file for example.com/version v1.0.1
+# (because it is lower than the version explicitly required by m,
+# and the module that requires it — m — specifies 'go 1.17').
+#
+# That go.mod file happens not to affect the final 1.16 module graph anyway,
+# so the pruned graph is equivalent to the unpruned one.
+
+cp go.mod go.mod.orig
+go mod tidy
+cmp go.mod go.mod.orig
+
+go list -m all
+cmp stdout m_all.txt
+
+go mod edit -go=1.16
+go list -m all
+cmp stdout m_all.txt
+
+
+# If we explicitly drop compatibility with 1.16, we retain fewer checksums,
+# which gives a cleaner go.sum file but causes 1.16 to fail in readonly mode.
+
+cp go.mod.orig go.mod
+go mod tidy -compat=1.17
+cmp go.mod go.mod.orig
+
+go list -m all
+cmp stdout m_all.txt
+
+go mod edit -go=1.16
+! go list -m all
+stderr '^go: example.net/lazy@v0.1.0 requires\n\texample.com/version@v1.0.1: missing go.sum entry for go.mod file; to add it:\n\tgo mod download example.com/version$'
+
+
+-- go.mod --
+// Module m happens to have the exact same build list as what would be
+// selected under Go 1.16, but computes that build list without looking at
+// as many go.mod files.
+module example.com/m
+
+go 1.17
+
+replace example.net/lazy v0.1.0 => ./lazy
+
+require (
+ example.com/version v1.1.0
+ example.net/lazy v0.1.0
+)
+-- m_all.txt --
+example.com/m
+example.com/version v1.1.0
+example.net/lazy v0.1.0 => ./lazy
+-- compatible.go --
+package compatible
+
+import (
+ _ "example.com/version"
+ _ "example.net/lazy"
+)
+-- lazy/go.mod --
+// Module lazy requires example.com/version v1.0.1.
+//
+// However, since this module is lazy, its dependents
+// should not need checksums for that version of the module
+// unless they actually import packages from it.
+module example.net/lazy
+
+go 1.17
+
+require example.com/version v1.0.1
+-- lazy/lazy.go --
+package lazy
+
+import _ "example.com/version"
diff --git a/src/cmd/go/testdata/script/mod_tidy_compat_added.txt b/src/cmd/go/testdata/script/mod_tidy_compat_added.txt
new file mode 100644
index 0000000..b3f75ad
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_tidy_compat_added.txt
@@ -0,0 +1,105 @@
+# https://golang.org/issue/46141: 'go mod tidy' for a Go 1.17 module should by
+# default preserve enough checksums for the module to be used by Go 1.16.
+#
+# We don't have a copy of Go 1.16 handy, but we can simulate it by editing the
+# 'go' version in the go.mod file to 1.16, without actually updating the
+# requirements to match.
+
+[short] skip
+
+env MODFMT='{{with .Module}}{{.Path}} {{.Version}}{{end}}'
+
+
+# For this module, Go 1.17 produces an error for one module, and Go 1.16
+# produces a different error for a different module.
+
+cp go.mod go.mod.orig
+
+! go mod tidy
+
+stderr '^go: example\.com/m imports\n\texample\.net/added: module example\.net/added@latest found \(v0\.3\.0, replaced by \./a1\), but does not contain package example\.net/added$'
+
+cmp go.mod go.mod.orig
+
+
+# When we run 'go mod tidy -e', we should proceed past the first error and follow
+# it with a second error describing the version discrepancy.
+#
+# We should not provide advice on how to push past the version discrepancy,
+# because the '-e' flag should already do that, writing out an otherwise-tidied
+# go.mod file.
+
+go mod tidy -e
+
+stderr '^go: example\.com/m imports\n\texample\.net/added: module example\.net/added@latest found \(v0\.3\.0, replaced by \./a1\), but does not contain package example\.net/added\ngo: example\.net/added failed to load from any module,\n\tbut go 1\.16 would load it from example\.net/added@v0\.2\.0$'
+
+! stderr '\n\tgo mod tidy'
+
+cmp go.mod go.mod.tidy
+
+
+-- go.mod --
+module example.com/m
+
+go 1.17
+
+replace (
+ example.net/added v0.1.0 => ./a1
+ example.net/added v0.2.0 => ./a2
+ example.net/added v0.3.0 => ./a1
+ example.net/lazy v0.1.0 => ./lazy
+ example.net/pruned v0.1.0 => ./pruned
+)
+
+require (
+ example.net/added v0.1.0
+ example.net/lazy v0.1.0
+)
+-- go.mod.tidy --
+module example.com/m
+
+go 1.17
+
+replace (
+ example.net/added v0.1.0 => ./a1
+ example.net/added v0.2.0 => ./a2
+ example.net/added v0.3.0 => ./a1
+ example.net/lazy v0.1.0 => ./lazy
+ example.net/pruned v0.1.0 => ./pruned
+)
+
+require example.net/lazy v0.1.0
+-- m.go --
+package m
+
+import (
+ _ "example.net/added"
+ _ "example.net/lazy"
+)
+
+-- a1/go.mod --
+module example.net/added
+
+go 1.17
+-- a2/go.mod --
+module example.net/added
+
+go 1.17
+-- a2/added.go --
+package added
+
+-- lazy/go.mod --
+module example.net/lazy
+
+go 1.17
+
+require example.net/pruned v0.1.0
+-- lazy/lazy.go --
+package lazy
+
+-- pruned/go.mod --
+module example.net/pruned
+
+go 1.17
+
+require example.net/added v0.2.0
diff --git a/src/cmd/go/testdata/script/mod_tidy_compat_ambiguous.txt b/src/cmd/go/testdata/script/mod_tidy_compat_ambiguous.txt
new file mode 100644
index 0000000..5316220
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_tidy_compat_ambiguous.txt
@@ -0,0 +1,97 @@
+# https://golang.org/issue/46141: 'go mod tidy' for a Go 1.17 module should by
+# default preserve enough checksums for the module to be used by Go 1.16.
+#
+# We don't have a copy of Go 1.16 handy, but we can simulate it by editing the
+# 'go' version in the go.mod file to 1.16, without actually updating the
+# requirements to match.
+
+[short] skip
+
+env MODFMT='{{with .Module}}{{.Path}} {{.Version}}{{end}}'
+
+# For this module, the dependency providing package
+# example.net/ambiguous/nested/pkg is unambiguous in Go 1.17 (because only one
+# root of the module graph contains the package), whereas it is ambiguous in
+# Go 1.16 (because two different modules contain plausible packages and Go 1.16
+# does not privilege roots above other dependencies).
+#
+# However, the overall build list is identical for both versions.
+
+cp go.mod go.mod.orig
+
+! go mod tidy
+
+stderr '^go: example\.com/m imports\n\texample\.net/indirect imports\n\texample\.net/ambiguous/nested/pkg loaded from example\.net/ambiguous/nested@v0\.1\.0,\n\tbut go 1.16 would fail to locate it:\n\tambiguous import: found package example\.net/ambiguous/nested/pkg in multiple modules:\n\texample\.net/ambiguous v0.1.0 \(.*\)\n\texample\.net/ambiguous/nested v0.1.0 \(.*\)\n\n'
+
+stderr '\n\nTo proceed despite packages unresolved in go 1\.16:\n\tgo mod tidy -e\nIf reproducibility with go 1.16 is not needed:\n\tgo mod tidy -compat=1\.17\nFor other options, see:\n\thttps://golang\.org/doc/modules/pruning\n'
+
+cmp go.mod go.mod.orig
+
+
+# If we run 'go mod tidy -e', we should still save enough checksums to run
+# 'go list -m all' reproducibly with go 1.16, even though we can't list
+# the specific package.
+
+go mod tidy -e
+! stderr '\n\tgo mod tidy'
+cmp go.mod go.mod.orig
+
+go list -m all
+cmp stdout all-m.txt
+
+go list -f $MODFMT example.net/ambiguous/nested/pkg
+stdout '^example.net/ambiguous/nested v0\.1\.0$'
+! stderr .
+
+go mod edit -go=1.16
+go list -m all
+cmp stdout all-m.txt
+
+! go list -f $MODFMT example.net/ambiguous/nested/pkg
+stderr '^ambiguous import: found package example\.net/ambiguous/nested/pkg in multiple modules:\n\texample\.net/ambiguous v0\.1\.0 \(.*\)\n\texample\.net/ambiguous/nested v0\.1\.0 \(.*\)\n'
+
+
+# On the other hand, if we use -compat=1.17, 1.16 can't even load
+# the build list (due to missing checksums).
+
+cp go.mod.orig go.mod
+go mod tidy -compat=1.17
+! stderr .
+go list -m all
+cmp stdout all-m.txt
+
+go mod edit -go=1.16
+! go list -m all
+stderr '^go: example\.net/indirect@v0\.1\.0 requires\n\texample\.net/ambiguous@v0\.1\.0: missing go\.sum entry for go\.mod file; to add it:\n\tgo mod download example\.net/ambiguous\n'
+
+
+-- go.mod --
+module example.com/m
+
+go 1.17
+
+replace example.net/indirect v0.1.0 => ./indirect
+
+require example.net/indirect v0.1.0
+
+require example.net/ambiguous/nested v0.1.0 // indirect
+-- all-m.txt --
+example.com/m
+example.net/ambiguous v0.1.0
+example.net/ambiguous/nested v0.1.0
+example.net/indirect v0.1.0 => ./indirect
+-- m.go --
+package m
+
+import _ "example.net/indirect"
+
+-- indirect/go.mod --
+module example.net/indirect
+
+go 1.17
+
+require example.net/ambiguous v0.1.0
+-- indirect/indirect.go --
+package indirect
+
+import _ "example.net/ambiguous/nested/pkg"
diff --git a/src/cmd/go/testdata/script/mod_tidy_compat_deleted.txt b/src/cmd/go/testdata/script/mod_tidy_compat_deleted.txt
new file mode 100644
index 0000000..b148fc1
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_tidy_compat_deleted.txt
@@ -0,0 +1,128 @@
+# https://golang.org/issue/46141: 'go mod tidy' for a Go 1.17 module should by
+# default preserve enough checksums for the module to be used by Go 1.16.
+#
+# We don't have a copy of Go 1.16 handy, but we can simulate it by editing the
+# 'go' version in the go.mod file to 1.16, without actually updating the
+# requirements to match.
+
+[short] skip
+
+env MODFMT='{{with .Module}}{{.Path}} {{.Version}}{{end}}'
+
+
+# For this module, the "deleted" dependency contains an imported package, but
+# Go 1.16 selects a higher version (in which that package has been deleted).
+
+cp go.mod go.mod.orig
+
+! go mod tidy
+
+stderr '^go: example\.com/m imports\n\texample\.net/deleted loaded from example\.net/deleted@v0\.1\.0,\n\tbut go 1\.16 would fail to locate it in example\.net/deleted@v0\.2\.0\n\n'
+
+stderr '\n\nTo upgrade to the versions selected by go 1.16, leaving some packages unresolved:\n\tgo mod tidy -e -go=1\.16 && go mod tidy -e -go=1\.17\nIf reproducibility with go 1.16 is not needed:\n\tgo mod tidy -compat=1\.17\nFor other options, see:\n\thttps://golang\.org/doc/modules/pruning\n'
+
+
+# The suggested 'go mod tidy -e' command should proceed anyway.
+
+go mod tidy -e
+cmp go.mod go.mod.tidy
+
+
+# In 'go 1.16' mode we should error out in the way we claimed.
+
+cd 116-outside
+! go list -deps -f $MODFMT example.com/m
+stderr '^\.\.[/\\]m\.go:4:2: no required module provides package example\.net/deleted; to add it:\n\tgo get example\.net/deleted$'
+cd ..
+
+go mod edit -go=1.16
+! go list -deps -f $MODFMT example.com/m
+stderr '^go: updates to go\.mod needed; to update it:\n\tgo mod tidy$'
+
+! go mod tidy
+stderr '^go: example\.com/m imports\n\texample\.net/deleted: module example\.net/deleted@latest found \(v0\.2\.0, replaced by \./d2\), but does not contain package example\.net/deleted$'
+
+
+-- go.mod --
+module example.com/m
+
+go 1.17
+
+replace (
+ example.net/deleted v0.1.0 => ./d1
+ example.net/deleted v0.2.0 => ./d2
+ example.net/lazy v0.1.0 => ./lazy
+ example.net/pruned v0.1.0 => ./pruned
+)
+
+require (
+ example.net/deleted v0.1.0
+ example.net/deleted v0.1.0 // redundant
+ example.net/lazy v0.1.0
+)
+-- go.mod.tidy --
+module example.com/m
+
+go 1.17
+
+replace (
+ example.net/deleted v0.1.0 => ./d1
+ example.net/deleted v0.2.0 => ./d2
+ example.net/lazy v0.1.0 => ./lazy
+ example.net/pruned v0.1.0 => ./pruned
+)
+
+require (
+ example.net/deleted v0.1.0
+ example.net/lazy v0.1.0
+)
+-- 116-outside/go.mod --
+module outside
+
+go 1.16
+
+replace (
+ example.com/m => ../
+ example.net/deleted v0.1.0 => ../d1
+ example.net/deleted v0.2.0 => ../d2
+ example.net/lazy v0.1.0 => ../lazy
+ example.net/pruned v0.1.0 => ../pruned
+)
+
+require example.com/m v0.1.0
+-- m.go --
+package m
+
+import (
+ _ "example.net/deleted"
+ _ "example.net/lazy"
+)
+
+-- d1/go.mod --
+module example.net/deleted
+
+go 1.17
+-- d1/deleted.go --
+package deleted
+-- d2/go.mod --
+module example.net/deleted
+
+go 1.17
+-- d2/README --
+There is no longer a Go package here.
+
+-- lazy/go.mod --
+module example.net/lazy
+
+go 1.17
+
+require example.net/pruned v0.1.0
+-- lazy/lazy.go --
+package lazy
+
+-- pruned/go.mod --
+module example.net/pruned
+
+go 1.17
+
+require example.net/deleted v0.2.0
diff --git a/src/cmd/go/testdata/script/mod_tidy_compat_implicit.txt b/src/cmd/go/testdata/script/mod_tidy_compat_implicit.txt
new file mode 100644
index 0000000..26e4749
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_tidy_compat_implicit.txt
@@ -0,0 +1,128 @@
+# https://golang.org/issue/46141: 'go mod tidy' for a Go 1.17 module should by
+# default preserve enough checksums for the module to be used by Go 1.16.
+#
+# We don't have a copy of Go 1.16 handy, but we can simulate it by editing the
+# 'go' version in the go.mod file to 1.16, without actually updating the
+# requirements to match.
+
+[short] skip
+
+env MODFMT='{{with .Module}}{{.Path}} {{.Version}}{{end}}'
+
+
+# For this module, Go 1.16 selects the same versions of all explicit dependencies
+# as Go 1.17 does. However, Go 1.16 selects a higher version of an *implicit*
+# dependency, imported by a test of one of the (external) imported packages.
+# As a result, Go 1.16 also needs checksums for the module sources for that higher
+# version.
+#
+# The Go 1.16 module graph looks like:
+#
+# m ---- lazy v0.1.0 ---- incompatible v1.0.0
+# |
+# + ------------- requireincompatible v0.1.0 ---- incompatible v2.0.0+incompatible
+#
+# The Go 1.17 module graph is the same except that the dependencies of
+# requireincompatible are pruned out (because the module that requires
+# it — lazy v0.1.0 — specifies 'go 1.17', and it is not otherwise relevant to
+# the main module).
+
+# 'go mod tidy' should by default diagnose the difference in dependencies as an
+# error, with useful suggestions about how to resolve it.
+
+cp go.mod go.mod.orig
+! go mod tidy
+stderr '^go: example\.com/m imports\n\texample\.net/lazy tested by\n\texample\.net/lazy.test imports\n\texample\.com/retract/incompatible loaded from example\.com/retract/incompatible@v1\.0\.0,\n\tbut go 1\.16 would select v2\.0\.0\+incompatible\n\n'
+stderr '\n\nTo upgrade to the versions selected by go 1\.16:\n\tgo mod tidy -go=1\.16 && go mod tidy -go=1\.17\nIf reproducibility with go 1.16 is not needed:\n\tgo mod tidy -compat=1.17\nFor other options, see:\n\thttps://golang\.org/doc/modules/pruning\n'
+
+cmp go.mod go.mod.orig
+
+# The suggested '-compat' flag to ignore differences should silence the error
+# and leave go.mod unchanged, resulting in checksum errors when Go 1.16 tries
+# to load a module pruned out by Go 1.17.
+
+go mod tidy -compat=1.17
+! stderr .
+cmp go.mod go.mod.orig
+
+go list -deps -test -f $MODFMT ./...
+stdout '^example.net/lazy v0.1.0$'
+
+go mod edit -go=1.16
+! go list -deps -test -f $MODFMT ./...
+
+stderr -count=1 '^go: example\.net/lazy@v0\.1\.0 requires\n\texample\.com/retract/incompatible@v1\.0\.0: missing go\.sum entry for go\.mod file; to add it:\n\tgo mod download example\.com/retract/incompatible$'
+
+
+# If we combine a Go 1.16 go.sum file...
+go mod tidy -go=1.16
+
+# ...with a Go 1.17 go.mod file...
+cp go.mod.orig go.mod
+
+# ...then Go 1.17 no longer works. 😞
+! go list -deps -test -f $MODFMT all
+stderr -count=1 '^go: can''t load test package: lazy[/\\]lazy_test.go:3:8: missing go\.sum entry for module providing package example\.com/retract/incompatible \(imported by example\.net/lazy\); to add:\n\tgo get -t example.net/lazy@v0\.1\.0$'
+
+
+# However, if we take the union of the go.sum files...
+go list -mod=mod -deps -test all
+cmp go.mod go.mod.orig
+
+# ...then Go 1.17 continues to work...
+go list -deps -test -f $MODFMT all
+stdout '^example\.com/retract/incompatible v1\.0\.0$'
+
+# ...and 1.16 also works(‽), but selects a different version for the
+# external-test dependency.
+go mod edit -go=1.16
+go list -deps -test -f $MODFMT all
+stdout '^example\.com/retract/incompatible v2\.0\.0\+incompatible$'
+
+
+-- go.mod --
+// Module m imports packages from the same versions under Go 1.17
+// as under Go 1.16, but under 1.16 its (implicit) external test dependencies
+// are higher.
+module example.com/m
+
+go 1.17
+
+replace (
+ example.net/lazy v0.1.0 => ./lazy
+ example.net/requireincompatible v0.1.0 => ./requireincompatible
+)
+
+require example.net/lazy v0.1.0
+-- implicit.go --
+package implicit
+
+import _ "example.net/lazy"
+-- lazy/go.mod --
+// Module lazy requires example.com/retract/incompatible v1.0.0.
+//
+// When viewed from the outside it also has a transitive dependency
+// on v2.0.0+incompatible, but in lazy mode that transitive dependency
+// is pruned out.
+module example.net/lazy
+
+go 1.17
+
+exclude example.com/retract/incompatible v2.0.0+incompatible
+
+require (
+ example.com/retract/incompatible v1.0.0
+ example.net/requireincompatible v0.1.0
+)
+-- lazy/lazy.go --
+package lazy
+-- lazy/lazy_test.go --
+package lazy_test
+
+import _ "example.com/retract/incompatible"
+-- requireincompatible/go.mod --
+module example.net/requireincompatible
+
+go 1.15
+
+require example.com/retract/incompatible v2.0.0+incompatible
diff --git a/src/cmd/go/testdata/script/mod_tidy_compat_incompatible.txt b/src/cmd/go/testdata/script/mod_tidy_compat_incompatible.txt
new file mode 100644
index 0000000..9e2a9ee
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_tidy_compat_incompatible.txt
@@ -0,0 +1,133 @@
+# https://golang.org/issue/46141: 'go mod tidy' for a Go 1.17 module should by
+# default preserve enough checksums for the module to be used by Go 1.16.
+#
+# We don't have a copy of Go 1.16 handy, but we can simulate it by editing the
+# 'go' version in the go.mod file to 1.16, without actually updating the
+# requirements to match.
+
+[short] skip
+
+env MODFMT='{{with .Module}}{{.Path}} {{.Version}}{{end}}'
+
+
+# For this module, Go 1.17 prunes out a (transitive and otherwise-irrelevant)
+# requirement on a retracted higher version of a dependency.
+# However, when Go 1.16 reads the same requirements from the go.mod file,
+# it does not prune out that requirement, and selects the retracted version.
+#
+# The Go 1.16 module graph looks like:
+#
+# m ---- lazy v0.1.0 ---- requireincompatible v0.1.0 ---- incompatible v2.0.0+incompatible
+# | |
+# + -------+------------- incompatible v1.0.0
+#
+# The Go 1.17 module graph is the same except that the dependencies of
+# requireincompatible are pruned out (because the module that requires
+# it — lazy v0.1.0 — specifies 'go 1.17', and it is not otherwise relevant to
+# the main module).
+
+
+# 'go mod tidy' should by default diagnose the difference in dependencies as an
+# error, with useful suggestions about how to resolve it.
+
+cp go.mod go.mod.orig
+! go mod tidy
+stderr '^go: example\.com/m imports\n\texample\.net/lazy imports\n\texample\.com/retract/incompatible loaded from example\.com/retract/incompatible@v1\.0\.0,\n\tbut go 1\.16 would select v2\.0\.0\+incompatible\n\n'
+stderr '\n\nTo upgrade to the versions selected by go 1\.16:\n\tgo mod tidy -go=1\.16 && go mod tidy -go=1\.17\nIf reproducibility with go 1\.16 is not needed:\n\tgo mod tidy -compat=1.17\nFor other options, see:\n\thttps://golang\.org/doc/modules/pruning\n'
+
+cmp go.mod go.mod.orig
+
+
+# The suggested '-compat' flag to ignore differences should silence the error
+# and leave go.mod unchanged, resulting in checksum errors when Go 1.16 tries
+# to load a module pruned out by Go 1.17.
+
+go mod tidy -compat=1.17
+! stderr .
+cmp go.mod go.mod.orig
+
+go mod edit -go=1.16
+! go list -f $MODFMT -deps ./...
+stderr -count=1 '^go: example\.net/lazy@v0\.1\.0 requires\n\texample\.net/requireincompatible@v0\.1\.0 requires\n\texample\.com/retract/incompatible@v2\.0\.0\+incompatible: missing go.sum entry for go.mod file; to add it:\n\tgo mod download example.com/retract/incompatible$'
+
+
+# There are two ways for the module author to bring the two into alignment.
+# One is to *explicitly* 'exclude' the version that is already *implicitly*
+# pruned out under 1.17.
+
+go mod edit -exclude=example.com/retract/incompatible@v2.0.0+incompatible
+go list -f $MODFMT -deps ./...
+stdout '^example.com/retract/incompatible v1\.0\.0$'
+! stdout 'v2\.0\.0'
+
+
+# The other is to explicitly upgrade the version required under Go 1.17
+# to match the version selected by Go 1.16. The commands suggested by
+# 'go mod tidy' should do exactly that.
+
+cp go.mod.orig go.mod
+
+go mod tidy -go=1.16
+go list -f $MODFMT -deps ./...
+stdout '^example.com/retract/incompatible v2\.0\.0\+incompatible$'
+! stdout 'v1\.0\.0'
+
+go mod tidy -go=1.17
+go list -f $MODFMT -deps ./...
+stdout '^example.com/retract/incompatible v2\.0\.0\+incompatible$'
+! stdout 'v1\.0\.0'
+
+go mod edit -go=1.16
+go list -f $MODFMT -deps ./...
+stdout '^example.com/retract/incompatible v2\.0\.0\+incompatible$'
+! stdout 'v1\.0\.0'
+
+
+-- go.mod --
+// Module m indirectly imports a package from
+// example.com/retract/incompatible. Its selected version of
+// that module is lower under Go 1.17 semantics than under Go 1.16.
+module example.com/m
+
+go 1.17
+
+replace (
+ example.net/lazy v0.1.0 => ./lazy
+ example.net/requireincompatible v0.1.0 => ./requireincompatible
+)
+
+require example.net/lazy v0.1.0
+
+require example.com/retract/incompatible v1.0.0 // indirect
+-- incompatible.go --
+package incompatible
+
+import _ "example.net/lazy"
+
+-- lazy/go.mod --
+// Module lazy requires example.com/retract/incompatible v1.0.0.
+//
+// When viewed from the outside it also has a transitive dependency
+// on v2.0.0+incompatible, but in lazy mode that transitive dependency
+// is pruned out.
+module example.net/lazy
+
+go 1.17
+
+exclude example.com/retract/incompatible v2.0.0+incompatible
+
+require (
+ example.com/retract/incompatible v1.0.0
+ example.net/requireincompatible v0.1.0
+)
+-- lazy/lazy.go --
+package lazy
+
+import _ "example.com/retract/incompatible"
+
+-- requireincompatible/go.mod --
+module example.net/requireincompatible
+
+go 1.15
+
+require example.com/retract/incompatible v2.0.0+incompatible
diff --git a/src/cmd/go/testdata/script/mod_tidy_compat_irrelevant.txt b/src/cmd/go/testdata/script/mod_tidy_compat_irrelevant.txt
new file mode 100644
index 0000000..e4eaea0
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_tidy_compat_irrelevant.txt
@@ -0,0 +1,98 @@
+# https://golang.org/issue/46141: 'go mod tidy' for a Go 1.17 module should by
+# default preserve enough checksums for the module to be used by Go 1.16.
+#
+# We don't have a copy of Go 1.16 handy, but we can simulate it by editing the
+# 'go' version in the go.mod file to 1.16, without actually updating the
+# requirements to match.
+
+[short] skip
+
+env MODFMT='{{with .Module}}{{.Path}} {{.Version}}{{end}}'
+
+
+# This module selects the same versions in Go 1.16 and 1.17 for all modules
+# that provide packages (or test dependencies of packages) imported by the
+# main module. However, in Go 1.16 it selects a higher version of a
+# transitive module dependency that is not otherwise relevant to the main module.
+# As a result, Go 1.16 needs an additional checksum for the go.mod file of
+# that irrelevant dependency.
+#
+# The Go 1.16 module graph looks like:
+#
+# m ---- lazy v0.1.0 ---- incompatible v1.0.0
+# |
+# + ------------- requireincompatible v0.1.0 ---- incompatible v2.0.0+incompatible
+
+cp go.mod go.mod.orig
+go mod tidy
+cmp go.mod go.mod.orig
+
+go list -deps -test -f $MODFMT all
+cp stdout out-117.txt
+
+go mod edit -go=1.16
+go list -deps -test -f $MODFMT all
+cmp stdout out-117.txt
+
+
+# If we explicitly drop compatibility with 1.16, we retain fewer checksums,
+# which gives a cleaner go.sum file but causes 1.16 to fail in readonly mode.
+
+cp go.mod.orig go.mod
+go mod tidy -compat=1.17
+cmp go.mod go.mod.orig
+
+go list -deps -test -f $MODFMT all
+cmp stdout out-117.txt
+
+go mod edit -go=1.16
+! go list -deps -test -f $MODFMT all
+stderr -count=1 '^go: example.net/lazy@v0.1.0 requires\n\texample.com/retract/incompatible@v1.0.0: missing go.sum entry for go.mod file; to add it:\n\tgo mod download example.com/retract/incompatible$'
+
+
+-- go.mod --
+// Module m imports packages from the same versions under Go 1.17
+// as under Go 1.16, but under 1.16 its (implicit) external test dependencies
+// are higher.
+module example.com/m
+
+go 1.17
+
+replace (
+ example.net/lazy v0.1.0 => ./lazy
+ example.net/requireincompatible v0.1.0 => ./requireincompatible
+)
+
+require example.net/lazy v0.1.0
+-- m.go --
+package m
+
+import _ "example.net/lazy"
+-- lazy/go.mod --
+// Module lazy requires example.com/retract/incompatible v1.0.0.
+//
+// When viewed from the outside it also has a transitive dependency
+// on v2.0.0+incompatible, but in lazy mode that transitive dependency
+// is pruned out.
+module example.net/lazy
+
+go 1.17
+
+exclude example.com/retract/incompatible v2.0.0+incompatible
+
+require (
+ example.com/retract/incompatible v1.0.0
+ example.net/requireincompatible v0.1.0
+)
+-- lazy/lazy.go --
+package lazy
+-- lazy/unimported/unimported.go --
+package unimported
+
+import _ "example.com/retract/incompatible"
+-- requireincompatible/go.mod --
+module example.net/requireincompatible
+
+go 1.15
+
+require example.com/retract/incompatible v2.0.0+incompatible
diff --git a/src/cmd/go/testdata/script/mod_tidy_convergence.txt b/src/cmd/go/testdata/script/mod_tidy_convergence.txt
new file mode 100644
index 0000000..45f74b4
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_tidy_convergence.txt
@@ -0,0 +1,202 @@
+# This test demonstrates a simple case in which 'go mod tidy' may resolve a
+# missing package, only to remove that package when resolving its dependencies.
+#
+# If we naively iterate 'go mod tidy' until the dependency graph converges, this
+# scenario may fail to converge.
+
+# The import graph used in this test looks like:
+#
+# m --- x
+# |
+# x_test --- y
+#
+# The module dependency graph of m is initially empty.
+# Modules x and y look like:
+#
+# x.1 (provides package x that imports y, but does not depend on module y)
+#
+# x.2-pre (no dependencies, but does not provide package x)
+#
+# y.1 (no dependencies, but provides package y)
+#
+# y.2 --- x.2-pre (provides package y)
+#
+#
+# When we resolve the missing import of y in x_test, we add y@latest — which is
+# y.2, not y.1 — as a new dependency. That upgrades to x to x.2-pre, which
+# removes package x (and also the need for module y). We can then safely remove
+# the dependency on module y, because nothing imports package y any more!
+#
+# We might be tempted to remove the dependency on module x for the same reason:
+# it no longer provides any imported package. However, that would cause 'go mod
+# tidy -e' to become unstable: with x.2-pre out of the way, we could once again
+# resolve the missing import of package x by re-adding x.1.
+
+cp go.mod go.mod.orig
+
+# 'go mod tidy' without -e should fail without modifying go.mod,
+# because it cannot resolve x and y simultaneously.
+! go mod tidy
+
+cmp go.mod go.mod.orig
+
+stderr '^go: found example\.net/y in example\.net/y v0.2.0$'
+stderr '^go: finding module for package example\.net/x$'
+
+ # TODO: This error message should be clearer — it doesn't indicate why v0.2.0-pre is required.
+stderr '^go: example\.net/m imports\n\texample\.net/x: package example\.net/x provided by example\.net/x at latest version v0\.1\.0 but not at required version v0\.2\.0-pre$'
+
+
+# 'go mod tidy -e' should follow upgrades to try to resolve the modules that it
+# can, and then stop. When we resolve example.net/y, we upgrade to example.net/x
+# to v0.2.0-pre. At that version, package x no longer exists and no longer
+# imports package y, so the import of x should be left unsatisfied and the
+# existing dependency on example.net/x removed.
+#
+# TODO(bcmills): It would be ever better if we could keep the original
+# dependency on example.net/x v0.1.0, but I don't see a way to do that without
+# making the algorithm way too complicated. (We would have to detect that the
+# new dependency on example.net/y interferes with the package that caused us to
+# to add that dependency in the first place, and back out that part of the change
+# without also backing out any other needed changes.)
+
+go mod tidy -e
+cmp go.mod go.mod.tidye
+stderr '^go: found example\.net/y in example\.net/y v0.2.0$'
+
+ # TODO: This error message should be clearer — it doesn't indicate why v0.2.0-pre is required.
+stderr '^go: example\.net/m imports\n\texample\.net/x: package example\.net/x provided by example\.net/x at latest version v0\.1\.0 but not at required version v0\.2\.0-pre$'
+
+
+# Since we attempt to resolve the dependencies of package x whenever we add x itself,
+# this end state is stable.
+
+go mod tidy -e
+cmp go.mod go.mod.tidye
+
+
+# An explicit 'go get' with the correct versions should allow 'go mod tidy' to
+# succeed and remain stable. y.1 does not upgrade x, and can therefore be used
+# with it.
+
+go get example.net/x@v0.1.0 example.net/y@v0.1.0
+go mod tidy
+cmp go.mod go.mod.postget
+
+
+# The 'tidy' logic for a lazy main module is somewhat different from that for an
+# eager main module, but the overall behavior is the same.
+
+cp go.mod.orig go.mod
+go mod edit -go=1.17 go.mod
+go mod edit -go=1.17 go.mod.tidye
+
+go mod tidy -e
+cmp go.mod go.mod.tidye
+stderr '^go: found example\.net/y in example\.net/y v0.2.0$'
+stderr '^go: example\.net/m imports\n\texample\.net/x: package example\.net/x provided by example\.net/x at latest version v0\.1\.0 but not at required version v0\.2\.0-pre$'
+
+go get example.net/x@v0.1.0 example.net/y@v0.1.0
+go mod tidy
+cmp go.mod go.mod.postget-117
+
+
+-- go.mod --
+module example.net/m
+
+go 1.16
+
+replace (
+ example.net/x v0.1.0 => ./x1
+ example.net/x v0.2.0-pre => ./x2-pre
+ example.net/y v0.1.0 => ./y1
+ example.net/y v0.2.0 => ./y2
+)
+
+require (
+ example.net/x v0.1.0
+)
+-- go.mod.tidye --
+module example.net/m
+
+go 1.16
+
+replace (
+ example.net/x v0.1.0 => ./x1
+ example.net/x v0.2.0-pre => ./x2-pre
+ example.net/y v0.1.0 => ./y1
+ example.net/y v0.2.0 => ./y2
+)
+-- go.mod.postget --
+module example.net/m
+
+go 1.16
+
+replace (
+ example.net/x v0.1.0 => ./x1
+ example.net/x v0.2.0-pre => ./x2-pre
+ example.net/y v0.1.0 => ./y1
+ example.net/y v0.2.0 => ./y2
+)
+
+require (
+ example.net/x v0.1.0
+ example.net/y v0.1.0 // indirect
+)
+-- go.mod.postget-117 --
+module example.net/m
+
+go 1.17
+
+replace (
+ example.net/x v0.1.0 => ./x1
+ example.net/x v0.2.0-pre => ./x2-pre
+ example.net/y v0.1.0 => ./y1
+ example.net/y v0.2.0 => ./y2
+)
+
+require example.net/x v0.1.0
+
+require example.net/y v0.1.0 // indirect
+-- m.go --
+package m
+
+import _ "example.net/x"
+
+-- x1/go.mod --
+module example.net/x
+
+go 1.16
+-- x1/x.go --
+package x
+-- x1/x_test.go --
+package x
+
+import _ "example.net/y"
+
+-- x2-pre/go.mod --
+module example.net/x
+
+go 1.16
+-- x2-pre/README.txt --
+There is no package x here. Use example.com/x/subpkg instead.
+-- x2-pre/subpkg/subpkg.go --
+package subpkg // import "example.net/x/subpkg"
+
+-- y1/go.mod --
+module example.net/y
+
+go 1.16
+-- y1/y.go --
+package y
+
+-- y2/go.mod --
+module example.net/y
+
+go 1.16
+
+require example.net/x v0.2.0-pre
+-- y2/y.go --
+package y
+
+import _ "example.net/x/subpkg"
diff --git a/src/cmd/go/testdata/script/mod_tidy_convergence_loop.txt b/src/cmd/go/testdata/script/mod_tidy_convergence_loop.txt
new file mode 100644
index 0000000..ec58159
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_tidy_convergence_loop.txt
@@ -0,0 +1,329 @@
+# This test demonstrates a simple case in which 'go mod tidy' may resolve a
+# missing package, only to remove that package when resolving its dependencies.
+#
+# If we naively iterate 'go mod tidy' until the dependency graph converges, this
+# scenario may fail to converge.
+
+# The import graph used in this test looks like:
+#
+# m --- w
+# |
+# + --- x
+# |
+# + --- y
+# |
+# + --- z
+#
+# The module dependency graph of m initially contains w.1 (and, by extension,
+# y.2-pre and z.2-pre). This is an arbitrary point in the cycle of possible
+# configurations.
+#
+# w.1 requires y.2-pre and z.2-pre
+# x.1 requires z.2-pre and w.2-pre
+# y.1 requires w.2-pre and x.2-pre
+# z.1 requires x.2-pre and y.2-pre
+#
+# At each point, exactly one missing package can be resolved by adding a
+# dependency on the .1 release of the module that provides that package.
+# However, adding that dependency causes the module providing another package to
+# roll over from its .1 release to its .2-pre release, which removes the
+# package. Once the package is removed, 'go mod tidy -e' no longer sees the
+# module as relevant to the main module, and will happily remove the existing
+# dependency on it.
+#
+# The cycle is of length 4 so that at every step only one package can be
+# resolved. This is important because it prevents the iteration from ever
+# reaching a state in which every package is simultaneously over-upgraded — such
+# a state is stable and does not exhibit failure to converge.
+
+cp go.mod go.mod.orig
+
+# 'go mod tidy' without -e should fail without modifying go.mod,
+# because it cannot resolve x, y, and z simultaneously.
+! go mod tidy
+
+cmp go.mod go.mod.orig
+
+stderr '^go: finding module for package example\.net/w$'
+stderr '^go: finding module for package example\.net/x$'
+stderr -count=2 '^go: finding module for package example\.net/y$'
+stderr -count=2 '^go: finding module for package example\.net/z$'
+stderr '^go: found example\.net/x in example\.net/x v0.1.0$'
+
+ # TODO: These error messages should be clearer — it doesn't indicate why v0.2.0-pre is required.
+stderr '^go: example\.net/m imports\n\texample\.net/w: package example\.net/w provided by example\.net/w at latest version v0\.1\.0 but not at required version v0\.2\.0-pre$'
+stderr '^go: example\.net/m imports\n\texample\.net/y: package example\.net/y provided by example\.net/y at latest version v0\.1\.0 but not at required version v0\.2\.0-pre$'
+stderr '^go: example\.net/m imports\n\texample\.net/z: package example\.net/z provided by example\.net/z at latest version v0\.1\.0 but not at required version v0\.2\.0-pre$'
+
+
+# 'go mod tidy -e' should preserve all of the upgrades to modules that could
+# provide the missing packages but don't. That would at least explain why they
+# are missing, and why no individual module can be upgraded in order to satisfy
+# a missing import.
+#
+# TODO(bcmills): Today, it doesn't preserve those upgrades, and instead advances
+# the state by one through the cycle of semi-tidy states.
+
+go mod tidy -e
+
+cmp go.mod go.mod.tidye1
+
+stderr '^go: finding module for package example\.net/w$'
+stderr '^go: finding module for package example\.net/x$'
+stderr -count=2 '^go: finding module for package example\.net/y$'
+stderr -count=2 '^go: finding module for package example\.net/z$'
+stderr '^go: found example\.net/x in example\.net/x v0.1.0$'
+
+stderr '^go: example\.net/m imports\n\texample\.net/w: package example\.net/w provided by example\.net/w at latest version v0\.1\.0 but not at required version v0\.2\.0-pre$'
+stderr '^go: example\.net/m imports\n\texample\.net/y: package example\.net/y provided by example\.net/y at latest version v0\.1\.0 but not at required version v0\.2\.0-pre$'
+stderr '^go: example\.net/m imports\n\texample\.net/z: package example\.net/z provided by example\.net/z at latest version v0\.1\.0 but not at required version v0\.2\.0-pre$'
+
+
+go mod tidy -e
+cmp go.mod go.mod.tidye2
+
+go mod tidy -e
+cmp go.mod go.mod.tidye3
+
+go mod tidy -e
+cmp go.mod go.mod.orig
+
+
+# If we upgrade away all of the packages simultaneously, the resulting tidy
+# state converges at "no dependencies", because simultaneously adding all of the
+# packages simultaneously over-upgrades all of the dependencies, and 'go mod
+# tidy' treats "no package can be added" as a terminal state.
+
+go get example.net/w@v0.2.0-pre example.net/x@v0.2.0-pre example.net/y@v0.2.0-pre example.net/z@v0.2.0-pre
+go mod tidy -e
+cmp go.mod go.mod.postget
+go mod tidy -e
+cmp go.mod go.mod.postget
+
+
+# The 'tidy' logic for a lazy main module requires more iterations to converge,
+# because it is willing to drop dependencies on non-root modules that do not
+# otherwise provide imported packages.
+#
+# On the first iteration, it adds x.1 as a root, which upgrades z and w,
+# dropping w.1's requirement on y. w.1 was initially a root, so the upgraded
+# w.2-pre is retained as a root.
+#
+# On the second iteration, it adds y.1 as a root, which upgrades w and x,
+# dropping x.1's requirement on z. x.1 was added as a root in the previous step,
+# so the upgraded x.2-pre is retained as a root.
+#
+# On the third iteration, it adds z.1 as a root, which upgrades x and y.
+# x and y were already roots (from the previous steps), so their upgraded versions
+# are retained (not dropped) and the iteration stops.
+#
+# At that point, we have z.1 as a root providing package z,
+# and w, x, and y have all been upgraded to no longer provide any packages.
+# So only z is retained as a new root.
+#
+# (From the above, we can see that in a lazy module we still cycle through the
+# same possible root states, but in a different order from the eager case.)
+#
+# TODO(bcmills): if we retained the upgrades on w, x, and y (since they are
+# lexical prefixes for unresolved packages w, x, and y, respectively), then 'go
+# mod tidy -e' itself would become stable and no longer cycle through states.
+
+cp go.mod.orig go.mod
+go mod edit -go=1.17 go.mod
+cp go.mod go.mod.117
+go mod edit -go=1.17 go.mod.tidye1
+go mod edit -go=1.17 go.mod.tidye2
+go mod edit -go=1.17 go.mod.tidye3
+go mod edit -go=1.17 go.mod.postget
+
+go list -m all
+
+go mod tidy -e
+cmp go.mod go.mod.tidye3
+
+go mod tidy -e
+cmp go.mod go.mod.tidye2
+
+go mod tidy -e
+cmp go.mod go.mod.tidye1
+
+go mod tidy -e
+cmp go.mod go.mod.117
+
+
+# As in the eager case, for the lazy module the fully-upgraded dependency graph
+# becomes empty, and the empty graph is stable.
+
+go get example.net/w@v0.2.0-pre example.net/x@v0.2.0-pre example.net/y@v0.2.0-pre example.net/z@v0.2.0-pre
+go mod tidy -e
+cmp go.mod go.mod.postget
+go mod tidy -e
+cmp go.mod go.mod.postget
+
+
+-- m.go --
+package m
+
+import (
+ _ "example.net/w"
+ _ "example.net/x"
+ _ "example.net/y"
+ _ "example.net/z"
+)
+
+-- go.mod --
+module example.net/m
+
+go 1.16
+
+replace (
+ example.net/w v0.1.0 => ./w1
+ example.net/w v0.2.0-pre => ./w2-pre
+ example.net/x v0.1.0 => ./x1
+ example.net/x v0.2.0-pre => ./x2-pre
+ example.net/y v0.1.0 => ./y1
+ example.net/y v0.2.0-pre => ./y2-pre
+ example.net/z v0.1.0 => ./z1
+ example.net/z v0.2.0-pre => ./z2-pre
+)
+
+require example.net/w v0.1.0
+-- go.mod.tidye1 --
+module example.net/m
+
+go 1.16
+
+replace (
+ example.net/w v0.1.0 => ./w1
+ example.net/w v0.2.0-pre => ./w2-pre
+ example.net/x v0.1.0 => ./x1
+ example.net/x v0.2.0-pre => ./x2-pre
+ example.net/y v0.1.0 => ./y1
+ example.net/y v0.2.0-pre => ./y2-pre
+ example.net/z v0.1.0 => ./z1
+ example.net/z v0.2.0-pre => ./z2-pre
+)
+
+require example.net/x v0.1.0
+-- go.mod.tidye2 --
+module example.net/m
+
+go 1.16
+
+replace (
+ example.net/w v0.1.0 => ./w1
+ example.net/w v0.2.0-pre => ./w2-pre
+ example.net/x v0.1.0 => ./x1
+ example.net/x v0.2.0-pre => ./x2-pre
+ example.net/y v0.1.0 => ./y1
+ example.net/y v0.2.0-pre => ./y2-pre
+ example.net/z v0.1.0 => ./z1
+ example.net/z v0.2.0-pre => ./z2-pre
+)
+
+require example.net/y v0.1.0
+-- go.mod.tidye3 --
+module example.net/m
+
+go 1.16
+
+replace (
+ example.net/w v0.1.0 => ./w1
+ example.net/w v0.2.0-pre => ./w2-pre
+ example.net/x v0.1.0 => ./x1
+ example.net/x v0.2.0-pre => ./x2-pre
+ example.net/y v0.1.0 => ./y1
+ example.net/y v0.2.0-pre => ./y2-pre
+ example.net/z v0.1.0 => ./z1
+ example.net/z v0.2.0-pre => ./z2-pre
+)
+
+require example.net/z v0.1.0
+-- go.mod.postget --
+module example.net/m
+
+go 1.16
+
+replace (
+ example.net/w v0.1.0 => ./w1
+ example.net/w v0.2.0-pre => ./w2-pre
+ example.net/x v0.1.0 => ./x1
+ example.net/x v0.2.0-pre => ./x2-pre
+ example.net/y v0.1.0 => ./y1
+ example.net/y v0.2.0-pre => ./y2-pre
+ example.net/z v0.1.0 => ./z1
+ example.net/z v0.2.0-pre => ./z2-pre
+)
+-- w1/go.mod --
+module example.net/w
+
+go 1.16
+
+require (
+ example.net/y v0.2.0-pre
+ example.net/z v0.2.0-pre
+)
+-- w1/w.go --
+package w
+-- w2-pre/go.mod --
+module example.net/w
+
+go 1.16
+-- w2-pre/README.txt --
+Package w has been removed.
+
+-- x1/go.mod --
+module example.net/x
+
+go 1.16
+
+require (
+ example.net/z v0.2.0-pre
+ example.net/w v0.2.0-pre
+)
+-- x1/x.go --
+package x
+-- x2-pre/go.mod --
+module example.net/x
+
+go 1.16
+-- x2-pre/README.txt --
+Package x has been removed.
+
+-- y1/go.mod --
+module example.net/y
+
+go 1.16
+
+require (
+ example.net/w v0.2.0-pre
+ example.net/x v0.2.0-pre
+)
+-- y1/y.go --
+package y
+
+-- y2-pre/go.mod --
+module example.net/y
+
+go 1.16
+-- y2-pre/README.txt --
+Package y has been removed.
+
+-- z1/go.mod --
+module example.net/z
+
+go 1.16
+
+require (
+ example.net/x v0.2.0-pre
+ example.net/y v0.2.0-pre
+)
+-- z1/z.go --
+package z
+
+-- z2-pre/go.mod --
+module example.net/z
+
+go 1.16
+-- z2-pre/README.txt --
+Package z has been removed.
diff --git a/src/cmd/go/testdata/script/mod_tidy_cycle.txt b/src/cmd/go/testdata/script/mod_tidy_cycle.txt
new file mode 100644
index 0000000..e46f37d
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_tidy_cycle.txt
@@ -0,0 +1,75 @@
+# Regression test for https://golang.org/issue/34086:
+# 'go mod tidy' produced different go.mod file from other
+# subcommands when certain kinds of cycles were present
+# in the build graph.
+
+env GO111MODULE=on
+
+cp go.mod go.mod.orig
+go mod tidy
+cmp go.mod go.mod.orig
+
+# If the go.mod file is already tidy, 'go mod graph' should not modify it.
+go mod graph
+cmp go.mod go.mod.orig
+
+-- go.mod --
+module root
+
+go 1.13
+
+replace (
+ a v0.1.0 => ./a1
+ b v0.1.0 => ./b1
+ b v0.2.0 => ./b2
+ c v0.1.0 => ./c1
+ c v0.2.0 => ./c2
+)
+
+require (
+ a v0.1.0
+ b v0.2.0 // indirect
+)
+-- main.go --
+package main
+
+import _ "a"
+
+func main() {}
+
+-- a1/go.mod --
+module a
+
+go 1.13
+
+require b v0.1.0
+-- a1/a.go --
+package a
+
+import _ "c"
+-- b1/go.mod --
+module b
+
+go 1.13
+
+require c v0.1.0
+-- b2/go.mod --
+module b
+
+go 1.13
+
+require c v0.2.0
+-- c1/go.mod --
+module c
+
+go 1.13
+-- c2/c.go --
+package c
+-- c2/go.mod --
+module c
+
+go 1.13
+
+require b v0.2.0
+-- c2/c.go --
+package c
diff --git a/src/cmd/go/testdata/script/mod_tidy_downgrade_ambiguous.txt b/src/cmd/go/testdata/script/mod_tidy_downgrade_ambiguous.txt
new file mode 100644
index 0000000..8b508c7
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_tidy_downgrade_ambiguous.txt
@@ -0,0 +1,58 @@
+# Verifies golang.org/issue/47738.
+
+# In this test, the user has rewritten their imports to use rsc.io/quote/v3,
+# but their go.mod still requires rsc.io/quote@v1.5.2, and they indirectly
+# require rsc.io/quote@v1.5.1 but don't import anything from it.
+go list -m -f '{{.Path}}@{{.Version}}{{if .Indirect}} indirect{{end}}' all
+stdout '^rsc.io/quote@v1.5.2$'
+! stdout 'rsc.io/quote/v3'
+go list -e all
+! stdout '^rsc.io/quote$'
+
+# 'go mod tidy' should preserve the requirement on rsc.io/quote but mark it
+# indirect. This prevents a downgrade to v1.5.1, which could introduce
+# an ambiguity.
+go mod tidy
+go list -m -f '{{.Path}}@{{.Version}}{{if .Indirect}} indirect{{end}}' all
+stdout '^rsc.io/quote@v1.5.2 indirect$'
+stdout '^rsc.io/quote/v3@v3.0.0$'
+
+-- go.mod --
+module use
+
+go 1.16
+
+require (
+ old-indirect v0.0.0
+ rsc.io/quote v1.5.2
+)
+
+replace old-indirect v0.0.0 => ./old-indirect
+-- go.sum --
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw=
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+rsc.io/quote v1.5.1/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
+rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0=
+rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
+rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+-- use.go --
+package use
+
+import (
+ _ "old-indirect/empty"
+
+ _ "rsc.io/quote/v3"
+)
+-- old-indirect/empty/empty.go --
+package empty
+-- old-indirect/go.mod --
+module old-indirect
+
+go 1.16
+
+require rsc.io/quote v1.5.1
+-- old-indirect/go.sum --
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
diff --git a/src/cmd/go/testdata/script/mod_tidy_duplicates.txt b/src/cmd/go/testdata/script/mod_tidy_duplicates.txt
new file mode 100644
index 0000000..d454c8d
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_tidy_duplicates.txt
@@ -0,0 +1,38 @@
+env GO111MODULE=on
+
+# Regression test for golang.org/issue/28456:
+# 'go mod tidy' should not leave duplicate lines when re-writing the file.
+
+go mod tidy
+cmp go.sum golden.sum
+
+-- go.mod --
+module use
+
+go 1.16
+
+require rsc.io/quote v1.5.2
+
+-- go.sum --
+rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0=
+rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0=
+rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
+rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
+rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+rsc.io/testonly v1.0.0 h1:K/VWHdO+Jv7woUXG0GzVNx1czBXUt3Ib1deaMn+xk64=
+rsc.io/testonly v1.0.0/go.mod h1:OqmGbIFOcF+XrFReLOGZ6BhMM7uMBiQwZsyNmh74SzY=
+-- golden.sum --
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw=
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0=
+rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
+rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+rsc.io/testonly v1.0.0 h1:K/VWHdO+Jv7woUXG0GzVNx1czBXUt3Ib1deaMn+xk64=
+rsc.io/testonly v1.0.0/go.mod h1:OqmGbIFOcF+XrFReLOGZ6BhMM7uMBiQwZsyNmh74SzY=
+-- main.go --
+package use
+
+import _ "rsc.io/quote"
diff --git a/src/cmd/go/testdata/script/mod_tidy_error.txt b/src/cmd/go/testdata/script/mod_tidy_error.txt
new file mode 100644
index 0000000..fc6cd78
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_tidy_error.txt
@@ -0,0 +1,39 @@
+env GO111MODULE=on
+
+# Regression test for golang.org/issue/27063:
+# 'go mod tidy' and 'go mod vendor' should not hide loading errors.
+
+! go mod tidy
+! stderr 'package nonexist is not in std'
+stderr '^go: issue27063 imports\n\tnonexist.example.com: cannot find module providing package nonexist.example.com'
+stderr '^go: issue27063 imports\n\tissue27063/other imports\n\tother.example.com/nonexist: cannot find module providing package other.example.com/nonexist'
+
+! go mod vendor
+! stderr 'package nonexist is not in std'
+stderr '^go: issue27063 imports\n\tnonexist.example.com: no required module provides package nonexist.example.com; to add it:\n\tgo get nonexist.example.com$'
+stderr '^go: issue27063 imports\n\tissue27063/other imports\n\tother.example.com/nonexist: no required module provides package other.example.com/nonexist; to add it:\n\tgo get other.example.com/nonexist$'
+
+-- go.mod --
+module issue27063
+
+go 1.13
+
+require issue27063/other v0.0.0
+replace issue27063/other => ./other
+-- x.go --
+package main
+
+import (
+ "nonexist"
+
+ "nonexist.example.com"
+ "issue27063/other"
+)
+
+func main() {}
+-- other/go.mod --
+module issue27063/other
+-- other/other.go --
+package other
+
+import "other.example.com/nonexist"
diff --git a/src/cmd/go/testdata/script/mod_tidy_indirect.txt b/src/cmd/go/testdata/script/mod_tidy_indirect.txt
new file mode 100644
index 0000000..1f092b2
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_tidy_indirect.txt
@@ -0,0 +1,67 @@
+cp go.mod go.mod.orig
+go mod tidy
+cmp go.mod go.mod.orig
+
+-- go.mod --
+module example.com/tidy
+
+go 1.16
+
+require (
+ example.net/incomplete v0.1.0
+ example.net/indirect v0.2.0 // indirect
+ example.net/toolow v0.1.0
+)
+
+replace (
+ example.net/incomplete v0.1.0 => ./incomplete
+ example.net/indirect v0.1.0 => ./indirect.1
+ example.net/indirect v0.2.0 => ./indirect.2
+ example.net/toolow v0.1.0 => ./toolow
+)
+-- tidy.go --
+package tidy
+
+import (
+ _ "example.net/incomplete"
+ _ "example.net/toolow"
+)
+
+-- incomplete/go.mod --
+module example.net/incomplete
+
+go 1.16
+
+// This module omits a needed requirement on example.net/indirect.
+-- incomplete/incomplete.go --
+package incomplete
+
+import _ "example.net/indirect/newpkg"
+
+-- toolow/go.mod --
+module example.net/toolow
+
+go 1.16
+
+require example.net/indirect v0.1.0
+-- toolow/toolow.go --
+package toolow
+
+import _ "example.net/indirect/oldpkg"
+
+-- indirect.1/go.mod --
+module example.net/indirect
+
+go 1.16
+-- indirect.1/oldpkg/oldpkg.go --
+package oldpkg
+
+
+-- indirect.2/go.mod --
+module example.net/indirect
+
+go 1.16
+-- indirect.2/oldpkg/oldpkg.go --
+package oldpkg
+-- indirect.2/newpkg/newpkg.go --
+package newpkg
diff --git a/src/cmd/go/testdata/script/mod_tidy_issue60313.txt b/src/cmd/go/testdata/script/mod_tidy_issue60313.txt
new file mode 100644
index 0000000..6963994
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_tidy_issue60313.txt
@@ -0,0 +1,69 @@
+# Regression test for https://go.dev/issue/60313: 'go mod tidy' did not preserve
+# dependencies needed to prevent 'ambiguous import' errors in external test
+# dependencies.
+
+cp go.mod go.mod.orig
+go mod tidy
+cmp go.mod go.mod.orig
+
+-- go.mod --
+module example
+
+go 1.21
+
+require (
+ example.net/a v0.1.0
+ example.net/b v0.1.0
+)
+
+require example.net/outer/inner v0.1.0 // indirect
+
+replace (
+ example.net/a v0.1.0 => ./a
+ example.net/b v0.1.0 => ./b
+ example.net/outer v0.1.0 => ./outer
+ example.net/outer/inner v0.1.0 => ./inner
+)
+-- example.go --
+package example
+
+import (
+ _ "example.net/a"
+ _ "example.net/b"
+)
+-- a/go.mod --
+module example.net/a
+
+go 1.21
+
+require example.net/outer/inner v0.1.0
+-- a/a.go --
+package a
+-- a/a_test.go --
+package a_test
+
+import _ "example.net/outer/inner"
+-- b/go.mod --
+module example.net/b
+
+go 1.21
+
+require example.net/outer v0.1.0
+-- b/b.go --
+package b
+-- b/b_test.go --
+package b_test
+
+import _ "example.net/outer/inner"
+-- inner/go.mod --
+module example.net/outer/inner
+
+go 1.21
+-- inner/inner.go --
+package inner
+-- outer/go.mod --
+module example.net/outer
+
+go 1.21
+-- outer/inner/inner.go --
+package inner
diff --git a/src/cmd/go/testdata/script/mod_tidy_lazy_self.txt b/src/cmd/go/testdata/script/mod_tidy_lazy_self.txt
new file mode 100644
index 0000000..9abbabd
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_tidy_lazy_self.txt
@@ -0,0 +1,66 @@
+# Regression test for https://golang.org/issue/46078:
+# 'go mod tidy' should not panic if the main module initially
+# requires an older version of itself.
+
+# A module may require an older version of itself without error. This is
+# inconsistent (the required version is never selected), but we still get
+# a reproducible build list.
+go list -m all
+stdout '^golang.org/issue/46078$'
+
+# 'go mod tidy' should fix this (and not crash).
+go mod tidy
+
+
+# We prune out redundant roots very early on in module loading, and at that
+# point the indirect requirement on example.net/x v0.1.0 appears to be
+# irrelevant. It should be pruned out; when the import of "example.net/x" is
+# later resolved, it should resolve at the latest version (v0.2.0), not the
+# version implied by the (former) misleading requirement on the older version of
+# the main module.
+
+cmp go.mod go.mod.tidy
+
+
+-- go.mod --
+module golang.org/issue/46078
+
+go 1.17
+
+replace (
+ example.net/x v0.1.0 => ./x
+ example.net/x v0.2.0 => ./x
+ golang.org/issue/46078 v0.1.0 => ./old
+)
+
+require golang.org/issue/46078 v0.1.0
+-- go.mod.tidy --
+module golang.org/issue/46078
+
+go 1.17
+
+replace (
+ example.net/x v0.1.0 => ./x
+ example.net/x v0.2.0 => ./x
+ golang.org/issue/46078 v0.1.0 => ./old
+)
+
+require example.net/x v0.2.0
+-- issue46078/issue.go --
+package issue46078
+
+import _ "example.net/x"
+
+-- old/go.mod --
+module golang.org/issue/46078
+
+go 1.17
+
+require example.net/x v0.1.0
+
+-- x/go.mod --
+module example.net/x
+
+go 1.17
+-- x/x.go --
+package x
diff --git a/src/cmd/go/testdata/script/mod_tidy_newroot.txt b/src/cmd/go/testdata/script/mod_tidy_newroot.txt
new file mode 100644
index 0000000..3abd5ef
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_tidy_newroot.txt
@@ -0,0 +1,82 @@
+# https://golang.org/issue/45952: 'go mod tidy' in an eager module failed due
+# to an erroneous check on root completeness.
+#
+# Per the issue report:
+# > It may have to do with:
+# >
+# > package A imports package B in go.mod, which imports package C in its own go.mod
+# > package A drops direct dependency on package B …
+#
+# We infer from that that package C is still needed by some other indirect
+# dependency, and must be at a higher version than what is required by that
+# dependency (or else no new root would be needed). An additional package D
+# in its own module satisfies that condition, reproducing the bug.
+
+go mod tidy
+cmp go.mod go.mod.tidy
+
+-- go.mod --
+module example.net/a
+
+go 1.16
+
+require (
+ example.net/b v0.1.0
+ example.net/d v0.1.0
+)
+
+replace (
+ example.net/b v0.1.0 => ./b
+ example.net/c v0.1.0 => ./c
+ example.net/c v0.2.0 => ./c
+ example.net/d v0.1.0 => ./d
+)
+-- go.mod.tidy --
+module example.net/a
+
+go 1.16
+
+require (
+ example.net/c v0.2.0 // indirect
+ example.net/d v0.1.0
+)
+
+replace (
+ example.net/b v0.1.0 => ./b
+ example.net/c v0.1.0 => ./c
+ example.net/c v0.2.0 => ./c
+ example.net/d v0.1.0 => ./d
+)
+-- a.go --
+package a
+
+import _ "example.net/d"
+
+-- b/go.mod --
+module example.net/b
+
+go 1.16
+
+require example.net/c v0.2.0
+-- b/b.go --
+package b
+
+import _ "example.net/c"
+
+-- c/go.mod --
+module example.net/c
+
+go 1.16
+-- c/c.go --
+package c
+
+-- d/go.mod --
+module example.net/d
+
+go 1.16
+
+require example.net/c v0.1.0
+-- d/d.go --
+package d
+
+import _ "example.net/c"
diff --git a/src/cmd/go/testdata/script/mod_tidy_old.txt b/src/cmd/go/testdata/script/mod_tidy_old.txt
new file mode 100644
index 0000000..7428f0c
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_tidy_old.txt
@@ -0,0 +1,46 @@
+# 'go mod tidy' should remove content sums for module versions that aren't
+# in the build list. It should preserve go.mod sums for module versions that
+# are in the module graph though.
+# Verifies golang.org/issue/33008.
+go mod tidy
+! grep '^rsc.io/quote v1.5.0 h1:' go.sum
+grep '^rsc.io/quote v1.5.0/go.mod h1:' go.sum
+
+-- go.mod --
+module m
+
+go 1.15
+
+require (
+ rsc.io/quote v1.5.2
+ example.com/r v0.0.0
+)
+
+replace example.com/r => ./r
+
+-- go.sum --
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw=
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+rsc.io/quote v1.5.0 h1:6fJa6E+wGadANKkUMlZ0DhXFpoKlslOQDCo259XtdIE=
+rsc.io/quote v1.5.0/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
+rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0=
+rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
+rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+rsc.io/testonly v1.0.0 h1:K/VWHdO+Jv7woUXG0GzVNx1czBXUt3Ib1deaMn+xk64=
+rsc.io/testonly v1.0.0/go.mod h1:OqmGbIFOcF+XrFReLOGZ6BhMM7uMBiQwZsyNmh74SzY=
+
+-- r/go.mod --
+module example.com/r
+
+require rsc.io/quote v1.5.0
+
+-- use.go --
+package use
+
+import _ "example.com/r"
+
+-- r/use.go --
+package use
+
+import _ "rsc.io/quote"
diff --git a/src/cmd/go/testdata/script/mod_tidy_oldgo.txt b/src/cmd/go/testdata/script/mod_tidy_oldgo.txt
new file mode 100644
index 0000000..0e88b06
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_tidy_oldgo.txt
@@ -0,0 +1,21 @@
+# Modules were introduced in Go 1.11, but for various reasons users may
+# decide to declare a (much!) older go version in their go.mod file.
+# Modules with very old versions should not be rejected, and should have
+# the same module-graph semantics as in Go 1.11.
+
+cp go.mod go.mod.orig
+go mod tidy
+cmp go.mod go.mod.orig
+
+-- go.mod --
+module example.com/legacy/go1
+
+go 1.0
+
+require golang.org/x/text v0.3.0
+-- main.go --
+package main
+
+import _ "golang.org/x/text/language"
+
+func main() {}
diff --git a/src/cmd/go/testdata/script/mod_tidy_quote.txt b/src/cmd/go/testdata/script/mod_tidy_quote.txt
new file mode 100644
index 0000000..423c7c2
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_tidy_quote.txt
@@ -0,0 +1,26 @@
+# Check that mod tidy does not introduce repeated
+# require statements when input go.mod has quoted requirements.
+env GO111MODULE=on
+
+go mod tidy
+grep -count=1 rsc.io/quote go.mod
+
+cp go.mod2 go.mod
+go mod tidy
+grep -count=1 rsc.io/quote go.mod
+
+
+-- go.mod --
+module x
+
+-- x.go --
+package x
+import "rsc.io/quote"
+func main() { _ = quote.Hello }
+
+-- go.mod2 --
+module x
+require (
+ "rsc.io/sampler" v1.3.0
+ "rsc.io/quote" v1.5.2
+)
diff --git a/src/cmd/go/testdata/script/mod_tidy_replace.txt b/src/cmd/go/testdata/script/mod_tidy_replace.txt
new file mode 100644
index 0000000..274f3bf
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_tidy_replace.txt
@@ -0,0 +1,145 @@
+env GO111MODULE=on
+env GOFLAGS=-mod=mod
+[short] skip
+
+# golang.org/issue/30166: 'go mod tidy' should not crash if a replaced module is
+# involved in a cycle.
+cd cycle
+env GOTRACEBACK=off
+go mod tidy
+cd ..
+
+# From inside the module, 'go list -m all' should NOT include transitive
+# requirements of modules that have been replaced.
+go list -m all
+stdout 'rsc.io/quote/v3 v3.0.0'
+! stdout 'rsc.io/sampler'
+! stdout 'golang.org/x/text'
+
+# From outside the module, 'go list -m all' should include them.
+cd outside
+go list -m all
+stdout 'rsc.io/quote/v3 v3.0.0'
+stdout 'rsc.io/sampler v1.3.0'
+stdout 'golang.org/x/text'
+cd ..
+
+# 'go list all' should add indirect requirements to satisfy the packages
+# imported from replacement modules.
+! grep 'rsc.io/sampler' go.mod
+! grep 'golang.org/x/text' go.mod
+go list all
+grep 'rsc.io/sampler' go.mod
+grep 'golang.org/x/text' go.mod
+
+# 'go get' and 'go mod tidy' should follow the requirements of the replacements,
+# not the originals, even if that results in a set of versions that are
+# misleading or redundant without those replacements.
+go get rsc.io/sampler@v1.2.0
+go mod tidy
+go list -m all
+stdout 'rsc.io/quote/v3 v3.0.0'
+stdout 'rsc.io/sampler v1.2.0'
+stdout 'golang.org/x/text'
+
+# The requirements seen from outside may be higher (or lower)
+# than those seen from within the module.
+grep 'rsc.io/sampler v1.2.0' go.mod
+cd outside
+go list -m all
+stdout 'rsc.io/sampler v1.3.0'
+cd ..
+
+# The same module can't be used as two different paths.
+cd multiple-paths
+! go mod tidy
+stderr 'rsc.io/quote/v3@v3.0.0 used for two different module paths \(not-rsc.io/quote/v3 and rsc.io/quote/v3\)'
+
+-- go.mod --
+module example.com/tidy
+
+require rsc.io/quote/v3 v3.0.0
+replace rsc.io/quote/v3 => ./not-rsc.io/quote/v3
+
+-- imports.go --
+package tidy
+
+import _ "rsc.io/quote/v3"
+
+-- outside/go.mod --
+module example.com/tidy/outside
+
+require example.com/tidy v0.0.0
+replace example.com/tidy => ./..
+
+-- not-rsc.io/quote/v3/go.mod --
+module not-rsc.io/quote/v3
+
+// No requirements specified!
+
+-- not-rsc.io/quote/v3/quote.go --
+package quote
+
+import (
+ _ "rsc.io/sampler"
+ _ "golang.org/x/text/language"
+)
+
+-- cycle/go.mod --
+module golang.org/issue/30166
+
+require (
+ golang.org/issue/30166/a v0.0.0
+ golang.org/issue/30166/b v0.0.0
+)
+
+replace (
+ golang.org/issue/30166/a => ./a
+ golang.org/issue/30166/b => ./b
+)
+-- cycle/cycle.go --
+package cycle
+
+import (
+ _ "golang.org/issue/30166/a"
+ _ "golang.org/issue/30166/b"
+)
+-- cycle/a/a.go --
+package a
+-- cycle/a/go.mod --
+module golang.org/issue/30166/a
+
+require golang.org/issue/30166/b v0.0.0
+-- cycle/b/b.go --
+package b
+-- cycle/b/go.mod --
+module golang.org/issue/30166/b
+
+require golang.org/issue/30166/a v0.0.0
+-- multiple-paths/main.go --
+package main
+
+import (
+ "fmt"
+ "rsc.io/quote/v3"
+)
+
+func main() {
+ fmt.Println(quote.GoV3())
+}
+-- multiple-paths/go.mod --
+module quoter
+
+require (
+ rsc.io/quote/v3 v3.0.0
+ not-rsc.io/quote/v3 v3.0.0
+)
+
+replace not-rsc.io/quote/v3 => rsc.io/quote/v3 v3.0.0
+-- multiple-paths/use.go --
+package quoter
+
+import (
+ _ "not-rsc.io/quote/v3"
+ _ "rsc.io/quote/v3"
+)
diff --git a/src/cmd/go/testdata/script/mod_tidy_replace_old.txt b/src/cmd/go/testdata/script/mod_tidy_replace_old.txt
new file mode 100644
index 0000000..18605b1
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_tidy_replace_old.txt
@@ -0,0 +1,34 @@
+# Regression test for https://golang.org/issue/46659.
+#
+# If a 'replace' directive specifies an older-than-selected version of a module,
+# 'go mod tidy' shouldn't try to add that version to the build list to resolve a
+# missing package: it won't be selected, and would cause the module loader to
+# loop indefinitely trying to resolve the package.
+
+cp go.mod go.mod.orig
+
+! go mod tidy
+! stderr panic
+stderr '^go: golang\.org/issue46659 imports\n\texample\.com/missingpkg/deprecated: package example\.com/missingpkg/deprecated provided by example\.com/missingpkg at latest version v1\.0\.0 but not at required version v1\.0\.1-beta$'
+
+go mod tidy -e
+
+cmp go.mod go.mod.orig
+
+-- go.mod --
+module golang.org/issue46659
+
+go 1.17
+
+replace example.com/missingpkg v1.0.1-alpha => example.com/missingpkg v1.0.0
+
+require example.com/usemissingpre v1.0.0
+
+require example.com/missingpkg v1.0.1-beta // indirect
+-- m.go --
+package m
+
+import (
+ _ "example.com/missingpkg/deprecated"
+ _ "example.com/usemissingpre"
+)
diff --git a/src/cmd/go/testdata/script/mod_tidy_sum.txt b/src/cmd/go/testdata/script/mod_tidy_sum.txt
new file mode 100644
index 0000000..5a15818
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_tidy_sum.txt
@@ -0,0 +1,33 @@
+env GO111MODULE=on
+
+# go.sum should list directly used modules and dependencies
+go get rsc.io/quote@v1.5.2
+go mod tidy
+grep rsc.io/sampler go.sum
+
+# go.sum should not normally lose old entries
+go get rsc.io/quote@v1.0.0
+grep 'rsc.io/quote v1.0.0' go.sum
+grep 'rsc.io/quote v1.5.2' go.sum
+grep rsc.io/sampler go.sum
+
+# go mod tidy should clear dead entries from go.sum
+go mod tidy
+grep 'rsc.io/quote v1.0.0' go.sum
+! grep 'rsc.io/quote v1.5.2' go.sum
+! grep rsc.io/sampler go.sum
+
+# go.sum with no entries is OK to keep
+# (better for version control not to delete and recreate.)
+cp x.go.noimports x.go
+go mod tidy
+exists go.sum
+! grep . go.sum
+
+-- go.mod --
+module x
+-- x.go --
+package x
+import _ "rsc.io/quote"
+-- x.go.noimports --
+package x
diff --git a/src/cmd/go/testdata/script/mod_tidy_support_buildx.txt b/src/cmd/go/testdata/script/mod_tidy_support_buildx.txt
new file mode 100644
index 0000000..d2135e1
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_tidy_support_buildx.txt
@@ -0,0 +1,18 @@
+# This test checks that "go mod tidy -x" print
+# commands tidy executes.
+# Verifies golang.org/issue/35849
+
+rm $GOPATH/pkg/mod/cache/download/rsc.io/quote
+go mod tidy
+! stderr 'get '$GOPROXY
+
+rm $GOPATH/pkg/mod/cache/download/rsc.io/quote
+go mod tidy -x
+stderr 'get '$GOPROXY
+
+-- go.mod --
+module example.com/mod
+
+-- a.go --
+package mod
+import _ "rsc.io/quote" \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/mod_tidy_symlink_issue35941.txt b/src/cmd/go/testdata/script/mod_tidy_symlink_issue35941.txt
new file mode 100644
index 0000000..d4658c6
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_tidy_symlink_issue35941.txt
@@ -0,0 +1,36 @@
+env GO111MODULE=on
+[!symlink] skip
+
+cd m
+symlink symlink -> ../outside
+
+cp go.mod go.mod.orig
+
+# Issue 35941: suppress symlink warnings when running 'go mod tidy'.
+# 'go mod tidy' should not scan packages in symlinked subdirectories.
+go mod tidy
+! stderr 'warning: ignoring symlink'
+cmp go.mod go.mod.orig
+
+! go build ./symlink
+stderr '^symlink[\\/]symlink.go:3:8: module example.net/unresolved provides package example.net/unresolved and is replaced but not required; to add it:\n\tgo get example.net/unresolved@v0.1.0$'
+
+-- m/go.mod --
+module example.net/m
+
+go 1.16
+
+replace example.net/unresolved v0.1.0 => ../unresolved
+-- m/a.go --
+package a
+-- outside/symlink.go --
+package symlink
+
+import _ "example.net/unresolved"
+-- unresolved/go.mod --
+module example.net/unresolved
+
+go 1.16
+-- unresolved/unresolved.go --
+// Package unresolved exists, but 'go mod tidy' won't add it.
+package unresolved
diff --git a/src/cmd/go/testdata/script/mod_tidy_temp.txt b/src/cmd/go/testdata/script/mod_tidy_temp.txt
new file mode 100644
index 0000000..8a2fa4e
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_tidy_temp.txt
@@ -0,0 +1,26 @@
+# Regression test for https://go.dev/issue/51992
+
+# 'go mod tidy' should error instead of throwing panic in the situation below.
+# 1. /tmp/go.mod exists
+# 2. run 'go mod tidy' in /tmp or in the child directory not having go.mod.
+
+[GOOS:plan9] stop # Plan 9 has no $TMPDIR variable to set.
+
+env GOROOT=$TESTGO_GOROOT
+env TMP=$WORK
+env TMPDIR=$WORK
+mkdir $WORK/child
+
+! go mod tidy
+! stdout .
+stderr 'go: go.mod file not found in current directory or any parent directory'
+
+cd $WORK/child
+! go mod tidy
+! stdout .
+stderr 'go: go.mod file not found in current directory or any parent directory'
+
+-- $WORK/go.mod --
+module issue51992
+
+go 1.18
diff --git a/src/cmd/go/testdata/script/mod_tidy_version.txt b/src/cmd/go/testdata/script/mod_tidy_version.txt
new file mode 100644
index 0000000..e3f2561
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_tidy_version.txt
@@ -0,0 +1,394 @@
+# https://golang.org/issue/45094: 'go mod tidy' now accepts a '-go' flag
+# to change the language version in use.
+#
+# The package import graph used in this test looks like:
+#
+# m --- a --- b
+# |
+# b_test --- c
+# |
+# c_test --- d
+#
+# The module diagram looks like:
+#
+# m --- a --- b
+# |
+# + --- c
+# |
+# + --- d
+#
+# Module b omits its dependency on c, and module c omits its dependency on d.
+#
+# In go 1.15, the tidy main module must require a (because it is direct),
+# c (because it is a missing test dependency of an imported package),
+# and d (because it is a missing transitive test dependency).
+#
+# In go 1.16, the tidy main module can omit d because it is no longer
+# included in "all".
+#
+# In go 1.17, the main module must explicitly require b
+# (because it is transitively imported by the main module).
+
+cp go.mod go.mod.orig
+
+ # Pretend we're a release version so that we can theoretically
+ # write our version in toolchain lines.
+env goversion=1.99.0
+env TESTGO_VERSION=go${goversion}
+
+# An invalid argument should be rejected.
+
+! go mod tidy -go=bananas
+stderr '^invalid value "bananas" for flag -go: expecting a Go version like "'$goversion'"$'
+cmp go.mod go.mod.orig
+
+! go mod tidy -go=0.9
+stderr '^invalid value "0.9" for flag -go: expecting a Go version like "'$goversion'"$'
+
+! go mod tidy -go=2000.0
+stderr '^invalid value "2000.0" for flag -go: maximum supported Go version is '$goversion'$'
+
+
+# Supported versions should change the go.mod file to be tidy according to the
+# indicated version.
+
+go mod tidy -go=1.15
+cmp go.mod go.mod.115
+
+go mod tidy
+cmp go.mod go.mod.115
+
+
+go mod tidy -go=1.16
+cmp go.mod go.mod.116
+
+go mod tidy
+cmp go.mod go.mod.116
+
+
+go mod tidy -go=1.17
+cmp go.mod go.mod.117
+
+go mod tidy
+cmp go.mod go.mod.117
+
+
+# If we downgrade back to 1.15, we should re-resolve d to v0.2.0 instead
+# of the original v0.1.0 (because the original requirement is lost).
+
+go mod tidy -go=1.15
+cmp go.mod go.mod.115-2
+
+
+# -go= (with an empty argument) maintains the existing version or adds the
+# default version (just like omitting the flag).
+
+go mod tidy -go=''
+cmp go.mod go.mod.115-2
+
+cp go.mod.orig go.mod
+go mod tidy -go=''
+cmpenv go.mod go.mod.latest
+
+# Repeat with go get go@ instead of mod tidy.
+
+# Go 1.16 -> 1.17 should be a no-op.
+cp go.mod.116 go.mod
+go get go@1.16
+cmp go.mod go.mod.116
+
+# Go 1.17 -> 1.16 should leave b (go get is not tidy).
+cp go.mod.117 go.mod
+go get go@1.16
+cmp go.mod go.mod.116from117
+
+# Go 1.15 -> 1.16 should leave d (go get is not tidy).
+cp go.mod.115 go.mod
+go get go@1.16
+cmp go.mod go.mod.116from115
+
+# Go 1.16 -> 1.17 should add b.
+cp go.mod.116 go.mod
+go get go@1.17
+stderr '^\tnote: expanded dependencies to upgrade to go 1.17 or higher; run ''go mod tidy'' to clean up'
+cmp go.mod go.mod.117
+
+# Go 1.16 -> 1.15 should add d,
+# but 'go get' doesn't load enough packages to know that.
+# (This leaves the module untidy, but the user can fix it by running 'go mod tidy'.)
+cp go.mod.116 go.mod
+go get go@1.15 toolchain@none
+cmp go.mod go.mod.115from116
+go mod tidy
+cmp go.mod go.mod.115-2
+
+# Updating the go line to 1.21 or higher also updates the toolchain line,
+# only if the toolchain is higher than what would be implied by the go line.
+
+cp go.mod.117 go.mod
+go mod tidy -go=$goversion
+cmpenv go.mod go.mod.latest
+
+cp go.mod.117 go.mod
+go mod tidy -go=1.21.0 # lower than $goversion
+cmpenv go.mod go.mod.121toolchain
+
+
+-- go.mod --
+module example.com/m
+
+require example.net/a v0.1.0
+
+require (
+ example.net/c v0.1.0 // indirect
+ example.net/d v0.1.0 // indirect
+)
+
+replace (
+ example.net/a v0.1.0 => ./a
+ example.net/a v0.2.0 => ./a
+ example.net/b v0.1.0 => ./b
+ example.net/b v0.2.0 => ./b
+ example.net/c v0.1.0 => ./c
+ example.net/c v0.2.0 => ./c
+ example.net/d v0.1.0 => ./d
+ example.net/d v0.2.0 => ./d
+)
+-- m.go --
+package m
+
+import _ "example.net/a"
+
+-- go.mod.115 --
+module example.com/m
+
+go 1.15
+
+require example.net/a v0.1.0
+
+require (
+ example.net/c v0.1.0 // indirect
+ example.net/d v0.1.0 // indirect
+)
+
+replace (
+ example.net/a v0.1.0 => ./a
+ example.net/a v0.2.0 => ./a
+ example.net/b v0.1.0 => ./b
+ example.net/b v0.2.0 => ./b
+ example.net/c v0.1.0 => ./c
+ example.net/c v0.2.0 => ./c
+ example.net/d v0.1.0 => ./d
+ example.net/d v0.2.0 => ./d
+)
+-- go.mod.115from116 --
+module example.com/m
+
+go 1.15
+
+require example.net/a v0.1.0
+
+require example.net/c v0.1.0 // indirect
+
+replace (
+ example.net/a v0.1.0 => ./a
+ example.net/a v0.2.0 => ./a
+ example.net/b v0.1.0 => ./b
+ example.net/b v0.2.0 => ./b
+ example.net/c v0.1.0 => ./c
+ example.net/c v0.2.0 => ./c
+ example.net/d v0.1.0 => ./d
+ example.net/d v0.2.0 => ./d
+)
+-- go.mod.116from115 --
+module example.com/m
+
+go 1.16
+
+require example.net/a v0.1.0
+
+require (
+ example.net/c v0.1.0 // indirect
+ example.net/d v0.1.0 // indirect
+)
+
+replace (
+ example.net/a v0.1.0 => ./a
+ example.net/a v0.2.0 => ./a
+ example.net/b v0.1.0 => ./b
+ example.net/b v0.2.0 => ./b
+ example.net/c v0.1.0 => ./c
+ example.net/c v0.2.0 => ./c
+ example.net/d v0.1.0 => ./d
+ example.net/d v0.2.0 => ./d
+)
+-- go.mod.115-2 --
+module example.com/m
+
+go 1.15
+
+require example.net/a v0.1.0
+
+require (
+ example.net/c v0.1.0 // indirect
+ example.net/d v0.2.0 // indirect
+)
+
+replace (
+ example.net/a v0.1.0 => ./a
+ example.net/a v0.2.0 => ./a
+ example.net/b v0.1.0 => ./b
+ example.net/b v0.2.0 => ./b
+ example.net/c v0.1.0 => ./c
+ example.net/c v0.2.0 => ./c
+ example.net/d v0.1.0 => ./d
+ example.net/d v0.2.0 => ./d
+)
+-- go.mod.116 --
+module example.com/m
+
+go 1.16
+
+require example.net/a v0.1.0
+
+require example.net/c v0.1.0 // indirect
+
+replace (
+ example.net/a v0.1.0 => ./a
+ example.net/a v0.2.0 => ./a
+ example.net/b v0.1.0 => ./b
+ example.net/b v0.2.0 => ./b
+ example.net/c v0.1.0 => ./c
+ example.net/c v0.2.0 => ./c
+ example.net/d v0.1.0 => ./d
+ example.net/d v0.2.0 => ./d
+)
+-- go.mod.117 --
+module example.com/m
+
+go 1.17
+
+require example.net/a v0.1.0
+
+require (
+ example.net/b v0.1.0 // indirect
+ example.net/c v0.1.0 // indirect
+)
+
+replace (
+ example.net/a v0.1.0 => ./a
+ example.net/a v0.2.0 => ./a
+ example.net/b v0.1.0 => ./b
+ example.net/b v0.2.0 => ./b
+ example.net/c v0.1.0 => ./c
+ example.net/c v0.2.0 => ./c
+ example.net/d v0.1.0 => ./d
+ example.net/d v0.2.0 => ./d
+)
+-- go.mod.116from117 --
+module example.com/m
+
+go 1.16
+
+require example.net/a v0.1.0
+
+require (
+ example.net/b v0.1.0 // indirect
+ example.net/c v0.1.0 // indirect
+)
+
+replace (
+ example.net/a v0.1.0 => ./a
+ example.net/a v0.2.0 => ./a
+ example.net/b v0.1.0 => ./b
+ example.net/b v0.2.0 => ./b
+ example.net/c v0.1.0 => ./c
+ example.net/c v0.2.0 => ./c
+ example.net/d v0.1.0 => ./d
+ example.net/d v0.2.0 => ./d
+)
+-- go.mod.latest --
+module example.com/m
+
+go $goversion
+
+require example.net/a v0.1.0
+
+require (
+ example.net/b v0.1.0 // indirect
+ example.net/c v0.1.0 // indirect
+)
+
+replace (
+ example.net/a v0.1.0 => ./a
+ example.net/a v0.2.0 => ./a
+ example.net/b v0.1.0 => ./b
+ example.net/b v0.2.0 => ./b
+ example.net/c v0.1.0 => ./c
+ example.net/c v0.2.0 => ./c
+ example.net/d v0.1.0 => ./d
+ example.net/d v0.2.0 => ./d
+)
+-- go.mod.121toolchain --
+module example.com/m
+
+go 1.21.0
+
+toolchain $TESTGO_VERSION
+
+require example.net/a v0.1.0
+
+require (
+ example.net/b v0.1.0 // indirect
+ example.net/c v0.1.0 // indirect
+)
+
+replace (
+ example.net/a v0.1.0 => ./a
+ example.net/a v0.2.0 => ./a
+ example.net/b v0.1.0 => ./b
+ example.net/b v0.2.0 => ./b
+ example.net/c v0.1.0 => ./c
+ example.net/c v0.2.0 => ./c
+ example.net/d v0.1.0 => ./d
+ example.net/d v0.2.0 => ./d
+)
+-- a/go.mod --
+module example.net/a
+
+go 1.15
+
+require example.net/b v0.1.0
+-- a/a.go --
+package a
+
+import _ "example.net/b"
+
+-- b/go.mod --
+module example.net/b
+
+go 1.15
+-- b/b.go --
+package b
+-- b/b_test.go --
+package b_test
+
+import _ "example.net/c"
+
+-- c/go.mod --
+module example.net/c
+
+go 1.15
+-- c/c.go --
+package c
+-- c/c_test.go --
+package c_test
+
+import _ "example.net/d"
+
+-- d/go.mod --
+module example.net/d
+
+go 1.15
+-- d/d.go --
+package d
diff --git a/src/cmd/go/testdata/script/mod_tidy_version_tooold.txt b/src/cmd/go/testdata/script/mod_tidy_version_tooold.txt
new file mode 100644
index 0000000..713ef1a
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_tidy_version_tooold.txt
@@ -0,0 +1,23 @@
+env TESTGO_VERSION=go1.22.0
+
+! go mod tidy -go=1.21
+stderr '^go: example.net/a@v0.1.0 requires go@1.22, but 1.21 is requested$'
+
+-- go.mod --
+module example
+
+go 1.22
+
+require example.net/a v0.1.0
+
+replace example.net/a v0.1.0 => ./a
+-- example.go --
+package example
+
+import "example.net/a"
+-- a/go.mod --
+module example.net/a
+
+go 1.22
+-- a/a.go --
+package a
diff --git a/src/cmd/go/testdata/script/mod_toolchain.txt b/src/cmd/go/testdata/script/mod_toolchain.txt
new file mode 100644
index 0000000..c771cae
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_toolchain.txt
@@ -0,0 +1,76 @@
+env TESTGO_VERSION=go1.100.0
+env TESTGO_VERSION_SWITCH=switch
+
+go get toolchain@go1.22.1
+stderr '^go: added toolchain go1.22.1$'
+! stderr '(added|removed|upgraded|downgraded) go'
+grep 'toolchain go1.22.1' go.mod
+
+go get toolchain@none
+stderr '^go: removed toolchain go1.22.1$'
+! stderr '(added|removed|upgraded|downgraded) go'
+! grep toolchain go.mod
+
+go get toolchain@go1.22.1
+stderr '^go: added toolchain go1.22.1$'
+! stderr '(added|removed|upgraded|downgraded) go'
+grep 'toolchain go1.22.1' go.mod
+
+go get go@1.22.3
+stderr '^go: upgraded go 1.10 => 1.22.3$'
+stderr '^go: upgraded toolchain go1.22.1 => go1.100.0$'
+grep 'go 1.22.3' go.mod
+
+go get go@1.22.3 toolchain@1.22.3
+stderr '^go: removed toolchain go1.100.0$'
+! grep toolchain go.mod
+
+go get go@1.22.1 toolchain@go1.22.3
+stderr '^go: downgraded go 1.22.3 => 1.22.1$'
+stderr '^go: added toolchain go1.22.3$'
+grep 'go 1.22.1' go.mod
+grep 'toolchain go1.22.3' go.mod
+
+go get go@1.22.3 toolchain@1.22.3
+stderr '^go: upgraded go 1.22.1 => 1.22.3$'
+stderr '^go: removed toolchain go1.22.3$'
+grep 'go 1.22.3' go.mod
+! grep toolchain go.mod
+
+go get toolchain@1.22.1
+stderr '^go: downgraded go 1.22.3 => 1.22.1$'
+! stderr toolchain # already gone, was not added
+grep 'go 1.22.1' go.mod
+! grep toolchain go.mod
+
+env TESTGO_VERSION=go1.22.1
+env GOTOOLCHAIN=local
+! go get go@1.22.3
+stderr 'go: updating go.mod requires go >= 1.22.3 \(running go 1.22.1; GOTOOLCHAIN=local\)$'
+
+env TESTGO_VERSION=go1.30
+go get toolchain@1.22.3
+grep 'toolchain go1.22.3' go.mod
+
+go get go@1.22.1
+grep 'go 1.22.1' go.mod
+go get m2@v1.0.0
+stderr '^go: upgraded go 1.22.1 => 1.23$'
+stderr '^go: added m2 v1.0.0$'
+grep 'go 1.23$' go.mod
+
+go get toolchain@go1.23.9 go@1.23.5
+go get toolchain@none
+stderr '^go: removed toolchain go1.23.9'
+! stderr ' go 1'
+grep 'go 1.23.5' go.mod
+
+-- go.mod --
+module m
+go 1.10
+
+replace m2 v1.0.0 => ./m2
+
+-- m2/go.mod --
+module m2
+go 1.23
diff --git a/src/cmd/go/testdata/script/mod_toolchain_slash.txt b/src/cmd/go/testdata/script/mod_toolchain_slash.txt
new file mode 100644
index 0000000..bb1f770
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_toolchain_slash.txt
@@ -0,0 +1,32 @@
+[!exec:/bin/sh] skip
+
+chmod 0777 go1.999999-/run.sh
+chmod 0777 run.sh
+
+! go list all
+! stdout 'RAN SCRIPT'
+
+cd subdir
+! go list all
+! stdout 'RAN SCRIPT'
+
+-- go.mod --
+module exploit
+
+go 1.21
+toolchain go1.999999-/run.sh
+-- go1.999999-/run.sh --
+#!/bin/sh
+printf 'RAN SCRIPT\n'
+exit 1
+-- run.sh --
+#!/bin/sh
+printf 'RAN SCRIPT\n'
+exit 1
+-- subdir/go.mod --
+module exploit
+
+go 1.21
+toolchain go1.999999-/../../run.sh
+-- subdir/go1.999999-/README.txt --
+heh heh heh
diff --git a/src/cmd/go/testdata/script/mod_update_sum_readonly.txt b/src/cmd/go/testdata/script/mod_update_sum_readonly.txt
new file mode 100644
index 0000000..41f12e4
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_update_sum_readonly.txt
@@ -0,0 +1,34 @@
+# When finding the latest version of a module, we should not download version
+# contents. Previously, we downloaded .zip files to determine whether a real
+# .mod file was present in order to decide whether +incompatible versions
+# could be "latest".
+#
+# Verifies #47377.
+
+# rsc.io/breaker has two versions, neither of which has a .mod file.
+go list -m -versions rsc.io/breaker
+stdout '^rsc.io/breaker v1.0.0 v2.0.0\+incompatible$'
+go mod download rsc.io/breaker@v1.0.0
+! grep '^go' $GOPATH/pkg/mod/cache/download/rsc.io/breaker/@v/v1.0.0.mod
+go mod download rsc.io/breaker@v2.0.0+incompatible
+! grep '^go' $GOPATH/pkg/mod/cache/download/rsc.io/breaker/@v/v2.0.0+incompatible.mod
+
+# Delete downloaded .zip files.
+go clean -modcache
+
+# Check for updates.
+go list -m -u rsc.io/breaker
+stdout '^rsc.io/breaker v1.0.0 \[v2.0.0\+incompatible\]$'
+
+# We should not have downloaded zips.
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/breaker/@v/v1.0.0.zip
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/breaker/@v/v2.0.0+incompatible.zip
+
+-- go.mod --
+module m
+
+go 1.16
+
+require rsc.io/breaker v1.0.0
+-- go.sum --
+rsc.io/breaker v1.0.0/go.mod h1:s5yxDXvD88U1/ESC23I2FK3Lkv4YIKaB1ij/Hbm805g=
diff --git a/src/cmd/go/testdata/script/mod_upgrade_patch.txt b/src/cmd/go/testdata/script/mod_upgrade_patch.txt
new file mode 100644
index 0000000..79a9808
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_upgrade_patch.txt
@@ -0,0 +1,110 @@
+env GO111MODULE=on
+[short] skip
+
+# Initially, we are at v1.0.0 for all dependencies.
+go get
+cp go.mod go.mod.orig
+go list -m all
+stdout '^patch.example.com/direct v1.0.0'
+stdout '^patch.example.com/indirect v1.0.0'
+! stdout '^patch.example.com/depofdirectpatch'
+
+# @patch should be rejected for modules not already in the build list.
+! go get patch.example.com/depofdirectpatch@patch
+stderr '^go: can''t query version "patch" of module patch.example.com/depofdirectpatch: no existing version is required$'
+cmp go.mod.orig go.mod
+
+# get -u=patch, with no arguments, should patch-update all dependencies
+# of the package in the current directory, pulling in transitive dependencies
+# and also patching those.
+cp go.mod.orig go.mod
+go get -u=patch
+go list -m all
+stdout '^patch.example.com/direct v1.0.1'
+stdout '^patch.example.com/indirect v1.0.1'
+stdout '^patch.example.com/depofdirectpatch v1.0.0'
+
+# 'get all@patch' should patch the modules that provide packages in 'all'.
+cp go.mod.orig go.mod
+go get all@patch
+go list -m all
+stdout '^patch.example.com/direct v1.0.1'
+stdout '^patch.example.com/indirect v1.0.1'
+stdout '^patch.example.com/depofdirectpatch v1.0.0'
+
+# ...but 'all@patch' should fail if any of the affected modules do not already
+# have a selected version.
+cp go.mod.orig go.mod
+go mod edit -droprequire=patch.example.com/direct
+cp go.mod go.mod.dropped
+! go get all@patch
+stderr '^go: all@patch: can''t query version "patch" of module patch.example.com/direct: no existing version is required$'
+cmp go.mod.dropped go.mod
+
+# Requesting the direct dependency with -u=patch but without an explicit version
+# should patch-update it and its dependencies.
+cp go.mod.orig go.mod
+go get -u=patch patch.example.com/direct
+go list -m all
+stdout '^patch.example.com/direct v1.0.1'
+stdout '^patch.example.com/indirect v1.0.1'
+stdout '^patch.example.com/depofdirectpatch v1.0.0'
+
+# Requesting only the indirect dependency should not update the direct one.
+cp go.mod.orig go.mod
+go get -u=patch patch.example.com/indirect
+go list -m all
+stdout '^patch.example.com/direct v1.0.0'
+stdout '^patch.example.com/indirect v1.0.1'
+! stdout '^patch.example.com/depofdirectpatch'
+
+# @patch should apply only to the specific module,
+# but the result must reflect its upgraded requirements.
+cp go.mod.orig go.mod
+go get patch.example.com/direct@patch
+go list -m all
+stdout '^patch.example.com/direct v1.0.1'
+stdout '^patch.example.com/indirect v1.0.0'
+stdout '^patch.example.com/depofdirectpatch v1.0.0'
+
+# An explicit @patch should override a general -u.
+cp go.mod.orig go.mod
+go get -u patch.example.com/direct@patch
+go list -m all
+stdout '^patch.example.com/direct v1.0.1'
+stdout '^patch.example.com/indirect v1.1.0'
+stdout '^patch.example.com/depofdirectpatch v1.0.0'
+
+# An explicit @latest should override a general -u=patch.
+cp go.mod.orig go.mod
+go get -u=patch patch.example.com/direct@latest
+go list -m all
+stdout '^patch.example.com/direct v1.1.0'
+stdout '^patch.example.com/indirect v1.0.1'
+! stdout '^patch.example.com/depofdirectpatch'
+
+# Standard library packages cannot be upgraded explicitly.
+cp go.mod.orig go.mod
+! go get cmd/vet@patch
+stderr 'go: can''t request explicit version "patch" of standard library package cmd/vet$'
+
+# However, standard-library packages without explicit versions are fine.
+go get -u=patch cmd/go
+
+# We can upgrade to a new version of a module with no root package.
+go get example.com/noroot@v1.0.0
+go list -m all
+stdout '^example.com/noroot v1.0.0$'
+go get example.com/noroot@patch
+go list -m all
+stdout '^example.com/noroot v1.0.1$'
+
+
+-- go.mod --
+module x
+
+require patch.example.com/direct v1.0.0
+
+-- main.go --
+package x
+import _ "patch.example.com/direct"
diff --git a/src/cmd/go/testdata/script/mod_vcs_missing.txt b/src/cmd/go/testdata/script/mod_vcs_missing.txt
new file mode 100644
index 0000000..7f63e9d
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_vcs_missing.txt
@@ -0,0 +1,28 @@
+[exec:bzr] skip 'tests NOT having bzr'
+[!net:launchpad.net] skip
+
+env GO111MODULE=on
+env GOPROXY=direct
+
+cd empty
+! go get launchpad.net/gocheck
+stderr '"bzr": executable file not found'
+cd ..
+
+# 1.11 used to give the cryptic error "cannot find module for path" here, but
+# only for a main package.
+cd main
+! go build -mod=mod
+stderr '"bzr": executable file not found'
+cd ..
+
+-- empty/go.mod --
+module m
+-- main/go.mod --
+module m
+-- main/main.go --
+package main
+
+import _ "launchpad.net/gocheck"
+
+func main() {}
diff --git a/src/cmd/go/testdata/script/mod_vendor.txt b/src/cmd/go/testdata/script/mod_vendor.txt
new file mode 100644
index 0000000..b02341d
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_vendor.txt
@@ -0,0 +1,354 @@
+env GO111MODULE=on
+
+# Without vendoring, a build should succeed unless -mod=vendor is set.
+[!short] go build
+[!short] ! go build -mod=vendor
+
+# Without vendoring, 'go list' should report the replacement directory for
+# a package in a replaced module.
+go list -f {{.Dir}} x
+stdout 'src[\\/]x'
+
+# 'go mod vendor' should copy all replaced modules to the vendor directory.
+go mod vendor -v
+stderr '^# x v1.0.0 => ./x'
+stderr '^x'
+stderr '^# y v1.0.0 => ./y'
+stderr '^y'
+stderr '^# z v1.0.0 => ./z'
+stderr '^z'
+! stderr '^w'
+grep 'a/foo/bar/b\na/foo/bar/c' vendor/modules.txt # must be sorted
+
+# An explicit '-mod=mod' should ignore the vendor directory.
+go list -mod=mod -f {{.Dir}} x
+stdout 'src[\\/]x'
+
+go list -mod=mod -f {{.Dir}} -m x
+stdout 'src[\\/]x'
+
+# An explicit '-mod=vendor' should report package directories within
+# the vendor directory.
+go list -mod=vendor -f {{.Dir}} x
+stdout 'src[\\/]vendor[\\/]x'
+
+# 'go list -mod=vendor -m' should successfully list vendored modules,
+# but should not provide a module directory because no directory contains
+# the complete module.
+go list -mod=vendor -f '{{.Version}} {{.Dir}}' -m x
+stdout '^v1.0.0 $'
+
+# -mod=vendor should cause 'go list' flags that look up versions to fail.
+! go list -mod=vendor -versions -m x
+stderr '^go: can''t determine available versions using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)$'
+! go list -mod=vendor -u -m x
+stderr '^go: can''t determine available upgrades using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)$'
+
+# 'go list -mod=vendor -m' on a transitive dependency that does not
+# provide vendored packages should give a helpful error rather than
+# 'not a known dependency'.
+! go list -mod=vendor -f '{{.Version}} {{.Dir}}' -m diamondright
+stderr 'go: module diamondright: can''t resolve module using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)'
+
+# 'go list -mod=mod' should report packages outside the import graph,
+# but 'go list -mod=vendor' should error out for them.
+go list -mod=mod -f {{.Dir}} w
+stdout 'src[\\/]w'
+! go list -mod=vendor -f {{.Dir}} w
+stderr 'package w is not in std'
+
+go list -mod=mod -f {{.Dir}} diamondright
+stdout 'src[\\/]diamondright'
+
+# Test dependencies should not be copied.
+! exists vendor/x/testdata
+! exists vendor/a/foo/bar/b/ignored.go
+! exists vendor/a/foo/bar/b/main_test.go
+
+# Licenses and other metadata for each module should be copied
+# if any package within their module is copied.
+exists vendor/a/foo/AUTHORS.txt
+exists vendor/a/foo/CONTRIBUTORS
+exists vendor/a/foo/LICENSE
+exists vendor/a/foo/PATENTS
+exists vendor/a/foo/COPYING
+exists vendor/a/foo/COPYLEFT
+exists vendor/x/NOTICE!
+exists vendor/mysite/myname/mypkg/LICENSE.txt
+
+! exists vendor/a/foo/licensed-to-kill
+! exists vendor/w
+! exists vendor/w/LICENSE
+! exists vendor/x/x2
+! exists vendor/x/x2/LICENSE
+
+# 'go mod vendor' should work with an alternative vendor directory if the -o flag is provided.
+go mod vendor -v -o alternative-vendor-dir
+exists alternative-vendor-dir/modules.txt
+exists alternative-vendor-dir/a/foo/LICENSE
+
+# 'go mod vendor' should interpret paths relative to the current working directory when the -o flag is provided.
+mkdir dir1
+mkdir dir2
+
+cd dir1
+go mod vendor -v -o relative-vendor-dir
+
+go mod vendor -v -o ../dir2/relative-vendor-dir
+
+cd ..
+exists dir1/relative-vendor-dir/modules.txt
+exists dir1/relative-vendor-dir/a/foo/LICENSE
+exists dir2/relative-vendor-dir/modules.txt
+exists dir2/relative-vendor-dir/a/foo/LICENSE
+
+# 'go mod vendor' should fall back to the default 'vendor' directory when an empty argument is passed to the -o flag
+# the same behavior should be exhibited both on the module root directory, as well as nested subdirectories
+
+go mod vendor -v -o ''
+exists vendor/modules.txt
+
+env GOFLAGS=-o=foo
+go mod vendor -v -o ''
+exists vendor/modules.txt
+env GOFLAGS=''
+
+mkdir -p nested/dir
+cd nested/dir
+go mod vendor -v -o ''
+! exists vendor/
+exists ../../vendor/modules.txt
+cd ../..
+
+# 'go mod vendor' should work with absolute paths as well
+go mod vendor -v -o $WORK/tmp/absolute-vendor-dir
+exists $WORK/tmp/absolute-vendor-dir/modules.txt
+
+[short] stop
+
+# 'go build' and 'go test' using vendored packages should succeed.
+go build -mod=mod
+go build -mod=vendor
+go test -mod=vendor . ./subdir
+go test -mod=vendor ./...
+go fmt -mod=vendor ./...
+
+-- go.mod --
+module m
+
+go 1.13
+
+require (
+ a v1.0.0
+ diamondroot v0.0.0
+ mysite/myname/mypkg v1.0.0
+ w v1.0.0 // indirect
+ x v1.0.0
+ y v1.0.0
+ z v1.0.0
+)
+
+replace (
+ a v1.0.0 => ./a
+ diamondleft => ./diamondleft
+ diamondpoint => ./diamondpoint
+ diamondright => ./diamondright
+ diamondroot => ./diamondroot
+ mysite/myname/mypkg v1.0.0 => ./mypkg
+ w v1.0.0 => ./w
+ x v1.0.0 => ./x
+ y v1.0.0 => ./y
+ z v1.0.0 => ./z
+)
+
+-- a/foo/AUTHORS.txt --
+-- a/foo/CONTRIBUTORS --
+-- a/foo/LICENSE --
+-- a/foo/PATENTS --
+-- a/foo/COPYING --
+-- a/foo/COPYLEFT --
+-- a/foo/licensed-to-kill --
+-- w/LICENSE --
+-- x/NOTICE! --
+-- x/x2/LICENSE --
+-- mypkg/LICENSE.txt --
+
+-- a/foo/bar/b/main.go --
+package b
+-- a/foo/bar/b/ignored.go --
+// This file is intended for use with "go run"; it isn't really part of the package.
+
+// +build ignore
+
+package main
+
+func main() {}
+-- a/foo/bar/b/main_test.go --
+package b
+
+import (
+ "os"
+ "testing"
+)
+
+func TestDir(t *testing.T) {
+ if _, err := os.Stat("../testdata/1"); err != nil {
+ t.Fatalf("testdata: %v", err)
+ }
+}
+-- a/foo/bar/c/main.go --
+package c
+import _ "a/foo/bar/b"
+-- a/foo/bar/c/main_test.go --
+package c
+
+import (
+ "os"
+ "testing"
+)
+
+func TestDir(t *testing.T) {
+ if _, err := os.Stat("../../../testdata/1"); err != nil {
+ t.Fatalf("testdata: %v", err)
+ }
+ if _, err := os.Stat("./testdata/1"); err != nil {
+ t.Fatalf("testdata: %v", err)
+ }
+}
+-- a/foo/bar/c/testdata/1 --
+-- a/foo/bar/testdata/1 --
+-- a/go.mod --
+module a
+-- a/main.go --
+package a
+-- a/main_test.go --
+package a
+
+import (
+ "os"
+ "testing"
+)
+
+func TestDir(t *testing.T) {
+ if _, err := os.Stat("./testdata/1"); err != nil {
+ t.Fatalf("testdata: %v", err)
+ }
+}
+-- a/testdata/1 --
+-- appengine.go --
+// +build appengine
+
+package m
+
+import _ "appengine"
+import _ "appengine/datastore"
+-- mypkg/go.mod --
+module me
+-- mypkg/mydir/d.go --
+package mydir
+-- subdir/v1_test.go --
+package m
+
+import _ "mysite/myname/mypkg/mydir"
+-- testdata1.go --
+package m
+
+import _ "a"
+-- testdata2.go --
+package m
+
+import _ "a/foo/bar/c"
+-- v1.go --
+package m
+
+import _ "x"
+-- v2.go --
+// +build abc
+
+package mMmMmMm
+
+import _ "y"
+-- v3.go --
+// +build !abc
+
+package m
+
+import _ "z"
+-- v4.go --
+// +build notmytag
+
+package m
+
+import _ "x/x1"
+-- importdiamond.go --
+package m
+
+import _ "diamondroot"
+-- w/go.mod --
+module w
+-- w/w.go --
+package w
+-- x/go.mod --
+module x
+-- x/testdata/x.txt --
+placeholder - want directory with no go files
+-- x/x.go --
+package x
+-- x/x1/x1.go --
+// +build notmytag
+
+package x1
+-- x/x2/dummy.txt --
+dummy
+-- x/x_test.go --
+package x
+
+import _ "w"
+-- y/go.mod --
+module y
+-- y/y.go --
+package y
+-- z/go.mod --
+module z
+-- z/z.go --
+package z
+
+-- diamondroot/go.mod --
+module diamondroot
+
+require (
+ diamondleft v0.0.0
+ diamondright v0.0.0
+)
+-- diamondroot/x.go --
+package diamondroot
+
+import _ "diamondleft"
+-- diamondroot/unused/unused.go --
+package unused
+
+import _ "diamondright"
+-- diamondleft/go.mod --
+module diamondleft
+
+require (
+ diamondpoint v0.0.0
+)
+-- diamondleft/x.go --
+package diamondleft
+
+import _ "diamondpoint"
+-- diamondright/go.mod --
+module diamondright
+
+require (
+ diamondpoint v0.0.0
+)
+-- diamondright/x.go --
+package diamondright
+
+import _ "diamondpoint"
+-- diamondpoint/go.mod --
+module diamondpoint
+-- diamondpoint/x.go --
+package diamondpoint
diff --git a/src/cmd/go/testdata/script/mod_vendor_auto.txt b/src/cmd/go/testdata/script/mod_vendor_auto.txt
new file mode 100644
index 0000000..2cafcda
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_vendor_auto.txt
@@ -0,0 +1,259 @@
+# Integration test for golang.org/issue/33848: automatically check and use vendored packages.
+
+env GO111MODULE=on
+
+[short] skip
+
+cd $WORK/auto
+cp go.mod go.mod.orig
+cp $WORK/modules-1.13.txt $WORK/auto/modules.txt
+
+# An explicit -mod=vendor should force use of the vendor directory.
+env GOFLAGS=-mod=vendor
+
+# Pass -e to permit an error: tools.go imports a main package
+# "example.com/printversion".
+# TODO(#59186): investigate why it didn't fail without -e.
+go list -f {{.Dir}} -tags tools -e all
+stdout '^'$WORK'[/\\]auto$'
+stdout '^'$WORK'[/\\]auto[/\\]vendor[/\\]example.com[/\\]printversion$'
+stdout '^'$WORK'[/\\]auto[/\\]vendor[/\\]example.com[/\\]version$'
+
+! go list -m all
+stderr 'go: can''t compute ''all'' using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)'
+
+! go list -m -f '{{.Dir}}' all
+stderr 'go: can''t compute ''all'' using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)'
+
+# An explicit -mod=mod should force the vendor directory to be ignored.
+env GOFLAGS=-mod=mod
+
+go list -f {{.Dir}} -tags tools -e all
+stdout '^'$WORK'[/\\]auto$'
+stdout '^'$GOPATH'[/\\]pkg[/\\]mod[/\\]example.com[/\\]printversion@v1.0.0$'
+stdout '^'$WORK'[/\\]auto[/\\]replacement-version$'
+
+go list -m all
+stdout '^example.com/auto$'
+stdout 'example.com/printversion v1.0.0'
+stdout 'example.com/version v1.0.0'
+
+go list -m -f '{{.Dir}}' all
+stdout '^'$WORK'[/\\]auto$'
+stdout '^'$GOPATH'[/\\]pkg[/\\]mod[/\\]example.com[/\\]printversion@v1.0.0$'
+stdout '^'$WORK'[/\\]auto[/\\]replacement-version$'
+
+# If the main module's "go" directive says 1.13, we should default to -mod=mod.
+env GOFLAGS=
+go mod edit -go=1.13
+
+go list -f {{.Dir}} -tags tools -e all
+stdout '^'$WORK'[/\\]auto$'
+stdout '^'$GOPATH'[/\\]pkg[/\\]mod[/\\]example.com[/\\]printversion@v1.0.0$'
+stdout '^'$WORK'[/\\]auto[/\\]replacement-version$'
+
+go list -m -f '{{.Dir}}' all
+stdout '^'$WORK'[/\\]auto$'
+stdout '^'$GOPATH'[/\\]pkg[/\\]mod[/\\]example.com[/\\]printversion@v1.0.0$'
+stdout '^'$WORK'[/\\]auto[/\\]replacement-version$'
+
+# A 'go 1.14' directive in the main module's go.mod file should enable
+# -mod=vendor by default, along with stronger checks for consistency
+# between the go.mod file and vendor/modules.txt.
+# A 'go 1.13' vendor/modules.txt file is not usually sufficient
+# to pass those checks.
+go mod edit -go=1.14
+
+! go list -f {{.Dir}} -tags tools all
+stderr '^go: inconsistent vendoring in '$WORK[/\\]auto':$'
+stderr '^\texample.com/printversion@v1.0.0: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt'
+stderr '^\texample.com/unused: is replaced in go.mod, but not marked as replaced in vendor/modules.txt'
+stderr '^\texample.com/version@v1.2.0: is replaced in go.mod, but not marked as replaced in vendor/modules.txt'
+stderr '^\tTo ignore the vendor directory, use -mod=readonly or -mod=mod.\n\tTo sync the vendor directory, run:\n\t\tgo mod vendor$'
+
+# Module-specific subcommands should continue to load the full module graph.
+go mod graph
+stdout '^example.com/printversion@v1.0.0 example.com/version@v1.0.0$'
+
+# An explicit -mod=mod should still force the vendor directory to be ignored.
+env GOFLAGS=-mod=mod
+
+go list -f {{.Dir}} -tags tools -e all
+stdout '^'$WORK'[/\\]auto$'
+stdout '^'$GOPATH'[/\\]pkg[/\\]mod[/\\]example.com[/\\]printversion@v1.0.0$'
+stdout '^'$WORK'[/\\]auto[/\\]replacement-version$'
+
+go list -m all
+stdout '^example.com/auto$'
+stdout 'example.com/printversion v1.0.0'
+stdout 'example.com/version v1.0.0'
+
+go list -m -f '{{.Dir}}' all
+stdout '^'$WORK'[/\\]auto$'
+stdout '^'$GOPATH'[/\\]pkg[/\\]mod[/\\]example.com[/\\]printversion@v1.0.0$'
+stdout '^'$WORK'[/\\]auto[/\\]replacement-version$'
+
+# 'go mod vendor' should repair vendor/modules.txt so that the implicit
+# -mod=vendor works again.
+env GOFLAGS=
+
+go mod edit -go=1.14
+go mod vendor
+
+go list -f {{.Dir}} -tags tools -e all
+stdout '^'$WORK'[/\\]auto$'
+stdout '^'$WORK'[/\\]auto[/\\]vendor[/\\]example.com[/\\]printversion$'
+stdout '^'$WORK'[/\\]auto[/\\]vendor[/\\]example.com[/\\]version$'
+
+# ...but 'go list -m' should continue to fail, this time without
+# referring to a -mod default that the user didn't set.
+! go list -m all
+stderr 'go: can''t compute ''all'' using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)'
+
+! go list -m -f '{{.Dir}}' all
+stderr 'go: can''t compute ''all'' using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)'
+
+
+# 'go mod init' should work if there is already a GOPATH-mode vendor directory
+# present. If there are no module dependencies, -mod=vendor should be used by
+# default and should not fail the consistency check even though no module
+# information is present.
+
+rm go.mod
+rm vendor/modules.txt
+
+go mod init example.com/auto
+go list -f {{.Dir}} -tags tools -e all
+stdout '^'$WORK'[/\\]auto$'
+stdout '^'$WORK'[/\\]auto[/\\]vendor[/\\]example.com[/\\]printversion$'
+stdout '^'$WORK'[/\\]auto[/\\]vendor[/\\]example.com[/\\]version$'
+
+# If information about dependencies is added to a 1.14 go.mod file, subsequent
+# list commands should error out if vendor/modules.txt is missing or incomplete.
+
+cp go.mod.orig go.mod
+go mod edit -go=1.14
+! go list -f {{.Dir}} -tags tools -e all
+stderr '^go: inconsistent vendoring in '$WORK[/\\]auto':$'
+stderr '^\texample.com/printversion@v1.0.0: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt'
+stderr '^\texample.com/unused: is replaced in go.mod, but not marked as replaced in vendor/modules.txt'
+stderr '^\texample.com/version@v1.2.0: is replaced in go.mod, but not marked as replaced in vendor/modules.txt'
+stderr '^\tTo ignore the vendor directory, use -mod=readonly or -mod=mod.\n\tTo sync the vendor directory, run:\n\t\tgo mod vendor$'
+
+# If -mod=vendor is set, limited consistency checks should apply even when
+# the go version is 1.13 or earlier.
+# An incomplete or missing vendor/modules.txt should resolve the vendored packages...
+go mod edit -go=1.13
+go list -mod=vendor -f {{.Dir}} -tags tools -e all
+stdout '^'$WORK'[/\\]auto$'
+stdout '^'$WORK'[/\\]auto[/\\]vendor[/\\]example.com[/\\]printversion$'
+stdout '^'$WORK'[/\\]auto[/\\]vendor[/\\]example.com[/\\]version$'
+
+# ...but a version mismatch for an explicit dependency should be noticed.
+cp $WORK/modules-bad-1.13.txt vendor/modules.txt
+! go list -mod=vendor -f {{.Dir}} -tags tools all
+stderr '^go: inconsistent vendoring in '$WORK[/\\]auto':$'
+stderr '^\texample.com/printversion@v1.0.0: is explicitly required in go.mod, but vendor/modules.txt indicates example.com/printversion@v1.1.0$'
+stderr '^\tTo ignore the vendor directory, use -mod=readonly or -mod=mod.\n\tTo sync the vendor directory, run:\n\t\tgo mod vendor$'
+
+# If the go version is still 1.13, 'go mod vendor' should write a
+# matching vendor/modules.txt containing the corrected 1.13 data.
+go mod vendor
+cmp $WORK/modules-1.13.txt vendor/modules.txt
+
+go list -mod=vendor -f {{.Dir}} -tags tools -e all
+stdout '^'$WORK'[/\\]auto$'
+stdout '^'$WORK'[/\\]auto[/\\]vendor[/\\]example.com[/\\]printversion$'
+stdout '^'$WORK'[/\\]auto[/\\]vendor[/\\]example.com[/\\]version$'
+
+# When the version is upgraded to 1.14, 'go mod vendor' should write a
+# vendor/modules.txt with the updated 1.14 annotations.
+go mod edit -go=1.14
+go mod vendor
+cmp $WORK/modules-1.14.txt vendor/modules.txt
+
+# Then, -mod=vendor should kick in automatically and succeed.
+go list -f {{.Dir}} -tags tools -e all
+stdout '^'$WORK'[/\\]auto$'
+stdout '^'$WORK'[/\\]auto[/\\]vendor[/\\]example.com[/\\]printversion$'
+stdout '^'$WORK'[/\\]auto[/\\]vendor[/\\]example.com[/\\]version$'
+
+# 'go get' should update from the network or module cache,
+# even if a vendor directory is present.
+go get example.com/version@v1.1.0
+! go list -f {{.Dir}} -tags tools all
+stderr '^go: inconsistent vendoring'
+
+-- $WORK/auto/go.mod --
+module example.com/auto
+
+go 1.13
+
+require example.com/printversion v1.0.0
+
+replace (
+ example.com/unused => nonexistent.example.com/unused v1.0.0-whatever
+ example.com/version v1.0.0 => ./replacement-version
+ example.com/version v1.2.0 => nonexistent.example.com/version v1.2.0
+)
+-- $WORK/auto/tools.go --
+// +build tools
+
+package auto
+
+import _ "example.com/printversion"
+-- $WORK/auto/auto.go --
+package auto
+-- $WORK/auto/replacement-version/go.mod --
+module example.com/version
+-- $WORK/auto/replacement-version/version.go --
+package version
+
+const V = "v1.0.0-replaced"
+-- $WORK/modules-1.14.txt --
+# example.com/printversion v1.0.0
+## explicit
+example.com/printversion
+# example.com/version v1.0.0 => ./replacement-version
+example.com/version
+# example.com/unused => nonexistent.example.com/unused v1.0.0-whatever
+# example.com/version v1.2.0 => nonexistent.example.com/version v1.2.0
+-- $WORK/modules-1.13.txt --
+# example.com/printversion v1.0.0
+example.com/printversion
+# example.com/version v1.0.0 => ./replacement-version
+example.com/version
+-- $WORK/modules-bad-1.13.txt --
+# example.com/printversion v1.1.0
+example.com/printversion
+# example.com/version v1.1.0
+example.com/version
+-- $WORK/auto/vendor/example.com/printversion/go.mod --
+module example.com/printversion
+
+require example.com/version v1.0.0
+replace example.com/version v1.0.0 => ../oops v0.0.0
+exclude example.com/version v1.0.1
+-- $WORK/auto/vendor/example.com/printversion/printversion.go --
+package main
+
+import (
+ "fmt"
+ "os"
+ "runtime/debug"
+
+ _ "example.com/version"
+)
+
+func main() {
+ info, _ := debug.ReadBuildInfo()
+ fmt.Fprintf(os.Stdout, "path is %s\n", info.Path)
+ fmt.Fprintf(os.Stdout, "main is %s %s\n", info.Main.Path, info.Main.Version)
+ for _, m := range info.Deps {
+ fmt.Fprintf(os.Stdout, "using %s %s\n", m.Path, m.Version)
+ }
+}
+-- $WORK/auto/vendor/example.com/version/version.go --
+package version
+
+const V = "v1.0.0-replaced"
diff --git a/src/cmd/go/testdata/script/mod_vendor_build.txt b/src/cmd/go/testdata/script/mod_vendor_build.txt
new file mode 100644
index 0000000..4efda55
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_vendor_build.txt
@@ -0,0 +1,41 @@
+env GO111MODULE=on
+[short] skip
+
+# Populate go.mod and go.sum.
+go mod tidy
+
+# initial conditions: using sampler v1.3.0, not listed in go.mod.
+go list -deps
+stdout rsc.io/sampler
+! grep 'rsc.io/sampler v1.3.0' go.mod
+
+# update to v1.3.1, now indirect in go.mod.
+go get rsc.io/sampler@v1.3.1
+grep 'rsc.io/sampler v1.3.1 // indirect' go.mod
+cp go.mod go.mod.good
+
+# vendoring can but should not need to make changes.
+go mod vendor
+cmp go.mod go.mod.good
+
+# go list -mod=vendor (or go build -mod=vendor) must not modify go.mod.
+# golang.org/issue/26704
+go list -mod=vendor
+cmp go.mod go.mod.good
+
+# With a clean (and empty) module cache, 'go list -mod=vendor' should not download modules.
+go clean -modcache
+env GOPROXY=off
+! go list ...
+go list -mod=vendor ...
+
+# However, it should still list packages in the main module.
+go list -mod=vendor m/...
+stdout m
+
+-- go.mod --
+module m
+go 1.12
+-- x.go --
+package x
+import _ "rsc.io/quote"
diff --git a/src/cmd/go/testdata/script/mod_vendor_embed.txt b/src/cmd/go/testdata/script/mod_vendor_embed.txt
new file mode 100644
index 0000000..1a3b2fe
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_vendor_embed.txt
@@ -0,0 +1,209 @@
+go mod vendor
+cmp vendor/example.com/a/samedir_embed.txt a/samedir_embed.txt
+cmp vendor/example.com/a/subdir/embed.txt a/subdir/embed.txt
+cmp vendor/example.com/a/subdir/test/embed.txt a/subdir/test/embed.txt
+cmp vendor/example.com/a/subdir/test/xtest/embed.txt a/subdir/test/xtest/embed.txt
+
+cd broken_no_matching_files
+! go mod vendor
+stderr 'go: pattern foo.txt: no matching files found'
+
+cd ../broken_bad_pattern
+! go mod vendor
+stderr 'go: pattern ../foo.txt: invalid pattern syntax'
+
+cd ../embed_go122
+go mod vendor
+cmp vendor/example.com/a/samedir_embed.txt ../a/samedir_embed.txt
+cmp vendor/example.com/a/subdir/embed.txt ../a/subdir/embed.txt
+! exists vendor/example.com/a/subdir/test/embed.txt
+! exists vendor/example.com/a/subdir/test/xtest/embed.txt
+-- embed_go122/go.mod --
+module example.com/foo
+go 1.22
+
+require (
+ example.com/a v0.1.0
+)
+
+replace (
+ example.com/a v0.1.0 => ../a
+)
+-- embed_go122/foo.go --
+package main
+
+import (
+ "fmt"
+
+ "example.com/a"
+)
+
+func main() {
+ fmt.Println(a.Str())
+}
+
+# matchPotentialSourceFile prunes out tests and unbuilt code.
+# Make sure that they are vendored if they are embedded files.
+cd ../embed_unbuilt
+go mod vendor
+cmp vendor/example.com/dep/unbuilt.go dep/unbuilt.go
+cmp vendor/example.com/dep/dep_test.go dep/dep_test.go
+! exists vendor/example.com/dep/not_embedded_unbuilt.go
+! exists vendor/example.com/dep/not_embedded_dep_test.go
+-- go.mod --
+module example.com/foo
+go 1.16
+
+require (
+ example.com/a v0.1.0
+)
+
+replace (
+ example.com/a v0.1.0 => ./a
+)
+-- foo.go --
+package main
+
+import (
+ "fmt"
+
+ "example.com/a"
+)
+
+func main() {
+ fmt.Println(a.Str())
+}
+-- a/go.mod --
+module example.com/a
+-- a/a.go --
+package a
+
+import _ "embed"
+
+//go:embed samedir_embed.txt
+var sameDir string
+
+//go:embed subdir/embed.txt
+var subDir string
+
+func Str() string {
+ return sameDir + subDir
+}
+-- a/a_test.go --
+package a
+
+import _ "embed"
+
+//go:embed subdir/test/embed.txt
+var subderTest string
+-- a/a_x_test.go --
+package a_test
+
+import _ "embed"
+
+//go:embed subdir/test/xtest/embed.txt
+var subdirXtest string
+-- a/samedir_embed.txt --
+embedded file in same directory as package
+-- a/subdir/embed.txt --
+embedded file in subdirectory of package
+-- a/subdir/test/embed.txt --
+embedded file of test in subdirectory of package
+-- a/subdir/test/xtest/embed.txt --
+embedded file of xtest in subdirectory of package
+-- broken_no_matching_files/go.mod --
+module example.com/broken
+go 1.16
+
+require (
+ example.com/brokendep v0.1.0
+)
+
+replace (
+ example.com/brokendep v0.1.0 => ./brokendep
+)
+-- broken_no_matching_files/f.go --
+package broken
+
+import _ "example.com/brokendep"
+
+func F() {}
+-- broken_no_matching_files/brokendep/go.mod --
+module example.com/brokendep
+go 1.16
+-- broken_no_matching_files/brokendep/f.go --
+package brokendep
+
+import _ "embed"
+
+//go:embed foo.txt
+var foo string
+-- broken_bad_pattern/go.mod --
+module example.com/broken
+go 1.16
+
+require (
+ example.com/brokendep v0.1.0
+)
+
+replace (
+ example.com/brokendep v0.1.0 => ./brokendep
+)
+-- broken_bad_pattern/f.go --
+package broken
+
+import _ "example.com/brokendep"
+
+func F() {}
+-- broken_bad_pattern/brokendep/go.mod --
+module example.com/brokendep
+go 1.16
+-- broken_bad_pattern/brokendep/f.go --
+package brokendep
+
+import _ "embed"
+
+//go:embed ../foo.txt
+var foo string
+-- embed_unbuilt/go.mod --
+module example.com/foo
+go 1.16
+
+require (
+ example.com/dep v0.1.0
+)
+
+replace (
+ example.com/dep v0.1.0 => ./dep
+)
+-- embed_unbuilt/foo.go --
+package a
+
+import _ "example.com/dep"
+
+func F() {}
+-- embed_unbuilt/dep/go.mod --
+module example.com/dep
+go 1.16
+-- embed_unbuilt/dep/dep.go --
+package dep
+
+import _ "embed"
+
+//go:embed unbuilt.go
+var unbuilt string
+
+//go:embed dep_test.go
+var depTest string
+-- embed_unbuilt/dep/unbuilt.go --
+// +build ignore
+
+package dep
+-- embed_unbuilt/dep/not_embedded_unbuilt.go --
+// +build ignore
+
+package dep
+-- embed_unbuilt/dep/dep_test.go --
+package dep
+-- embed_unbuilt/dep/not_embedded_dep_test.go --
+package dep
diff --git a/src/cmd/go/testdata/script/mod_vendor_gomod.txt b/src/cmd/go/testdata/script/mod_vendor_gomod.txt
new file mode 100644
index 0000000..3f6ea35
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_vendor_gomod.txt
@@ -0,0 +1,38 @@
+# https://golang.org/issue/42970: As of Go 1.17, go.mod and go.sum files should
+# be stripped from vendored dependencies.
+
+go mod vendor
+cd vendor/example.net/x
+go list all
+! stdout '^example.net/m'
+stdout '^example.net/x$'
+exists ./go.sum
+
+cd ../../..
+go mod edit -go=1.17
+go mod vendor
+cd vendor/example.net/x
+go list all
+stdout '^example.net/m$'
+stdout '^example.net/x$'
+! exists ./go.sum
+
+-- go.mod --
+module example.net/m
+
+go 1.16
+
+require example.net/x v0.1.0
+
+replace example.net/x v0.1.0 => ./x
+-- m.go --
+package m
+
+import _ "example.net/x"
+-- x/go.mod --
+module example.net/x
+
+go 1.16
+-- x/go.sum --
+-- x/x.go --
+package x
diff --git a/src/cmd/go/testdata/script/mod_vendor_goversion.txt b/src/cmd/go/testdata/script/mod_vendor_goversion.txt
new file mode 100644
index 0000000..838c557
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_vendor_goversion.txt
@@ -0,0 +1,102 @@
+# https://golang.org/issue/36876: As of Go 1.17, vendor/modules.txt should
+# indicate the language version used by each dependency.
+
+[short] skip
+
+# Control case: without a vendor directory, need117 builds and bad114 doesn't.
+
+go build example.net/need117
+! go build example.net/bad114
+stderr '^bad114[/\\]bad114.go:15:2: duplicate method Y( .*)?$'
+
+
+# With a vendor/modules.txt lacking language versions, the world is topsy-turvy,
+# because we have to guess a uniform version for everything.
+#
+# We always guess Go 1.16, because that was the last version for which
+# 'go mod vendor' failed to record dependency versions, and it has most of
+# the language features added since modules were introduced in Go 1.11.
+#
+# Even so, modules that declare 'go 1.17' and use 1.17 features spuriously fail
+# to build, and modules that declare an older version and use features from a
+# newer one spuriously build (instead of failing as they ought to).
+
+go mod vendor
+
+! grep 1.17 vendor/modules.txt
+! go build example.net/need117
+stderr '^vendor[/\\]example\.net[/\\]need117[/\\]need117.go:5:1[89]:'
+stderr 'conversion of slices to array pointers requires go1\.17 or later'
+
+! grep 1.13 vendor/modules.txt
+go build example.net/bad114
+
+
+# Upgrading the main module to 1.17 adds version annotations.
+# Then everything is once again consistent with the non-vendored world.
+
+go mod edit -go=1.17
+go mod vendor
+
+grep '^## explicit; go 1.17$' vendor/modules.txt
+go build example.net/need117
+
+grep '^## explicit; go 1.13$' vendor/modules.txt
+! go build example.net/bad114
+stderr '^vendor[/\\]example\.net[/\\]bad114[/\\]bad114.go:15:2: duplicate method Y( .+)?$'
+
+-- go.mod --
+module example.net/m
+
+go 1.16
+
+require (
+ example.net/bad114 v0.1.0
+ example.net/need117 v0.1.0
+)
+
+replace (
+ example.net/bad114 v0.1.0 => ./bad114
+ example.net/need117 v0.1.0 => ./need117
+)
+-- m.go --
+package m
+
+import _ "example.net/bad114"
+import _ "example.net/need117"
+
+-- bad114/go.mod --
+// Module bad114 requires Go 1.14 or higher, but declares Go 1.13.
+module example.net/bad114
+
+go 1.13
+-- bad114/bad114.go --
+package bad114
+
+type XY interface {
+ X()
+ Y()
+}
+
+type YZ interface {
+ Y()
+ Z()
+}
+
+type XYZ interface {
+ XY
+ YZ
+}
+
+-- need117/go.mod --
+// Module need117 requires Go 1.17 or higher.
+module example.net/need117
+
+go 1.17
+-- need117/need117.go --
+package need117
+
+func init() {
+ s := make([]byte, 4)
+ _ = (*[4]byte)(s)
+}
diff --git a/src/cmd/go/testdata/script/mod_vendor_issue46867.txt b/src/cmd/go/testdata/script/mod_vendor_issue46867.txt
new file mode 100644
index 0000000..38ae87b
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_vendor_issue46867.txt
@@ -0,0 +1,31 @@
+# Regression test for golang.org/issue/46867:
+# 'go mod vendor' on Windows attempted to open and copy
+# files from directories outside of the module.
+
+cd subdir
+go mod vendor
+! exists vendor/example.net/NOTICE
+exists vendor/example.net/m/NOTICE
+
+-- subdir/go.mod --
+module golang.org/issue46867
+
+go 1.17
+
+replace example.net/m v0.1.0 => ./m
+
+require example.net/m v0.1.0
+-- subdir/issue.go --
+package issue
+
+import _ "example.net/m/n"
+-- subdir/m/go.mod --
+module example.net/m
+
+go 1.17
+-- subdir/m/n/n.go --
+package n
+-- subdir/m/NOTICE --
+This notice is in module m and SHOULD be vendored.
+-- subdir/NOTICE --
+This notice is outside of module m and SHOULD NOT be vendored.
diff --git a/src/cmd/go/testdata/script/mod_vendor_nodeps.txt b/src/cmd/go/testdata/script/mod_vendor_nodeps.txt
new file mode 100644
index 0000000..e9a84ca
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_vendor_nodeps.txt
@@ -0,0 +1,9 @@
+env GO111MODULE=on
+
+go mod vendor
+stderr '^go: no dependencies to vendor'
+
+-- go.mod --
+module x
+-- x.go --
+package x
diff --git a/src/cmd/go/testdata/script/mod_vendor_redundant_requirement.txt b/src/cmd/go/testdata/script/mod_vendor_redundant_requirement.txt
new file mode 100644
index 0000000..3f6f5c5
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_vendor_redundant_requirement.txt
@@ -0,0 +1,29 @@
+# 'go list -mod=vendor' should succeed even when go.mod contains redundant
+# requirements. Verifies #47565.
+go list -mod=vendor
+
+-- go.mod --
+module m
+
+go 1.17
+
+require example.com/m v0.0.0
+require example.com/m v0.0.0
+
+replace example.com/m v0.0.0 => ./m
+-- m/go.mod --
+module example.com/m
+
+go 1.17
+-- m/m.go --
+package m
+-- use.go --
+package use
+
+import _ "example.com/m"
+-- vendor/example.com/m/m.go --
+package m
+-- vendor/modules.txt --
+# example.com/m v0.0.0 => ./m
+## explicit; go 1.17
+example.com/m
diff --git a/src/cmd/go/testdata/script/mod_vendor_replace.txt b/src/cmd/go/testdata/script/mod_vendor_replace.txt
new file mode 100644
index 0000000..c492999
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_vendor_replace.txt
@@ -0,0 +1,89 @@
+env GO111MODULE=on
+
+# Replacement should not use a vendor directory as the target.
+! go mod vendor
+stderr 'replacement path ./vendor/not-rsc.io/quote/v3 inside vendor directory'
+
+cp go.mod1 go.mod
+rm -r vendor
+
+# Before vendoring, we expect to see the original directory.
+go list -f '{{with .Module}}{{.Version}}{{end}} {{.Dir}}' rsc.io/quote/v3
+stdout 'v3.0.0'
+stdout '.*[/\\]not-rsc.io[/\\]quote[/\\]v3'
+
+# Since all dependencies are replaced, 'go mod vendor' should not
+# have to download anything from the network.
+go mod vendor
+! stderr 'downloading'
+! stderr 'finding'
+
+# After vendoring, we expect to see the replacement in the vendor directory,
+# without attempting to look up the non-replaced version.
+cmp vendor/rsc.io/quote/v3/quote.go local/not-rsc.io/quote/v3/quote.go
+
+go list -mod=vendor -f '{{with .Module}}{{.Version}}{{end}} {{.Dir}}' rsc.io/quote/v3
+stdout 'v3.0.0'
+stdout '.*[/\\]vendor[/\\]rsc.io[/\\]quote[/\\]v3'
+! stderr 'finding'
+! stderr 'lookup disabled'
+
+# 'go list' should provide the original replacement directory as the module's
+# replacement path.
+go list -mod=vendor -f '{{with .Module}}{{with .Replace}}{{.Path}}{{end}}{{end}}' rsc.io/quote/v3
+stdout '.*[/\\]not-rsc.io[/\\]quote[/\\]v3'
+
+# The same module can't be used as two different paths.
+cd multiple-paths
+! go mod vendor
+stderr 'rsc.io/quote/v3@v3.0.0 used for two different module paths \(not-rsc.io/quote/v3 and rsc.io/quote/v3\)'
+
+-- go.mod --
+module example.com/replace
+
+require rsc.io/quote/v3 v3.0.0
+replace rsc.io/quote/v3 => ./vendor/not-rsc.io/quote/v3
+
+-- go.mod1 --
+module example.com/replace
+
+require rsc.io/quote/v3 v3.0.0
+replace rsc.io/quote/v3 => ./local/not-rsc.io/quote/v3
+
+-- imports.go --
+package replace
+
+import _ "rsc.io/quote/v3"
+
+-- local/not-rsc.io/quote/v3/go.mod --
+module not-rsc.io/quote/v3
+
+-- local/not-rsc.io/quote/v3/quote.go --
+package quote
+
+-- multiple-paths/main.go --
+package main
+import (
+ "fmt"
+ "rsc.io/quote/v3"
+)
+func main() {
+ fmt.Println(quote.GoV3())
+}
+-- multiple-paths/go.mod --
+module quoter
+require (
+ rsc.io/quote/v3 v3.0.0
+ not-rsc.io/quote/v3 v3.0.0
+)
+replace not-rsc.io/quote/v3 => rsc.io/quote/v3 v3.0.0
+-- multiple-paths/go.sum --
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+rsc.io/quote/v3 v3.0.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+
+-- vendor/not-rsc.io/quote/v3/go.mod --
+module not-rsc.io/quote/v3
+
+-- vendor/not-rsc.io/quote/v3/quote.go --
+package quote
diff --git a/src/cmd/go/testdata/script/mod_vendor_trimpath.txt b/src/cmd/go/testdata/script/mod_vendor_trimpath.txt
new file mode 100644
index 0000000..d9d9d98
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_vendor_trimpath.txt
@@ -0,0 +1,49 @@
+# Check that when -trimpath and -mod=vendor are used together,
+# paths in vendored packages are properly trimmed.
+# Verifies golang.org/issue/36566.
+
+[short] skip
+
+# Only the main module has a root directory in vendor mode.
+go mod vendor
+go list -f {{.Module.Dir}} example.com/main
+stdout $PWD
+go list -f {{.Module.Dir}} example.com/stack
+! stdout .
+
+# The program prints a file name from a vendored package.
+# Without -trimpath, the name should include the vendor directory.
+go run main.go
+stdout vendor
+
+# With -trimpath, everything before the package path should be trimmed.
+# As with -mod=mod, the version should appear as part of the module path.
+go run -mod=vendor -trimpath main.go
+stdout '^example.com/stack@v1.0.0/stack.go$'
+
+# With pristinely vendored source code, a trimmed binary built from vendored
+# code should have the same behavior as one build from the module cache.
+go run -mod=mod -trimpath main.go
+stdout '^example.com/stack@v1.0.0/stack.go$'
+
+-- go.mod --
+module example.com/main
+
+go 1.17
+
+require example.com/stack v1.0.0
+-- go.sum --
+example.com/stack v1.0.0 h1:IEDLeew5NytZ8vrgCF/QVem3H3SR3QMttdu9HfJvk9I=
+example.com/stack v1.0.0/go.mod h1:7wFEbaV5e5O7wJ8aBdqQOR//UXppm/pwnwziMKViuI4=
+-- main.go --
+package main
+
+import (
+ "fmt"
+
+ "example.com/stack"
+)
+
+func main() {
+ fmt.Println(stack.TopFile())
+}
diff --git a/src/cmd/go/testdata/script/mod_vendor_unused.txt b/src/cmd/go/testdata/script/mod_vendor_unused.txt
new file mode 100644
index 0000000..96251bb
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_vendor_unused.txt
@@ -0,0 +1,67 @@
+# Auxiliary test for inclusion of otherwise-unused replacements in
+# vendor/modules.txt for golang.org/issue/33848.
+# We need metadata about replacements in order to verify that modules.txt
+# remains in sync with the main module's go.mod file.
+
+env GO111MODULE=on
+
+go mod vendor
+cmp go1.14-modules.txt vendor/modules.txt
+
+-- go.mod --
+module example.com/foo
+go 1.14
+
+require (
+ example.com/a v0.1.0
+)
+
+replace (
+ example.com/a v0.1.0 => ./a
+ example.com/b v0.1.0 => ./b1
+ example.com/b v0.2.0-unused => ./b2
+ example.com/c => ./c
+ example.com/d v0.1.0 => ./d1
+ example.com/d v0.2.0 => ./d2
+ example.com/e => example.com/e v0.1.0-unused
+)
+-- foo.go --
+package foo
+import _ "example.com/a"
+-- a/go.mod --
+module example.com/a
+require (
+ example.com/b v0.1.0 // indirect
+ example.com/c v0.1.0 // indirect
+)
+-- a/a.go --
+package a
+import _ "example.com/d"
+-- b1/go.mod --
+module example.com/b
+require example.com/d v0.1.0
+-- b2/go.mod --
+module example.com/b
+require example.com/c v0.2.0
+-- c/go.mod --
+module example.com/c
+require example.com/d v0.2.0
+-- d1/go.mod --
+module example.com/d
+-- d1/d1.go --
+package d
+-- d2/go.mod --
+module example.com/d
+-- d2/d2.go --
+package d
+-- go1.14-modules.txt --
+# example.com/a v0.1.0 => ./a
+## explicit
+example.com/a
+# example.com/d v0.2.0 => ./d2
+example.com/d
+# example.com/b v0.1.0 => ./b1
+# example.com/b v0.2.0-unused => ./b2
+# example.com/c => ./c
+# example.com/d v0.1.0 => ./d1
+# example.com/e => example.com/e v0.1.0-unused
diff --git a/src/cmd/go/testdata/script/mod_vendor_unused_only.txt b/src/cmd/go/testdata/script/mod_vendor_unused_only.txt
new file mode 100644
index 0000000..accd9f3
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_vendor_unused_only.txt
@@ -0,0 +1,19 @@
+# Ensure that we generate a vendor/modules.txt file even when the only
+# requirements in go.mod are unused. Regression test for
+# golang.org/issue/36580
+
+env GO111MODULE=on
+
+go mod vendor
+cmp go1.14-modules.txt vendor/modules.txt
+
+-- go.mod --
+module example.com/m
+go 1.14
+
+require example.com v1.0.0 // indirect
+-- go.sum --
+example.com v1.0.0/go.mod h1:WRiieAqDBb1hVdDXLLdxNtCDWNfehn7FWyPC5Oz2vB4=
+-- go1.14-modules.txt --
+# example.com v1.0.0
+## explicit
diff --git a/src/cmd/go/testdata/script/mod_verify.txt b/src/cmd/go/testdata/script/mod_verify.txt
new file mode 100644
index 0000000..018709e
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_verify.txt
@@ -0,0 +1,82 @@
+env GO111MODULE=on
+[short] skip
+
+# With good go.sum, verify succeeds by avoiding download.
+cp go.sum.good go.sum
+go mod verify
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.1.0.zip
+
+# With bad go.sum, verify succeeds by avoiding download.
+cp go.sum.bad go.sum
+go mod verify
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.1.0.zip
+
+# With bad go.sum, sync (which must download) fails.
+rm go.sum
+cp go.sum.bad go.sum
+! go mod tidy
+stderr 'checksum mismatch'
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.1.0.zip
+
+# With good go.sum, sync works.
+rm go.sum
+cp go.sum.good go.sum
+go mod tidy
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.1.0.zip
+exists $GOPATH/pkg/mod/rsc.io/quote@v1.1.0/quote.go
+
+# go.sum should have the new checksum for go.mod
+grep '^rsc.io/quote v1.1.0/go.mod ' go.sum
+
+# verify should work
+go mod verify
+
+# basic loading of module graph should detect incorrect go.mod files.
+go mod graph
+cp go.sum.bad2 go.sum
+! go mod graph
+stderr 'go.mod: checksum mismatch'
+
+# go.sum should be created and updated automatically.
+rm go.sum
+go mod tidy
+grep '^rsc.io/quote v1.1.0/go.mod ' go.sum
+grep '^rsc.io/quote v1.1.0 ' go.sum
+
+# verify should fail on a missing ziphash. tidy should restore it.
+rm $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.1.0.ziphash
+! go mod verify
+stderr '^rsc.io/quote v1.1.0: missing ziphash: open '$GOPATH'[/\\]pkg[/\\]mod[/\\]cache[/\\]download[/\\]rsc.io[/\\]quote[/\\]@v[/\\]v1.1.0.ziphash'
+go mod tidy
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.1.0.ziphash
+go mod verify
+
+# Packages below module root should not be mentioned in go.sum.
+rm go.sum
+go mod edit -droprequire rsc.io/quote
+go get rsc.io/quote/buggy
+grep '^rsc.io/quote v1.5.2/go.mod ' go.sum
+! grep buggy go.sum
+
+# non-existent packages below module root should not be mentioned in go.sum
+go mod edit -droprequire rsc.io/quote
+! go list rsc.io/quote/morebuggy
+grep '^rsc.io/quote v1.5.2/go.mod ' go.sum
+! grep buggy go.sum
+
+-- go.mod --
+module x
+require rsc.io/quote v1.1.0
+
+-- x.go --
+package x
+import _ "rsc.io/quote"
+
+-- go.sum.good --
+rsc.io/quote v1.1.0 h1:a3YaZoizPtXyv6ZsJ74oo2L4/bwOSTKMY7MAyo4O/0c=
+
+-- go.sum.bad --
+rsc.io/quote v1.1.0 h1:a3YaZoizPtXyv6ZsJ74oo2L4/bwOSTKMY7MAyo4O/1c=
+
+-- go.sum.bad2 --
+rsc.io/quote v1.1.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl1=
diff --git a/src/cmd/go/testdata/script/mod_verify_work.txt b/src/cmd/go/testdata/script/mod_verify_work.txt
new file mode 100644
index 0000000..d9f5a54
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_verify_work.txt
@@ -0,0 +1,24 @@
+# Regression test for Issue #62663: we would filter out the toolchain and
+# main modules from the build list incorrectly, leading to the workspace
+# modules being checked for correct sums. Specifically this would happen when
+# the module name sorted after the virtual 'go' version module name because
+# it could not get chopped off when we removed the MainModules.Len() modules
+# at the beginning of the build list and we would remove the go module instead.
+
+go mod verify
+
+-- go.work --
+go 1.21
+
+use (
+ ./a
+ ./b
+)
+-- a/go.mod --
+module hexample.com/a // important for test that module name sorts after 'go'
+
+go 1.21
+-- b/go.mod --
+module hexample.com/b // important for test that module name sorts after 'go'
+
+go 1.21 \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/mod_versions.txt b/src/cmd/go/testdata/script/mod_versions.txt
new file mode 100644
index 0000000..aaa4216
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_versions.txt
@@ -0,0 +1,14 @@
+# Test rejection of pkg@version in GOPATH mode.
+env GO111MODULE=off
+! go get rsc.io/quote@v1.5.1
+stderr '^go: modules disabled by GO111MODULE=off'
+! go build rsc.io/quote@v1.5.1
+stderr '^package rsc.io/quote@v1.5.1: can only use path@version syntax with ''go get'' and ''go install'' in module-aware mode$'
+
+env GO111MODULE=on
+cd x
+! go build rsc.io/quote@v1.5.1
+stderr '^package rsc.io/quote@v1.5.1: can only use path@version syntax with ''go get'' and ''go install'' in module-aware mode$'
+
+-- x/go.mod --
+module x
diff --git a/src/cmd/go/testdata/script/mod_why.txt b/src/cmd/go/testdata/script/mod_why.txt
new file mode 100644
index 0000000..b3036fa
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_why.txt
@@ -0,0 +1,130 @@
+env GO111MODULE=on
+[short] skip
+
+# Populate go.sum.
+go mod tidy
+cp go.mod go.mod.orig
+
+go list -test all
+stdout rsc.io/quote
+stdout golang.org/x/text/language
+
+# why a package?
+go mod why golang.org/x/text/language
+cmp stdout why-language.txt
+
+# why a module?
+go mod why -m golang.org...
+cmp stdout why-text-module.txt
+
+# why a package used only in tests?
+go mod why rsc.io/testonly
+cmp stdout why-testonly.txt
+
+# why a module used only in a test of a dependency?
+go mod why -m rsc.io/testonly
+cmp stdout why-testonly.txt
+
+# test package not needed
+go mod why golang.org/x/text/unused
+cmp stdout why-unused.txt
+
+# vendor doesn't use packages used only in tests.
+go mod why -vendor rsc.io/testonly
+cmp stdout why-vendor.txt
+
+# vendor doesn't use modules used only in tests.
+go mod why -vendor -m rsc.io/testonly
+cmp stdout why-vendor-module.txt
+
+# test multiple packages
+go mod why golang.org/x/text/language golang.org/x/text/unused
+cmp stdout why-both.txt
+
+# test multiple modules
+go mod why -m rsc.io/quote rsc.io/sampler
+cmp stdout why-both-module.txt
+
+# package in a module that isn't even in the module graph
+# (https://golang.org/issue/26977)
+go mod why rsc.io/fortune
+cmp stdout why-missing.txt
+
+# None of these command should have changed the go.mod file.
+cmp go.mod go.mod.orig
+
+-- go.mod --
+module mymodule
+require rsc.io/quote v1.5.2
+
+-- x/x.go --
+package x
+import _ "mymodule/z"
+
+-- y/y.go --
+package y
+
+-- y/y_test.go --
+package y
+import _ "rsc.io/quote"
+
+-- z/z.go --
+package z
+import _ "mymodule/y"
+
+
+-- why-language.txt --
+# golang.org/x/text/language
+mymodule/y
+mymodule/y.test
+rsc.io/quote
+rsc.io/sampler
+golang.org/x/text/language
+-- why-unused.txt --
+# golang.org/x/text/unused
+(main module does not need package golang.org/x/text/unused)
+-- why-text-module.txt --
+# golang.org/x/text
+mymodule/y
+mymodule/y.test
+rsc.io/quote
+rsc.io/sampler
+golang.org/x/text/language
+-- why-testonly.txt --
+# rsc.io/testonly
+mymodule/y
+mymodule/y.test
+rsc.io/quote
+rsc.io/sampler
+rsc.io/sampler.test
+rsc.io/testonly
+-- why-vendor.txt --
+# rsc.io/testonly
+(main module does not need to vendor package rsc.io/testonly)
+-- why-vendor-module.txt --
+# rsc.io/testonly
+(main module does not need to vendor module rsc.io/testonly)
+-- why-both.txt --
+# golang.org/x/text/language
+mymodule/y
+mymodule/y.test
+rsc.io/quote
+rsc.io/sampler
+golang.org/x/text/language
+
+# golang.org/x/text/unused
+(main module does not need package golang.org/x/text/unused)
+-- why-both-module.txt --
+# rsc.io/quote
+mymodule/y
+mymodule/y.test
+rsc.io/quote
+
+# rsc.io/sampler
+mymodule/y
+mymodule/y.test
+rsc.io/quote
+rsc.io/sampler
+-- why-missing.txt --
+# rsc.io/fortune
+(main module does not need package rsc.io/fortune)
diff --git a/src/cmd/go/testdata/script/modfile_flag.txt b/src/cmd/go/testdata/script/modfile_flag.txt
new file mode 100644
index 0000000..6d28759
--- /dev/null
+++ b/src/cmd/go/testdata/script/modfile_flag.txt
@@ -0,0 +1,98 @@
+# Tests the behavior of the -modfile flag in commands that support it.
+# The go.mod file exists but should not be read or written.
+# Same with go.sum.
+
+env GOFLAGS=-modfile=go.alt.mod
+cp go.mod go.mod.orig
+cp go.sum go.sum.orig
+
+
+# go mod init should create a new file, even though go.mod already exists.
+go mod init example.com/m
+grep example.com/m go.alt.mod
+
+# 'go env GOMOD' should print the path to the real file.
+# 'go env' does not recognize the '-modfile' flag.
+go env GOMOD
+stdout '^'$WORK${/}gopath${/}src${/}'go\.mod$'
+
+# 'go list -m' should print the effective go.mod file as GoMod though.
+go list -m -f '{{.GoMod}}'
+stdout '^go.alt.mod$'
+
+# go mod edit should operate on the alternate file
+go mod edit -require rsc.io/quote@v1.5.2
+grep rsc.io/quote go.alt.mod
+
+# 'go list -m' should add sums to the alternate go.sum.
+go list -m -mod=mod all
+grep '^rsc.io/quote v1.5.2/go.mod ' go.alt.sum
+! grep '^rsc.io/quote v1.5.2 ' go.alt.sum
+
+# other 'go mod' commands should work. 'go mod vendor' is tested later.
+go mod download rsc.io/quote
+go mod graph
+stdout rsc.io/quote
+go mod tidy
+grep rsc.io/quote go.alt.sum
+go mod verify
+go mod why rsc.io/quote
+
+
+# 'go list' and other commands with build flags should work.
+# They should update the alternate go.mod when a dependency is missing.
+go mod edit -droprequire rsc.io/quote
+go list -mod=mod .
+grep rsc.io/quote go.alt.mod
+go build -n -mod=mod .
+go test -n -mod=mod .
+go get rsc.io/quote
+
+
+# 'go mod vendor' should work.
+go mod vendor
+exists vendor
+
+# Automatic vendoring should be broken by editing an explicit requirement
+# in the alternate go.mod file.
+go mod edit -require rsc.io/quote@v1.5.1
+! go list .
+go list -mod=mod
+rm vendor
+
+
+# 'go generate' should use the alternate file when resolving packages.
+# Recursive go commands started with 'go generate' should not get an explicitly
+# passed -modfile, but they should see arguments from GOFLAGS.
+cp go.alt.mod go.gen.mod
+env OLD_GOFLAGS=$GOFLAGS
+env GOFLAGS=-modfile=go.gen.mod
+go generate -modfile=go.alt.mod .
+env GOFLAGS=$OLD_GOFLAGS
+grep example.com/exclude go.gen.mod
+! grep example.com/exclude go.alt.mod
+
+
+# The original files should not have been modified.
+cmp go.mod go.mod.orig
+cmp go.sum go.sum.orig
+
+
+# If the alternate mod file does not have a ".mod" suffix, an error
+# should be reported.
+cp go.alt.mod goaltmod
+! go mod tidy -modfile=goaltmod
+stderr '-modfile=goaltmod: file does not have .mod extension'
+
+-- go.mod --
+ʕ◔ϖ◔ʔ
+-- go.sum --
+ʕ◔ϖ◔ʔ
+-- use.go --
+package main
+
+import _ "rsc.io/quote"
+-- gen.go --
+//go:generate go mod edit -exclude example.com/exclude@v1.0.0
+
+package main
diff --git a/src/cmd/go/testdata/script/noncanonical_import.txt b/src/cmd/go/testdata/script/noncanonical_import.txt
new file mode 100644
index 0000000..018cb01
--- /dev/null
+++ b/src/cmd/go/testdata/script/noncanonical_import.txt
@@ -0,0 +1,19 @@
+env GO111MODULE=off
+
+! go build canonical/d
+stderr '^canonical[/\\]b[/\\]b.go:3:8: non-canonical import path "canonical/a/": should be "canonical/a"$'
+
+-- canonical/a/a.go --
+package a
+
+import _ "c"
+-- canonical/b/b.go --
+package b
+
+import _ "canonical/a/"
+-- canonical/a/vendor/c/c.go --
+package c
+-- canonical/d/d.go --
+package d
+
+import _ "canonical/b"
diff --git a/src/cmd/go/testdata/script/old_tidy_toolchain.txt b/src/cmd/go/testdata/script/old_tidy_toolchain.txt
new file mode 100644
index 0000000..d4b5af2
--- /dev/null
+++ b/src/cmd/go/testdata/script/old_tidy_toolchain.txt
@@ -0,0 +1,28 @@
+# Commands in an old module with no go line and no toolchain line,
+# or with only a go line, should succeed.
+# (They should not fail due to the go.mod not being tidy.)
+
+# No go line, no toolchain line.
+go list
+
+# Old go line, no toolchain line.
+go mod edit -go=1.16
+go list
+
+go mod edit -go=1.20
+go list
+
+# New go line, no toolchain line, using same toolchain.
+env TESTGO_VERSION=1.21
+go mod edit -go=1.21
+go list
+
+# New go line, no toolchain line, using newer Go version.
+# (Until we need to update the go line, no toolchain addition.)
+env TESTGO_VERSION=1.21.0
+go list
+
+-- go.mod --
+module m
+-- p.go --
+package p
diff --git a/src/cmd/go/testdata/script/pattern_syntax_error.txt b/src/cmd/go/testdata/script/pattern_syntax_error.txt
new file mode 100644
index 0000000..9a1f5e5
--- /dev/null
+++ b/src/cmd/go/testdata/script/pattern_syntax_error.txt
@@ -0,0 +1,12 @@
+env GO111MODULE=off
+
+# patterns match directories with syntax errors
+! go list ./...
+! go build ./...
+! go install ./...
+
+-- mypkg/x.go --
+package mypkg
+
+-- mypkg/y.go --
+pkg mypackage
diff --git a/src/cmd/go/testdata/script/prevent_sys_unix_import.txt b/src/cmd/go/testdata/script/prevent_sys_unix_import.txt
new file mode 100644
index 0000000..ea1ad78
--- /dev/null
+++ b/src/cmd/go/testdata/script/prevent_sys_unix_import.txt
@@ -0,0 +1,6 @@
+# Policy decision: we shouldn't vendor golang.org/x/sys/unix in std
+# See https://golang.org/issue/32102
+
+env GO111MODULE=on
+go list std
+! stdout vendor/golang.org/x/sys/unix
diff --git a/src/cmd/go/testdata/script/repro_build.txt b/src/cmd/go/testdata/script/repro_build.txt
new file mode 100644
index 0000000..7c6e317
--- /dev/null
+++ b/src/cmd/go/testdata/script/repro_build.txt
@@ -0,0 +1,22 @@
+# Check that goroutine scheduling does not affect compiler output.
+# If it does, reproducible builds will not work very well.
+[short] skip
+[GOOS:aix] env CGO_ENABLED=0 # go.dev/issue/56896
+env GOMAXPROCS=16
+go build -a -o http16.o net/http
+env GOMAXPROCS=17
+go build -a -o http17.o net/http
+cmp -q http16.o http17.o
+env GOMAXPROCS=18
+go build -a -o http18.o net/http
+cmp -q http16.o http18.o
+
+# Check that goroutine scheduling does not affect linker output.
+env GOMAXPROCS=16
+go build -a -o gofmt16.exe cmd/gofmt
+env GOMAXPROCS=17
+go build -a -o gofmt17.exe cmd/gofmt
+cmp -q gofmt16.exe gofmt17.exe
+env GOMAXPROCS=18
+go build -a -o gofmt18.exe cmd/gofmt
+cmp -q gofmt16.exe gofmt18.exe
diff --git a/src/cmd/go/testdata/script/reuse_git.txt b/src/cmd/go/testdata/script/reuse_git.txt
new file mode 100644
index 0000000..432f5a9
--- /dev/null
+++ b/src/cmd/go/testdata/script/reuse_git.txt
@@ -0,0 +1,376 @@
+[short] skip
+[!git] skip
+
+env GO111MODULE=on
+env GOPROXY=direct
+env GOSUMDB=off
+
+# go mod download with the pseudo-version should invoke git but not have a TagSum or Ref.
+go mod download -x -json vcs-test.golang.org/git/hello.git@v0.0.0-20170922010558-fc3a09f3dc5c
+stderr 'git fetch'
+cp stdout hellopseudo.json
+! stdout '"(Query|TagPrefix|TagSum|Ref)"'
+stdout '"Version": "v0.0.0-20170922010558-fc3a09f3dc5c"'
+stdout '"VCS": "git"'
+stdout '"URL": ".*/git/hello"'
+stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"'
+go clean -modcache
+
+# go mod download vcstest/hello should invoke git, print origin info
+go mod download -x -json vcs-test.golang.org/git/hello.git@latest
+stderr 'git fetch'
+cp stdout hello.json
+stdout '"Version": "v0.0.0-20170922010558-fc3a09f3dc5c"'
+stdout '"VCS": "git"'
+stdout '"URL": ".*/git/hello"'
+stdout '"Query": "latest"'
+! stdout '"TagPrefix"'
+stdout '"TagSum": "t1:47DEQpj8HBSa[+]/TImW[+]5JCeuQeRkm5NMpJWZG3hSuFU="'
+stdout '"Ref": "HEAD"'
+stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"'
+
+# pseudo-version again should not invoke git fetch (it has the version from the @latest query)
+# but still be careful not to include a TagSum or a Ref, especially not Ref set to HEAD,
+# which is easy to do when reusing the cached version from the @latest query.
+go mod download -x -json vcs-test.golang.org/git/hello.git@v0.0.0-20170922010558-fc3a09f3dc5c
+! stderr 'git fetch'
+cp stdout hellopseudo2.json
+cmpenv hellopseudo.json hellopseudo2.json
+
+# go mod download vcstest/hello@hash needs to check TagSum to find pseudoversion base.
+go mod download -x -json vcs-test.golang.org/git/hello.git@fc3a09f3dc5c
+! stderr 'git fetch'
+cp stdout hellohash.json
+stdout '"Version": "v0.0.0-20170922010558-fc3a09f3dc5c"'
+stdout '"Query": "fc3a09f3dc5c"'
+stdout '"VCS": "git"'
+stdout '"URL": ".*/git/hello"'
+stdout '"TagSum": "t1:47DEQpj8HBSa[+]/TImW[+]5JCeuQeRkm5NMpJWZG3hSuFU="'
+stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"'
+
+# go mod download vcstest/hello/v9 should fail, still print origin info
+! go mod download -x -json vcs-test.golang.org/git/hello.git/v9@latest
+cp stdout hellov9.json
+stdout '"Version": "latest"'
+stdout '"Error":.*no matching versions'
+! stdout '"TagPrefix"'
+stdout '"TagSum": "t1:47DEQpj8HBSa[+]/TImW[+]5JCeuQeRkm5NMpJWZG3hSuFU="'
+stdout '"Ref": "HEAD"'
+stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"'
+! stdout 'RepoSum'
+
+# go mod download vcstest/hello/sub/v9 should also fail, print origin info with TagPrefix
+! go mod download -x -json vcs-test.golang.org/git/hello.git/sub/v9@latest
+cp stdout hellosubv9.json
+stdout '"Version": "latest"'
+stdout '"Error":.*no matching versions'
+stdout '"TagPrefix": "sub/"'
+stdout '"TagSum": "t1:47DEQpj8HBSa[+]/TImW[+]5JCeuQeRkm5NMpJWZG3hSuFU="'
+stdout '"Ref": "HEAD"'
+stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"'
+! stdout 'RepoSum'
+
+# go mod download vcstest/hello@nonexist should fail, still print origin info
+! go mod download -x -json vcs-test.golang.org/git/hello.git@nonexist
+cp stdout hellononexist.json
+stdout '"Version": "nonexist"'
+stdout '"Error":.*unknown revision nonexist'
+stdout '"RepoSum": "r1:c0/9JCZ25lxoBiK3[+]3BhACU4giH49flcJmBynJ[+]Jvmc="'
+! stdout '"(TagPrefix|TagSum|Ref|Hash)"'
+
+# go mod download vcstest/hello@1234567890123456789012345678901234567890 should fail, still print origin info
+# (40 hex digits is assumed to be a full hash and is a slightly different code path from @nonexist)
+! go mod download -x -json vcs-test.golang.org/git/hello.git@1234567890123456789012345678901234567890
+cp stdout hellononhash.json
+stdout '"Version": "1234567890123456789012345678901234567890"'
+stdout '"Error":.*unknown revision 1234567890123456789012345678901234567890'
+stdout '"RepoSum": "r1:c0/9JCZ25lxoBiK3[+]3BhACU4giH49flcJmBynJ[+]Jvmc="'
+! stdout '"(TagPrefix|TagSum|Ref|Hash)"'
+
+# go mod download vcstest/hello@v0.0.0-20220101120101-123456789abc should fail, still print origin info
+# (non-existent pseudoversion)
+! go mod download -x -json vcs-test.golang.org/git/hello.git@v0.0.0-20220101120101-123456789abc
+cp stdout hellononpseudo.json
+stdout '"Version": "v0.0.0-20220101120101-123456789abc"'
+stdout '"Error":.*unknown revision 123456789abc'
+stdout '"RepoSum": "r1:c0/9JCZ25lxoBiK3[+]3BhACU4giH49flcJmBynJ[+]Jvmc="'
+! stdout '"(TagPrefix|TagSum|Ref|Hash)"'
+
+# go mod download vcstest/tagtests should invoke git, print origin info
+go mod download -x -json vcs-test.golang.org/git/tagtests.git@latest
+stderr 'git fetch'
+cp stdout tagtests.json
+stdout '"Version": "v0.2.2"'
+stdout '"Query": "latest"'
+stdout '"VCS": "git"'
+stdout '"URL": ".*/git/tagtests"'
+! stdout '"TagPrefix"'
+stdout '"TagSum": "t1:Dp7yRKDuE8WjG0429PN9hYWjqhy2te7P9Oki/sMEOGo="'
+stdout '"Ref": "refs/tags/v0.2.2"'
+stdout '"Hash": "59356c8cd18c5fe9a598167d98a6843e52d57952"'
+
+# go mod download vcstest/tagtests@v0.2.2 should print origin info, no TagSum needed
+go mod download -x -json vcs-test.golang.org/git/tagtests.git@v0.2.2
+cp stdout tagtestsv022.json
+stdout '"Version": "v0.2.2"'
+! stdout '"Query":'
+stdout '"VCS": "git"'
+stdout '"URL": ".*/git/tagtests"'
+! stdout '"TagPrefix"'
+! stdout '"TagSum"'
+stdout '"Ref": "refs/tags/v0.2.2"'
+stdout '"Hash": "59356c8cd18c5fe9a598167d98a6843e52d57952"'
+
+# go mod download vcstest/tagtests@master needs a TagSum again
+go mod download -x -json vcs-test.golang.org/git/tagtests.git@master
+cp stdout tagtestsmaster.json
+stdout '"Version": "v0.2.3-0.20190509225625-c7818c24fa2f"'
+stdout '"Query": "master"'
+stdout '"VCS": "git"'
+stdout '"URL": ".*/git/tagtests"'
+! stdout '"TagPrefix"'
+stdout '"TagSum": "t1:Dp7yRKDuE8WjG0429PN9hYWjqhy2te7P9Oki/sMEOGo="'
+stdout '"Ref": "refs/heads/master"'
+stdout '"Hash": "c7818c24fa2f3f714c67d0a6d3e411c85a518d1f"'
+
+# go mod download vcstest/prefixtagtests should invoke git, print origin info
+go mod download -x -json vcs-test.golang.org/git/prefixtagtests.git/sub@latest
+stderr 'git fetch'
+cp stdout prefixtagtests.json
+stdout '"Version": "v0.0.10"'
+stdout '"Query": "latest"'
+stdout '"VCS": "git"'
+stdout '"URL": ".*/git/prefixtagtests"'
+stdout '"Subdir": "sub"'
+stdout '"TagPrefix": "sub/"'
+stdout '"TagSum": "t1:YGSbWkJ8dn9ORAr[+]BlKHFK/2ZhXLb9hVuYfTZ9D8C7g="'
+stdout '"Ref": "refs/tags/sub/v0.0.10"'
+stdout '"Hash": "2b7c4692e12c109263cab51b416fcc835ddd7eae"'
+
+# go mod download of a bunch of these should fail (some are invalid) but write good JSON for later
+! go mod download -json vcs-test.golang.org/git/hello.git@latest vcs-test.golang.org/git/hello.git/v9@latest vcs-test.golang.org/git/hello.git/sub/v9@latest vcs-test.golang.org/git/tagtests.git@latest vcs-test.golang.org/git/tagtests.git@v0.2.2 vcs-test.golang.org/git/tagtests.git@master
+cp stdout all.json
+
+# clean the module cache, make sure that makes go mod download re-run git fetch, clean again
+go clean -modcache
+go mod download -x -json vcs-test.golang.org/git/hello.git@latest
+stderr 'git fetch'
+go clean -modcache
+
+# reuse go mod download vcstest/hello result
+go mod download -reuse=hello.json -x -json vcs-test.golang.org/git/hello.git@latest
+! stderr 'git fetch'
+stdout '"Reuse": true'
+stdout '"Version": "v0.0.0-20170922010558-fc3a09f3dc5c"'
+stdout '"VCS": "git"'
+stdout '"URL": ".*/git/hello"'
+! stdout '"TagPrefix"'
+stdout '"TagSum": "t1:47DEQpj8HBSa[+]/TImW[+]5JCeuQeRkm5NMpJWZG3hSuFU="'
+stdout '"Ref": "HEAD"'
+stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"'
+! stdout '"Dir"'
+! stdout '"Info"'
+! stdout '"GoMod"'
+! stdout '"Zip"'
+
+# reuse go mod download vcstest/hello pseudoversion result
+go mod download -reuse=hellopseudo.json -x -json vcs-test.golang.org/git/hello.git@v0.0.0-20170922010558-fc3a09f3dc5c
+! stderr 'git fetch'
+stdout '"Reuse": true'
+stdout '"Version": "v0.0.0-20170922010558-fc3a09f3dc5c"'
+stdout '"VCS": "git"'
+stdout '"URL": ".*/git/hello"'
+! stdout '"(Query|TagPrefix|TagSum|Ref)"'
+stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"'
+! stdout '"(Dir|Info|GoMod|Zip)"'
+
+# reuse go mod download vcstest/hello@hash
+go mod download -reuse=hellohash.json -x -json vcs-test.golang.org/git/hello.git@fc3a09f3dc5c
+! stderr 'git fetch'
+stdout '"Reuse": true'
+stdout '"Query": "fc3a09f3dc5c"'
+stdout '"Version": "v0.0.0-20170922010558-fc3a09f3dc5c"'
+stdout '"VCS": "git"'
+stdout '"URL": ".*/git/hello"'
+! stdout '"(TagPrefix|Ref)"'
+stdout '"TagSum": "t1:47DEQpj8HBSa[+]/TImW[+]5JCeuQeRkm5NMpJWZG3hSuFU="'
+stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"'
+! stdout '"(Dir|Info|GoMod|Zip)"'
+
+# reuse go mod download vcstest/hello/v9 error result
+! go mod download -reuse=hellov9.json -x -json vcs-test.golang.org/git/hello.git/v9@latest
+! stderr 'git fetch'
+stdout '"Reuse": true'
+stdout '"Error":.*no matching versions'
+! stdout '"TagPrefix"'
+stdout '"TagSum": "t1:47DEQpj8HBSa[+]/TImW[+]5JCeuQeRkm5NMpJWZG3hSuFU="'
+stdout '"Ref": "HEAD"'
+stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"'
+! stdout '"(Dir|Info|GoMod|Zip)"'
+
+# reuse go mod download vcstest/hello/sub/v9 error result
+! go mod download -reuse=hellosubv9.json -x -json vcs-test.golang.org/git/hello.git/sub/v9@latest
+! stderr 'git fetch'
+stdout '"Reuse": true'
+stdout '"Error":.*no matching versions'
+stdout '"TagPrefix": "sub/"'
+stdout '"TagSum": "t1:47DEQpj8HBSa[+]/TImW[+]5JCeuQeRkm5NMpJWZG3hSuFU="'
+stdout '"Ref": "HEAD"'
+stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"'
+! stdout '"(Dir|Info|GoMod|Zip)"'
+
+# reuse go mod download vcstest/hello@nonexist
+! go mod download -reuse=hellononexist.json -x -json vcs-test.golang.org/git/hello.git@nonexist
+! stderr 'git fetch'
+stdout '"Reuse": true'
+stdout '"Version": "nonexist"'
+stdout '"Error":.*unknown revision nonexist'
+stdout '"RepoSum": "r1:c0/9JCZ25lxoBiK3[+]3BhACU4giH49flcJmBynJ[+]Jvmc="'
+! stdout '"(TagPrefix|TagSum|Ref|Hash)"'
+! stdout '"(Dir|Info|GoMod|Zip)"'
+
+# reuse go mod download vcstest/hello@1234567890123456789012345678901234567890
+! go mod download -reuse=hellononhash.json -x -json vcs-test.golang.org/git/hello.git@1234567890123456789012345678901234567890
+! stderr 'git fetch'
+stdout '"Reuse": true'
+stdout '"Version": "1234567890123456789012345678901234567890"'
+stdout '"Error":.*unknown revision 1234567890123456789012345678901234567890'
+stdout '"RepoSum": "r1:c0/9JCZ25lxoBiK3[+]3BhACU4giH49flcJmBynJ[+]Jvmc="'
+! stdout '"(TagPrefix|TagSum|Ref|Hash)"'
+! stdout '"(Dir|Info|GoMod|Zip)"'
+
+# reuse go mod download vcstest/hello@v0.0.0-20220101120101-123456789abc
+! go mod download -reuse=hellononpseudo.json -x -json vcs-test.golang.org/git/hello.git@v0.0.0-20220101120101-123456789abc
+! stderr 'git fetch'
+stdout '"Reuse": true'
+stdout '"Version": "v0.0.0-20220101120101-123456789abc"'
+stdout '"Error":.*unknown revision 123456789abc'
+stdout '"RepoSum": "r1:c0/9JCZ25lxoBiK3[+]3BhACU4giH49flcJmBynJ[+]Jvmc="'
+! stdout '"(TagPrefix|TagSum|Ref|Hash)"'
+! stdout '"(Dir|Info|GoMod|Zip)"'
+
+# reuse go mod download vcstest/tagtests result
+go mod download -reuse=tagtests.json -x -json vcs-test.golang.org/git/tagtests.git@latest
+! stderr 'git fetch'
+stdout '"Reuse": true'
+stdout '"Version": "v0.2.2"'
+stdout '"Query": "latest"'
+stdout '"VCS": "git"'
+stdout '"URL": ".*/git/tagtests"'
+! stdout '"TagPrefix"'
+stdout '"TagSum": "t1:Dp7yRKDuE8WjG0429PN9hYWjqhy2te7P9Oki/sMEOGo="'
+stdout '"Ref": "refs/tags/v0.2.2"'
+stdout '"Hash": "59356c8cd18c5fe9a598167d98a6843e52d57952"'
+! stdout '"(Dir|Info|GoMod|Zip)"'
+
+# reuse go mod download vcstest/tagtests@v0.2.2 result
+go mod download -reuse=tagtestsv022.json -x -json vcs-test.golang.org/git/tagtests.git@v0.2.2
+! stderr 'git fetch'
+stdout '"Reuse": true'
+stdout '"Version": "v0.2.2"'
+! stdout '"Query":'
+stdout '"VCS": "git"'
+stdout '"URL": ".*/git/tagtests"'
+! stdout '"TagPrefix"'
+! stdout '"TagSum"'
+stdout '"Ref": "refs/tags/v0.2.2"'
+stdout '"Hash": "59356c8cd18c5fe9a598167d98a6843e52d57952"'
+! stdout '"(Dir|Info|GoMod|Zip)"'
+
+# reuse go mod download vcstest/tagtests@master result
+go mod download -reuse=tagtestsmaster.json -x -json vcs-test.golang.org/git/tagtests.git@master
+! stderr 'git fetch'
+stdout '"Reuse": true'
+stdout '"Version": "v0.2.3-0.20190509225625-c7818c24fa2f"'
+stdout '"Query": "master"'
+stdout '"VCS": "git"'
+stdout '"URL": ".*/git/tagtests"'
+! stdout '"TagPrefix"'
+stdout '"TagSum": "t1:Dp7yRKDuE8WjG0429PN9hYWjqhy2te7P9Oki/sMEOGo="'
+stdout '"Ref": "refs/heads/master"'
+stdout '"Hash": "c7818c24fa2f3f714c67d0a6d3e411c85a518d1f"'
+! stdout '"(Dir|Info|GoMod|Zip)"'
+
+# reuse go mod download vcstest/tagtests@master result again with all.json
+go mod download -reuse=all.json -x -json vcs-test.golang.org/git/tagtests.git@master
+! stderr 'git fetch'
+stdout '"Reuse": true'
+stdout '"Version": "v0.2.3-0.20190509225625-c7818c24fa2f"'
+stdout '"Query": "master"'
+stdout '"VCS": "git"'
+stdout '"URL": ".*/git/tagtests"'
+! stdout '"TagPrefix"'
+stdout '"TagSum": "t1:Dp7yRKDuE8WjG0429PN9hYWjqhy2te7P9Oki/sMEOGo="'
+stdout '"Ref": "refs/heads/master"'
+stdout '"Hash": "c7818c24fa2f3f714c67d0a6d3e411c85a518d1f"'
+! stdout '"(Dir|Info|GoMod|Zip)"'
+
+# go mod download vcstest/prefixtagtests result with json
+go mod download -reuse=prefixtagtests.json -x -json vcs-test.golang.org/git/prefixtagtests.git/sub@latest
+! stderr 'git fetch'
+stdout '"Version": "v0.0.10"'
+stdout '"Query": "latest"'
+stdout '"VCS": "git"'
+stdout '"URL": ".*/git/prefixtagtests"'
+stdout '"Subdir": "sub"'
+stdout '"TagPrefix": "sub/"'
+stdout '"TagSum": "t1:YGSbWkJ8dn9ORAr[+]BlKHFK/2ZhXLb9hVuYfTZ9D8C7g="'
+stdout '"Ref": "refs/tags/sub/v0.0.10"'
+stdout '"Hash": "2b7c4692e12c109263cab51b416fcc835ddd7eae"'
+! stdout '"(Dir|Info|GoMod|Zip)"'
+
+# reuse the bulk results with all.json
+! go mod download -reuse=all.json -json vcs-test.golang.org/git/hello.git@latest vcs-test.golang.org/git/hello.git/v9@latest vcs-test.golang.org/git/hello.git/sub/v9@latest vcs-test.golang.org/git/tagtests.git@latest vcs-test.golang.org/git/tagtests.git@v0.2.2 vcs-test.golang.org/git/tagtests.git@master
+! stderr 'git fetch'
+stdout '"Reuse": true'
+! stdout '"(Dir|Info|GoMod|Zip)"'
+
+# reuse attempt with stale hash should reinvoke git, not report reuse
+cp tagtestsv022.json tagtestsv022badhash.json
+replace '57952' '56952XXX' tagtestsv022badhash.json
+go mod download -reuse=tagtestsv022badhash.json -x -json vcs-test.golang.org/git/tagtests.git@v0.2.2
+stderr 'git fetch'
+! stdout '"Reuse": true'
+stdout '"Version": "v0.2.2"'
+! stdout '"Query"'
+stdout '"VCS": "git"'
+stdout '"URL": ".*/git/tagtests"'
+! stdout '"(TagPrefix|TagSum)"'
+stdout '"Ref": "refs/tags/v0.2.2"'
+stdout '"Hash": "59356c8cd18c5fe9a598167d98a6843e52d57952"'
+stdout '"Dir"'
+stdout '"Info"'
+stdout '"GoMod"'
+stdout '"Zip"'
+
+# reuse with stale repo URL
+cp tagtestsv022.json tagtestsv022badurl.json
+replace 'git/tagtests\"' 'git/tagtestsXXX\"' tagtestsv022badurl.json
+go mod download -reuse=tagtestsv022badurl.json -x -json vcs-test.golang.org/git/tagtests.git@v0.2.2
+! stdout '"Reuse": true'
+stdout '"URL": ".*/git/tagtests"'
+stdout '"Dir"'
+stdout '"Info"'
+stdout '"GoMod"'
+stdout '"Zip"'
+
+# reuse with stale VCS
+cp tagtestsv022.json tagtestsv022badvcs.json
+replace '\"git\"' '\"gitXXX\"' tagtestsv022badvcs.json
+go mod download -reuse=tagtestsv022badvcs.json -x -json vcs-test.golang.org/git/tagtests.git@v0.2.2
+! stdout '"Reuse": true'
+stdout '"URL": ".*/git/tagtests"'
+
+# reuse with stale Dir
+cp tagtestsv022.json tagtestsv022baddir.json
+replace '\t\t\"Ref\":' '\t\t\"Subdir\": \"subdir\",\n\t\t\"Ref\":' tagtestsv022baddir.json
+go mod download -reuse=tagtestsv022baddir.json -x -json vcs-test.golang.org/git/tagtests.git@v0.2.2
+! stdout '"Reuse": true'
+stdout '"URL": ".*/git/tagtests"'
+
+# reuse with stale TagSum
+cp tagtests.json tagtestsbadtagsum.json
+replace 'sMEOGo=' 'sMEoGo=XXX' tagtestsbadtagsum.json
+go mod download -reuse=tagtestsbadtagsum.json -x -json vcs-test.golang.org/git/tagtests.git@latest
+! stdout '"Reuse": true'
+stdout '"TagSum": "t1:Dp7yRKDuE8WjG0429PN9hYWjqhy2te7P9Oki/sMEOGo="'
diff --git a/src/cmd/go/testdata/script/run_dirs.txt b/src/cmd/go/testdata/script/run_dirs.txt
new file mode 100644
index 0000000..bd5cfbe
--- /dev/null
+++ b/src/cmd/go/testdata/script/run_dirs.txt
@@ -0,0 +1,21 @@
+cd rundir
+
+! go run x.go sub/sub.go
+stderr 'named files must all be in one directory; have . and sub'
+! go run sub/sub.go x.go
+stderr 'named files must all be in one directory; have sub and .'
+
+cd ../
+go run rundir/foo.go ./rundir/bar.go
+stderr 'hello world'
+
+-- rundir/sub/sub.go --
+package main
+-- rundir/x.go --
+package main
+-- rundir/foo.go --
+package main
+func main() { println(msg) }
+-- rundir/bar.go --
+package main
+const msg = "hello world"
diff --git a/src/cmd/go/testdata/script/run_hello.txt b/src/cmd/go/testdata/script/run_hello.txt
new file mode 100644
index 0000000..939b661
--- /dev/null
+++ b/src/cmd/go/testdata/script/run_hello.txt
@@ -0,0 +1,9 @@
+env GO111MODULE=off
+
+# hello world
+go run hello.go
+stderr 'hello world'
+
+-- hello.go --
+package main
+func main() { println("hello world") }
diff --git a/src/cmd/go/testdata/script/run_hello_pkg.txt b/src/cmd/go/testdata/script/run_hello_pkg.txt
new file mode 100644
index 0000000..ea2b4d7
--- /dev/null
+++ b/src/cmd/go/testdata/script/run_hello_pkg.txt
@@ -0,0 +1,17 @@
+go run m/hello
+stderr 'hello, world'
+
+cd hello
+go run .
+stderr 'hello, world'
+
+-- go.mod --
+module m
+
+go 1.16
+-- hello/hello.go --
+package main
+
+func main() {
+ println("hello, world")
+}
diff --git a/src/cmd/go/testdata/script/run_internal.txt b/src/cmd/go/testdata/script/run_internal.txt
new file mode 100644
index 0000000..d021850
--- /dev/null
+++ b/src/cmd/go/testdata/script/run_internal.txt
@@ -0,0 +1,64 @@
+env GO111MODULE=off
+
+go list -e -f '{{.Incomplete}}' m/runbad1.go
+stdout true
+! go run m/runbad1.go
+stderr 'use of internal package m/x/internal not allowed'
+
+go list -e -f '{{.Incomplete}}' m/runbad2.go
+stdout true
+! go run m/runbad2.go
+stderr 'use of internal package m/x/internal/y not allowed'
+
+go list -e -f '{{.Incomplete}}' m/runok.go
+stdout false
+go run m/runok.go
+
+cd m
+env GO111MODULE=on
+
+go list -e -f '{{.Incomplete}}' runbad1.go
+stdout true
+! go run runbad1.go
+stderr 'use of internal package m/x/internal not allowed'
+
+go list -e -f '{{.Incomplete}}' runbad2.go
+stdout true
+! go run runbad2.go
+stderr 'use of internal package m/x/internal/y not allowed'
+
+go list -e -f '{{.Incomplete}}' runok.go
+stdout false
+go run runok.go
+
+
+-- m/go.mod --
+module m
+
+-- m/x/internal/internal.go --
+package internal
+
+-- m/x/internal/y/y.go --
+package y
+
+-- m/internal/internal.go --
+package internal
+
+-- m/internal/z/z.go --
+package z
+
+-- m/runbad1.go --
+package main
+import _ "m/x/internal"
+func main() {}
+
+-- m/runbad2.go --
+package main
+import _ "m/x/internal/y"
+func main() {}
+
+-- m/runok.go --
+package main
+import _ "m/internal"
+import _ "m/internal/z"
+func main() {}
diff --git a/src/cmd/go/testdata/script/run_issue11709.txt b/src/cmd/go/testdata/script/run_issue11709.txt
new file mode 100644
index 0000000..c8ba998
--- /dev/null
+++ b/src/cmd/go/testdata/script/run_issue11709.txt
@@ -0,0 +1,15 @@
+# 'go run' should not pass extraneous environment variables to the subprocess.
+go run run.go
+! stdout .
+! stderr .
+
+-- run.go --
+package main
+
+import "os"
+
+func main() {
+ if os.Getenv("TERM") != "" {
+ os.Exit(1)
+ }
+} \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/run_issue51125.txt b/src/cmd/go/testdata/script/run_issue51125.txt
new file mode 100644
index 0000000..8fa4486
--- /dev/null
+++ b/src/cmd/go/testdata/script/run_issue51125.txt
@@ -0,0 +1,54 @@
+# Regression test for https://go.dev/issue/51125:
+# Relative import paths (a holdover from GOPATH) were accidentally allowed in module mode.
+
+cd $WORK
+
+# Relative imports should not be allowed with a go.mod file.
+
+! go run driver.go
+stderr '^driver.go:3:8: "./mypkg" is relative, but relative import paths are not supported in module mode$'
+
+go list -e -f '{{with .Error}}{{.}}{{end}}' -deps driver.go
+stdout '^driver.go:3:8: "./mypkg" is relative, but relative import paths are not supported in module mode$'
+! stderr .
+
+
+# Relative imports should not be allowed in module mode even without a go.mod file.
+rm go.mod
+
+! go run driver.go
+stderr '^driver.go:3:8: "./mypkg" is relative, but relative import paths are not supported in module mode$'
+
+go list -e -f '{{with .Error}}{{.}}{{end}}' -deps driver.go
+stdout '^driver.go:3:8: "./mypkg" is relative, but relative import paths are not supported in module mode$'
+! stderr .
+
+
+# In GOPATH mode, they're still allowed (but only outside of GOPATH/src).
+env GO111MODULE=off
+
+[!short] go run driver.go
+
+go list -deps driver.go
+
+
+-- $WORK/go.mod --
+module example
+
+go 1.17
+-- $WORK/driver.go --
+package main
+
+import "./mypkg"
+
+func main() {
+ mypkg.MyFunc()
+}
+-- $WORK/mypkg/code.go --
+package mypkg
+
+import "fmt"
+
+func MyFunc() {
+ fmt.Println("Hello, world!")
+}
diff --git a/src/cmd/go/testdata/script/run_set_executable_name.txt b/src/cmd/go/testdata/script/run_set_executable_name.txt
new file mode 100644
index 0000000..54ddee9
--- /dev/null
+++ b/src/cmd/go/testdata/script/run_set_executable_name.txt
@@ -0,0 +1,50 @@
+env GO111MODULE=on
+[short] skip
+
+# Check for correct naming of temporary executable
+
+#Test for single file specified
+cd x/y/z
+go run foo.go
+stderr 'foo'
+
+#Test for current directory
+go run .
+stderr 'z'
+
+#Test for set path
+go run m/x/y/z/
+stderr 'z'
+
+-- m/x/y/z/foo.go --
+package main
+import(
+ "os"
+ "path/filepath"
+)
+func main() {
+ println(filepath.Base(os.Args[0]))
+}
+
+-- x/y/z/foo.go --
+package main
+import(
+ "os"
+ "path/filepath"
+)
+func main() {
+ println(filepath.Base(os.Args[0]))
+}
+
+-- x/y/z/foo.go --
+package main
+import(
+ "os"
+ "path/filepath"
+)
+func main() {
+ println(filepath.Base(os.Args[0]))
+}
+
+-- go.mod --
+module m \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/run_vendor.txt b/src/cmd/go/testdata/script/run_vendor.txt
new file mode 100644
index 0000000..46cac06
--- /dev/null
+++ b/src/cmd/go/testdata/script/run_vendor.txt
@@ -0,0 +1,34 @@
+# Run
+env GO111MODULE=off
+cd vend/hello
+go run hello.go
+stdout 'hello, world'
+
+-- vend/hello/hello.go --
+package main
+
+import (
+ "fmt"
+ "strings" // really ../vendor/strings
+)
+
+func main() {
+ fmt.Printf("%s\n", strings.Msg)
+}
+-- vend/hello/hello_test.go --
+package main
+
+import (
+ "strings" // really ../vendor/strings
+ "testing"
+)
+
+func TestMsgInternal(t *testing.T) {
+ if strings.Msg != "hello, world" {
+ t.Fatalf("unexpected msg: %v", strings.Msg)
+ }
+}
+-- vend/vendor/strings/msg.go --
+package strings
+
+var Msg = "hello, world"
diff --git a/src/cmd/go/testdata/script/run_wildcard.txt b/src/cmd/go/testdata/script/run_wildcard.txt
new file mode 100644
index 0000000..3e7e7b7
--- /dev/null
+++ b/src/cmd/go/testdata/script/run_wildcard.txt
@@ -0,0 +1,7 @@
+env GO111MODULE=off
+
+# Fix for https://github.com/golang/go/issues/28696:
+# go run x/... should not panic when directory x doesn't exist.
+
+! go run nonexistent/...
+stderr '^go: no packages loaded from nonexistent/...$'
diff --git a/src/cmd/go/testdata/script/run_work_versioned.txt b/src/cmd/go/testdata/script/run_work_versioned.txt
new file mode 100644
index 0000000..eb0f22d
--- /dev/null
+++ b/src/cmd/go/testdata/script/run_work_versioned.txt
@@ -0,0 +1,16 @@
+[short] skip
+go run example.com/printversion@v0.1.0
+stdout '^main is example.com/printversion v0.1.0$'
+
+-- go.work --
+go 1.18
+
+use (
+ .
+)
+-- go.mod --
+module example
+
+go 1.18
+
+require example.com/printversion v1.0.0
diff --git a/src/cmd/go/testdata/script/script_help.txt b/src/cmd/go/testdata/script/script_help.txt
new file mode 100644
index 0000000..dd7f203
--- /dev/null
+++ b/src/cmd/go/testdata/script/script_help.txt
@@ -0,0 +1,7 @@
+help -v
+
+# To see help for a specific command or condition, run 'help' for it here.
+# For example:
+help wait
+help [verbose]
+help [exec:bash]
diff --git a/src/cmd/go/testdata/script/script_wait.txt b/src/cmd/go/testdata/script/script_wait.txt
new file mode 100644
index 0000000..f253060
--- /dev/null
+++ b/src/cmd/go/testdata/script/script_wait.txt
@@ -0,0 +1,28 @@
+env GO111MODULE=off
+
+[!exec:echo] skip
+[!exec:false] skip
+
+exec echo foo
+stdout foo
+
+exec echo foo &
+exec echo bar &
+! exec false &
+
+# Starting a background process should clear previous output.
+! stdout foo
+
+# Wait should set the output to the concatenated outputs of the background
+# programs, in the order in which they were started.
+wait
+stdout 'foo\nbar'
+
+# The end of the test should interrupt or kill any remaining background
+# programs, but that should not cause the test to fail if it does not
+# care about the exit status of those programs.
+[exec:sleep] ? exec sleep 86400 &
+
+# It should also cancel any backgrounded builtins that respond to Context
+# cancellation.
+? sleep 86400s &
diff --git a/src/cmd/go/testdata/script/slashpath.txt b/src/cmd/go/testdata/script/slashpath.txt
new file mode 100644
index 0000000..22b3e9d
--- /dev/null
+++ b/src/cmd/go/testdata/script/slashpath.txt
@@ -0,0 +1,18 @@
+# .a files should use slash-separated paths even on windows
+# This is important for reproducing native builds with cross-compiled builds.
+go build -o x.a text/template
+! grep 'GOROOT\\' x.a
+! grep 'text\\template' x.a
+! grep 'c:\\' x.a
+
+# executables should use slash-separated paths even on windows
+# This is important for reproducing native builds with cross-compiled builds.
+go build -o hello.exe hello.go
+! grep 'GOROOT\\' hello.exe
+! grep '\\runtime' hello.exe
+! grep 'runtime\\' hello.exe
+! grep 'gofile..[A-Za-z]:\\' hello.exe
+
+-- hello.go --
+package main
+func main() { println("hello") }
diff --git a/src/cmd/go/testdata/script/src_file.txt b/src/cmd/go/testdata/script/src_file.txt
new file mode 100644
index 0000000..8d5c20b
--- /dev/null
+++ b/src/cmd/go/testdata/script/src_file.txt
@@ -0,0 +1,9 @@
+# Files in src should not be treated as packages
+
+exists $GOROOT/src/regexp/testdata/README
+go list -f '{{.Dir}}' regexp/testdata/README
+
+-- go.mod --
+module regexp/testdata/README
+-- p.go --
+package p
diff --git a/src/cmd/go/testdata/script/std_vendor.txt b/src/cmd/go/testdata/script/std_vendor.txt
new file mode 100644
index 0000000..731ee9e
--- /dev/null
+++ b/src/cmd/go/testdata/script/std_vendor.txt
@@ -0,0 +1,43 @@
+env GO111MODULE=off
+
+[!compiler:gc] skip
+
+# 'go list' should report imports from _test.go in the TestImports field.
+go list -f '{{.TestImports}}'
+stdout net/http # from .TestImports
+
+# 'go list' should report standard-vendored packages by path.
+go list -f '{{.Dir}}' vendor/golang.org/x/net/http2/hpack
+stdout $GOROOT[/\\]src[/\\]vendor
+
+# 'go list -test' should report vendored transitive dependencies of _test.go
+# imports in the Deps field, with a 'vendor' prefix on their import paths.
+go list -test -f '{{.Deps}}'
+stdout golang.org/x/crypto # dep of .TestImports
+
+# Packages outside the standard library should not use its copy of vendored packages.
+cd broken
+! go build
+stderr 'cannot find package'
+
+-- go.mod --
+module m
+
+-- x.go --
+package x
+
+-- x_test.go --
+package x
+import "testing"
+import _ "net/http"
+func Test(t *testing.T) {}
+
+-- broken/go.mod --
+module broken
+-- broken/http.go --
+package broken
+
+import (
+ _ "net/http"
+ _ "golang.org/x/net/http/httpproxy"
+)
diff --git a/src/cmd/go/testdata/script/test2json_interrupt.txt b/src/cmd/go/testdata/script/test2json_interrupt.txt
new file mode 100644
index 0000000..763c336
--- /dev/null
+++ b/src/cmd/go/testdata/script/test2json_interrupt.txt
@@ -0,0 +1,58 @@
+[short] skip 'links and runs a test binary'
+[!fuzz] skip 'tests SIGINT behavior for interrupting fuzz tests'
+[GOOS:windows] skip 'windows does not support os.Interrupt'
+
+? go test -json -fuzz FuzzInterrupt -run '^$' -parallel 1
+stdout -count=1 '"Action":"pass","Package":"example","Test":"FuzzInterrupt"'
+stdout -count=1 '"Action":"pass","Package":"example","Elapsed":'
+
+mkdir $WORK/fuzzcache
+go test -c . -fuzz=. -o example_test.exe
+? go tool test2json -p example -t ./example_test.exe -test.v -test.paniconexit0 -test.fuzzcachedir $WORK/fuzzcache -test.fuzz FuzzInterrupt -test.run '^$' -test.parallel 1
+stdout -count=1 '"Action":"pass","Package":"example","Test":"FuzzInterrupt"'
+stdout -count=1 '"Action":"pass","Package":"example","Elapsed":'
+
+-- go.mod --
+module example
+go 1.20
+-- example_test.go --
+package example_test
+
+import (
+ "fmt"
+ "os"
+ "strconv"
+ "testing"
+ "strings"
+ "time"
+)
+
+func FuzzInterrupt(f *testing.F) {
+ pids := os.Getenv("GO_TEST_INTERRUPT_PIDS")
+ if pids == "" {
+ // This is the main test process.
+ // Set the environment variable for fuzz workers.
+ pid := os.Getpid()
+ ppid := os.Getppid()
+ os.Setenv("GO_TEST_INTERRUPT_PIDS", fmt.Sprintf("%d,%d", ppid, pid))
+ }
+
+ sentInterrupt := false
+ f.Fuzz(func(t *testing.T, orig string) {
+ if !sentInterrupt {
+ // Simulate a ctrl-C on the keyboard by sending SIGINT
+ // to the main test process and its parent.
+ for _, pid := range strings.Split(pids, ",") {
+ i, err := strconv.Atoi(pid)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if p, err := os.FindProcess(i); err == nil {
+ p.Signal(os.Interrupt)
+ sentInterrupt = true // Only send interrupts once.
+ }
+ }
+ }
+ time.Sleep(1 * time.Millisecond) // Delay the fuzzer a bit to avoid wasting CPU.
+ })
+}
diff --git a/src/cmd/go/testdata/script/test_android_issue62123.txt b/src/cmd/go/testdata/script/test_android_issue62123.txt
new file mode 100644
index 0000000..2f46a6b
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_android_issue62123.txt
@@ -0,0 +1,19 @@
+env GOOS=android GOARCH=amd64 CGO_ENABLED=0
+
+! go build -o $devnull cmd/buildid
+stderr 'android/amd64 requires external \(cgo\) linking, but cgo is not enabled'
+! stderr 'cannot find runtime/cgo'
+
+! go test -c -o $devnull os
+stderr '# os\nandroid/amd64 requires external \(cgo\) linking, but cgo is not enabled'
+! stderr 'cannot find runtime/cgo'
+
+env GOOS=ios GOARCH=arm64 CGO_ENABLED=0
+
+! go build -o $devnull cmd/buildid
+stderr 'ios/arm64 requires external \(cgo\) linking, but cgo is not enabled'
+! stderr 'cannot find runtime/cgo'
+
+! go test -c -o $devnull os
+stderr '# os\nios/arm64 requires external \(cgo\) linking, but cgo is not enabled'
+! stderr 'cannot find runtime/cgo'
diff --git a/src/cmd/go/testdata/script/test_bad_example.txt b/src/cmd/go/testdata/script/test_bad_example.txt
new file mode 100644
index 0000000..1d147b6
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_bad_example.txt
@@ -0,0 +1,13 @@
+# Tests that invalid examples are ignored.
+# Verifies golang.org/issue/35284
+go test x_test.go
+
+-- x_test.go --
+package x
+
+import "fmt"
+
+func ExampleThisShouldNotHaveAParameter(thisShouldntExist int) {
+ fmt.Println("X")
+ // Output:
+} \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/test_badtest.txt b/src/cmd/go/testdata/script/test_badtest.txt
new file mode 100644
index 0000000..e79fc51
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_badtest.txt
@@ -0,0 +1,49 @@
+env GO111MODULE=off
+
+! go test badtest/badexec
+! stdout ^ok
+stdout ^FAIL\tbadtest/badexec
+
+! go test badtest/badsyntax
+! stdout ^ok
+stdout ^FAIL\tbadtest/badsyntax
+
+! go test badtest/badvar
+! stdout ^ok
+stdout ^FAIL\tbadtest/badvar
+
+! go test notest
+! stdout ^ok
+stderr '^notest.hello.go:6:1: syntax error: non-declaration statement outside function body' # Exercise issue #7108
+
+-- badtest/badexec/x_test.go --
+package badexec
+
+func init() {
+ panic("badexec")
+}
+
+-- badtest/badsyntax/x.go --
+package badsyntax
+
+-- badtest/badsyntax/x_test.go --
+package badsyntax
+
+func func func func func!
+
+-- badtest/badvar/x.go --
+package badvar
+
+-- badtest/badvar/x_test.go --
+package badvar_test
+
+func f() {
+ _ = notdefined
+}
+-- notest/hello.go --
+package notest
+
+func hello() {
+ println("hello world")
+}
+Hello world \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/test_benchmark_1x.txt b/src/cmd/go/testdata/script/test_benchmark_1x.txt
new file mode 100644
index 0000000..b1d4c39
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_benchmark_1x.txt
@@ -0,0 +1,37 @@
+# Test that -benchtime 1x only runs a total of 1 loop iteration.
+# See golang.org/issue/32051.
+
+go test -run ^$ -bench . -benchtime 1x
+
+-- go.mod --
+module bench
+
+go 1.16
+-- x_test.go --
+package bench
+
+import (
+ "fmt"
+ "os"
+ "testing"
+)
+
+var called = false
+
+func TestMain(m *testing.M) {
+ m.Run()
+ if !called {
+ fmt.Println("benchmark never called")
+ os.Exit(1)
+ }
+}
+
+func Benchmark(b *testing.B) {
+ if b.N > 1 {
+ b.Fatalf("called with b.N=%d; want b.N=1 only", b.N)
+ }
+ if called {
+ b.Fatal("called twice")
+ }
+ called = true
+}
diff --git a/src/cmd/go/testdata/script/test_benchmark_chatty_fail.txt b/src/cmd/go/testdata/script/test_benchmark_chatty_fail.txt
new file mode 100644
index 0000000..6031ead
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_benchmark_chatty_fail.txt
@@ -0,0 +1,32 @@
+# Run chatty tests. Assert on CONT lines.
+! go test chatty_test.go -v -bench . chatty_bench
+
+# Sanity check that output occurs.
+stdout -count=2 'this is sub-0'
+stdout -count=2 'this is sub-1'
+stdout -count=2 'this is sub-2'
+stdout -count=1 'error from sub-0'
+stdout -count=1 'error from sub-1'
+stdout -count=1 'error from sub-2'
+
+# Benchmarks should not print CONT.
+! stdout CONT
+
+-- chatty_test.go --
+package chatty_bench
+
+import (
+ "testing"
+ "fmt"
+)
+
+func BenchmarkChatty(b *testing.B) {
+ for i := 0; i < 3; i++ {
+ b.Run(fmt.Sprintf("sub-%d", i), func(b *testing.B) {
+ for j := 0; j < 2; j++ {
+ b.Logf("this is sub-%d", i)
+ }
+ b.Errorf("error from sub-%d", i)
+ })
+ }
+} \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/test_benchmark_chatty_success.txt b/src/cmd/go/testdata/script/test_benchmark_chatty_success.txt
new file mode 100644
index 0000000..a1c0d65
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_benchmark_chatty_success.txt
@@ -0,0 +1,29 @@
+# Run chatty tests. Assert on CONT lines.
+go test chatty_test.go -v -bench . chatty_bench
+
+# Sanity check that output happens. We don't provide -count because the amount
+# of output is variable.
+stdout 'this is sub-0'
+stdout 'this is sub-1'
+stdout 'this is sub-2'
+
+# Benchmarks should not print CONT.
+! stdout CONT
+
+-- chatty_test.go --
+package chatty_bench
+
+import (
+ "testing"
+ "fmt"
+)
+
+func BenchmarkChatty(b *testing.B) {
+ for i := 0; i < 3; i++ {
+ b.Run(fmt.Sprintf("sub-%d", i), func(b *testing.B) {
+ for j := 0; j < 2; j++ {
+ b.Logf("this is sub-%d", i)
+ }
+ })
+ }
+} \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/test_benchmark_fatal.txt b/src/cmd/go/testdata/script/test_benchmark_fatal.txt
new file mode 100644
index 0000000..e281379
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_benchmark_fatal.txt
@@ -0,0 +1,19 @@
+# Test that calling t.Fatal in a benchmark causes a non-zero exit status.
+
+! go test -run '^$' -bench . benchfatal
+! stdout ^ok
+! stderr ^ok
+stdout FAIL.*benchfatal
+
+-- go.mod --
+module benchfatal
+
+go 1.16
+-- x_test.go --
+package benchfatal
+
+import "testing"
+
+func BenchmarkThatCallsFatal(b *testing.B) {
+ b.Fatal("called by benchmark")
+}
diff --git a/src/cmd/go/testdata/script/test_benchmark_labels.txt b/src/cmd/go/testdata/script/test_benchmark_labels.txt
new file mode 100644
index 0000000..6b424c1
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_benchmark_labels.txt
@@ -0,0 +1,23 @@
+# Tests that go test -bench prints out goos, goarch, and pkg.
+
+# Check for goos, goarch, and pkg.
+go test -run ^$ -bench . bench
+stdout '^goos: '$GOOS
+stdout '^goarch: '$GOARCH
+stdout '^pkg: bench'
+
+# Check go test does not print pkg multiple times
+! stdout 'pkg:.*pkg: '
+! stderr 'pkg:.*pkg:'
+
+-- go.mod --
+module bench
+
+go 1.16
+-- x_test.go --
+package bench
+
+import "testing"
+
+func Benchmark(b *testing.B) {
+}
diff --git a/src/cmd/go/testdata/script/test_benchmark_timeout.txt b/src/cmd/go/testdata/script/test_benchmark_timeout.txt
new file mode 100644
index 0000000..4bae7e7
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_benchmark_timeout.txt
@@ -0,0 +1,18 @@
+# Tests issue #18845
+[short] skip
+
+go test -bench . -timeout=750ms timeoutbench_test.go
+stdout ok
+stdout PASS
+
+-- timeoutbench_test.go --
+package timeoutbench_test
+
+import (
+ "testing"
+ "time"
+)
+
+func BenchmarkSleep1s(b *testing.B) {
+ time.Sleep(1 * time.Second)
+}
diff --git a/src/cmd/go/testdata/script/test_build_failure.txt b/src/cmd/go/testdata/script/test_build_failure.txt
new file mode 100644
index 0000000..e8c984f
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_build_failure.txt
@@ -0,0 +1,31 @@
+[short] skip
+
+! go test -x coverbad
+! stderr '[\\/]coverbad\.test( |$)' # 'go test' should not claim to have run the test.
+stderr 'undefined: g'
+[cgo] stderr 'undefined: j'
+
+-- go.mod --
+module coverbad
+
+go 1.16
+-- p.go --
+package p
+
+func f() {
+ g()
+}
+-- p1.go --
+package p
+
+import "C"
+
+func h() {
+ j()
+}
+-- p_test.go --
+package p
+
+import "testing"
+
+func Test(t *testing.T) {}
diff --git a/src/cmd/go/testdata/script/test_buildvcs.txt b/src/cmd/go/testdata/script/test_buildvcs.txt
new file mode 100644
index 0000000..db844f8
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_buildvcs.txt
@@ -0,0 +1,104 @@
+# https://go.dev/issue/51723: 'go test' should not stamp VCS metadata
+# in the build settings. (It isn't worth the latency hit, given that
+# test binaries are almost never distributed to users.)
+
+[short] skip
+[!git] skip
+
+exec git init
+
+# The test binaries should not have VCS settings stamped by default.
+# (The test itself verifies that.)
+go test . ./testonly
+
+# However, setting -buildvcs explicitly should override that and
+# stamp anyway (https://go.dev/issue/52648).
+go test -buildvcs -c -o ./testonly.exe ./testonly
+! exec ./testonly.exe
+stdout 'unexpected VCS setting: vcs\.modified=true'
+
+
+# Remove 'git' from $PATH. The test should still build.
+# This ensures that we aren't loading VCS metadata that
+# we subsequently throw away.
+env PATH=''
+env path=''
+
+# Compiling the test should not require the VCS tool.
+go test -c -o $devnull .
+
+
+# When listing a main package, in general we need its VCS metadata to determine
+# the .Stale and .StaleReason fields.
+! go list -buildvcs=true .
+stderr '^go: missing Git command\. See https://golang\.org/s/gogetcmd\nerror obtaining VCS status: .*\n\tUse -buildvcs=false to disable VCS stamping.'
+
+# Adding the -test flag should be strictly additive — it should not suppress the error.
+! go list -buildvcs=true -test .
+stderr '^go: missing Git command\. See https://golang\.org/s/gogetcmd\nerror obtaining VCS status: .*\n\tUse -buildvcs=false to disable VCS stamping.'
+
+# Adding the suggested flag should suppress the error.
+go list -test -buildvcs=false .
+! stderr .
+
+
+# Since the ./testonly package doesn't itself produce an actual binary, we shouldn't
+# invoke a VCS tool to compute a build stamp by default when listing it.
+go list ./testonly
+! stderr .
+go list -test ./testonly
+! stderr .
+
+# Again, setting -buildvcs explicitly should force the use of the VCS tool.
+! go list -buildvcs ./testonly
+stderr '^go: missing Git command\. See https://golang\.org/s/gogetcmd\nerror obtaining VCS status: .*\n\tUse -buildvcs=false to disable VCS stamping.'
+! go list -buildvcs -test ./testonly
+stderr '^go: missing Git command\. See https://golang\.org/s/gogetcmd\nerror obtaining VCS status: .*\n\tUse -buildvcs=false to disable VCS stamping.'
+
+
+-- go.mod --
+module example
+
+go 1.18
+-- example.go --
+package main
+-- example_test.go --
+package main
+
+import (
+ "runtime/debug"
+ "strings"
+ "testing"
+)
+
+func TestDetail(t *testing.T) {
+ bi, ok := debug.ReadBuildInfo()
+ if !ok {
+ t.Fatal("BuildInfo not present")
+ }
+ for _, s := range bi.Settings {
+ if strings.HasPrefix(s.Key, "vcs.") {
+ t.Fatalf("unexpected VCS setting: %s=%s", s.Key, s.Value)
+ }
+ }
+}
+-- testonly/main_test.go --
+package main
+
+import (
+ "runtime/debug"
+ "strings"
+ "testing"
+)
+
+func TestDetail(t *testing.T) {
+ bi, ok := debug.ReadBuildInfo()
+ if !ok {
+ t.Fatal("BuildInfo not present")
+ }
+ for _, s := range bi.Settings {
+ if strings.HasPrefix(s.Key, "vcs.") {
+ t.Fatalf("unexpected VCS setting: %s=%s", s.Key, s.Value)
+ }
+ }
+}
diff --git a/src/cmd/go/testdata/script/test_cache_inputs.txt b/src/cmd/go/testdata/script/test_cache_inputs.txt
new file mode 100644
index 0000000..3705c70
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_cache_inputs.txt
@@ -0,0 +1,270 @@
+env GO111MODULE=off
+
+# Test that cached test results are invalidated in response to
+# changes to the external inputs to the test.
+
+[short] skip
+[GODEBUG:gocacheverify=1] skip
+
+# We're testing cache behavior, so start with a clean GOCACHE.
+env GOCACHE=$WORK/cache
+
+# Build a helper binary to invoke os.Chtimes.
+go build -o mkold$GOEXE mkold.go
+
+# Make test input files appear to be a minute old.
+exec ./mkold$GOEXE 1m testcache/file.txt
+exec ./mkold$GOEXE 1m testcache/script.sh
+
+# If the test reads an environment variable, changes to that variable
+# should invalidate cached test results.
+env TESTKEY=x
+go test testcache -run=TestLookupEnv
+go test testcache -run=TestLookupEnv
+stdout '\(cached\)'
+
+env TESTKEY=y
+go test testcache -run=TestLookupEnv
+! stdout '\(cached\)'
+go test testcache -run=TestLookupEnv
+stdout '\(cached\)'
+
+# Changes in arguments forwarded to the test should invalidate cached test
+# results.
+go test testcache -run=TestOSArgs -v hello
+! stdout '\(cached\)'
+stdout 'hello'
+go test testcache -run=TestOSArgs -v goodbye
+! stdout '\(cached\)'
+stdout 'goodbye'
+
+# golang.org/issue/36134: that includes the `-timeout` argument.
+go test testcache -run=TestOSArgs -timeout=20m -v
+! stdout '\(cached\)'
+stdout '-test\.timeout[= ]20m'
+go test testcache -run=TestOSArgs -timeout=5s -v
+! stdout '\(cached\)'
+stdout '-test\.timeout[= ]5s'
+
+# If the test stats a file, changes to the file should invalidate the cache.
+go test testcache -run=FileSize
+go test testcache -run=FileSize
+stdout '\(cached\)'
+
+cp 4x.txt testcache/file.txt
+go test testcache -run=FileSize
+! stdout '\(cached\)'
+go test testcache -run=FileSize
+stdout '\(cached\)'
+
+# Files should be tracked even if the test changes its working directory.
+go test testcache -run=Chdir
+go test testcache -run=Chdir
+stdout '\(cached\)'
+cp 6x.txt testcache/file.txt
+go test testcache -run=Chdir
+! stdout '\(cached\)'
+go test testcache -run=Chdir
+stdout '\(cached\)'
+
+# The content of files should affect caching, provided that the mtime also changes.
+exec ./mkold$GOEXE 1m testcache/file.txt
+go test testcache -run=FileContent
+go test testcache -run=FileContent
+stdout '\(cached\)'
+cp 2y.txt testcache/file.txt
+exec ./mkold$GOEXE 50s testcache/file.txt
+go test testcache -run=FileContent
+! stdout '\(cached\)'
+go test testcache -run=FileContent
+stdout '\(cached\)'
+
+# Directory contents read via os.ReadDirNames should affect caching.
+go test testcache -run=DirList
+go test testcache -run=DirList
+stdout '\(cached\)'
+rm testcache/file.txt
+go test testcache -run=DirList
+! stdout '\(cached\)'
+go test testcache -run=DirList
+stdout '\(cached\)'
+
+# Files outside GOROOT and GOPATH should not affect caching.
+env TEST_EXTERNAL_FILE=$WORK/external.txt
+go test testcache -run=ExternalFile
+go test testcache -run=ExternalFile
+stdout '\(cached\)'
+
+rm $WORK/external.txt
+go test testcache -run=ExternalFile
+stdout '\(cached\)'
+
+# The -benchtime flag without -bench should not affect caching.
+go test testcache -run=Benchtime -benchtime=1x
+go test testcache -run=Benchtime -benchtime=1x
+stdout '\(cached\)'
+
+go test testcache -run=Benchtime -bench=Benchtime -benchtime=1x
+go test testcache -run=Benchtime -bench=Benchtime -benchtime=1x
+! stdout '\(cached\)'
+
+# golang.org/issue/47355: that includes the `-failfast` argument.
+go test testcache -run=TestOSArgs -failfast
+! stdout '\(cached\)'
+go test testcache -run=TestOSArgs -failfast
+stdout '\(cached\)'
+
+# Executables within GOROOT and GOPATH should affect caching,
+# even if the test does not stat them explicitly.
+
+[!exec:/bin/sh] skip
+chmod 0755 ./testcache/script.sh
+
+exec ./mkold$GOEXEC 1m testcache/script.sh
+go test testcache -run=Exec
+go test testcache -run=Exec
+stdout '\(cached\)'
+
+exec ./mkold$GOEXE 50s testcache/script.sh
+go test testcache -run=Exec
+! stdout '\(cached\)'
+go test testcache -run=Exec
+stdout '\(cached\)'
+
+-- testcache/file.txt --
+xx
+-- 4x.txt --
+xxxx
+-- 6x.txt --
+xxxxxx
+-- 2y.txt --
+yy
+-- $WORK/external.txt --
+This file is outside of GOPATH.
+-- testcache/script.sh --
+#!/bin/sh
+exit 0
+-- testcache/testcache_test.go --
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package testcache
+
+import (
+ "io"
+ "os"
+ "testing"
+)
+
+func TestChdir(t *testing.T) {
+ os.Chdir("..")
+ defer os.Chdir("testcache")
+ info, err := os.Stat("testcache/file.txt")
+ if err != nil {
+ t.Fatal(err)
+ }
+ if info.Size()%2 != 1 {
+ t.Fatal("even file")
+ }
+}
+
+func TestOddFileContent(t *testing.T) {
+ f, err := os.Open("file.txt")
+ if err != nil {
+ t.Fatal(err)
+ }
+ data, err := io.ReadAll(f)
+ f.Close()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(data)%2 != 1 {
+ t.Fatal("even file")
+ }
+}
+
+func TestOddFileSize(t *testing.T) {
+ info, err := os.Stat("file.txt")
+ if err != nil {
+ t.Fatal(err)
+ }
+ if info.Size()%2 != 1 {
+ t.Fatal("even file")
+ }
+}
+
+func TestOddGetenv(t *testing.T) {
+ val := os.Getenv("TESTKEY")
+ if len(val)%2 != 1 {
+ t.Fatal("even env value")
+ }
+}
+
+func TestLookupEnv(t *testing.T) {
+ _, ok := os.LookupEnv("TESTKEY")
+ if !ok {
+ t.Fatal("env missing")
+ }
+}
+
+func TestDirList(t *testing.T) {
+ f, err := os.Open(".")
+ if err != nil {
+ t.Fatal(err)
+ }
+ f.Readdirnames(-1)
+ f.Close()
+}
+
+func TestExec(t *testing.T) {
+ // Note: not using os/exec to make sure there is no unexpected stat.
+ p, err := os.StartProcess("./script.sh", []string{"script"}, new(os.ProcAttr))
+ if err != nil {
+ t.Fatal(err)
+ }
+ ps, err := p.Wait()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !ps.Success() {
+ t.Fatalf("script failed: %v", err)
+ }
+}
+
+func TestExternalFile(t *testing.T) {
+ os.Open(os.Getenv("TEST_EXTERNAL_FILE"))
+ _, err := os.Stat(os.Getenv("TEST_EXTERNAL_FILE"))
+ if err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestOSArgs(t *testing.T) {
+ t.Log(os.Args)
+}
+
+func TestBenchtime(t *testing.T) {
+}
+
+-- mkold.go --
+package main
+
+import (
+ "log"
+ "os"
+ "time"
+)
+
+func main() {
+ d, err := time.ParseDuration(os.Args[1])
+ if err != nil {
+ log.Fatal(err)
+ }
+ path := os.Args[2]
+ old := time.Now().Add(-d)
+ err = os.Chtimes(path, old, old)
+ if err != nil {
+ log.Fatal(err)
+ }
+}
diff --git a/src/cmd/go/testdata/script/test_chatty_fail.txt b/src/cmd/go/testdata/script/test_chatty_fail.txt
new file mode 100644
index 0000000..a5ef559
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_chatty_fail.txt
@@ -0,0 +1,32 @@
+# Run chatty tests. Assert on CONT lines.
+! go test chatty_test.go -v
+
+# Sanity check that output occurs.
+stdout -count=2 'this is sub-0'
+stdout -count=2 'this is sub-1'
+stdout -count=2 'this is sub-2'
+stdout -count=1 'error from sub-0'
+stdout -count=1 'error from sub-1'
+stdout -count=1 'error from sub-2'
+
+# Non-parallel tests should not print CONT.
+! stdout CONT
+
+-- chatty_test.go --
+package chatty_test
+
+import (
+ "testing"
+ "fmt"
+)
+
+func TestChatty(t *testing.T) {
+ for i := 0; i < 3; i++ {
+ t.Run(fmt.Sprintf("sub-%d", i), func(t *testing.T) {
+ for j := 0; j < 2; j++ {
+ t.Logf("this is sub-%d", i)
+ }
+ t.Errorf("error from sub-%d", i)
+ })
+ }
+} \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/test_chatty_parallel_fail.txt b/src/cmd/go/testdata/script/test_chatty_parallel_fail.txt
new file mode 100644
index 0000000..62f97db
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_chatty_parallel_fail.txt
@@ -0,0 +1,62 @@
+# Run parallel chatty tests.
+# Check that multiple parallel outputs continue running.
+! go test -parallel 3 chatty_parallel_test.go -v
+
+stdout -count=1 '^=== CONT TestChattyParallel/sub-0'
+stdout -count=1 '^=== CONT TestChattyParallel/sub-1'
+stdout -count=1 '^=== CONT TestChattyParallel/sub-2'
+
+stdout -count=1 '^=== (CONT|NAME) TestChattyParallel/sub-0\n chatty_parallel_test.go:38: error from sub-0$'
+stdout -count=1 '^=== (CONT|NAME) TestChattyParallel/sub-1\n chatty_parallel_test.go:38: error from sub-1$'
+stdout -count=1 '^=== (CONT|NAME) TestChattyParallel/sub-2\n chatty_parallel_test.go:38: error from sub-2$'
+
+# Run parallel chatty tests with -json.
+# Check that each output is attributed to the right test.
+! go test -json -parallel 3 chatty_parallel_test.go -v
+stdout -count=1 '"Test":"TestChattyParallel/sub-0","Output":" chatty_parallel_test.go:38: error from sub-0\\n"'
+stdout -count=1 '"Test":"TestChattyParallel/sub-1","Output":" chatty_parallel_test.go:38: error from sub-1\\n"'
+stdout -count=1 '"Test":"TestChattyParallel/sub-2","Output":" chatty_parallel_test.go:38: error from sub-2\\n"'
+
+-- chatty_parallel_test.go --
+package chatty_parallel_test
+
+import (
+ "testing"
+ "fmt"
+ "flag"
+)
+
+// This test ensures the order of CONT lines in parallel chatty tests.
+func TestChattyParallel(t *testing.T) {
+ t.Parallel()
+
+ // The number of concurrent tests running. This is closely tied to the
+ // -parallel test flag, so we grab it from the flag rather than setting it
+ // to some constant.
+ parallel := flag.Lookup("test.parallel").Value.(flag.Getter).Get().(int)
+
+ // ready is a synchronization mechanism that causes subtests to execute
+ // round robin.
+ ready := make([]chan bool, parallel)
+ for i := range ready {
+ ready[i] = make(chan bool, 1)
+ }
+ ready[0] <- true
+
+ for i := range ready {
+ i := i
+ t.Run(fmt.Sprintf("sub-%d", i), func(t *testing.T) {
+ t.Parallel()
+
+ // Some basic log output to precede the failures.
+ <-ready[i]
+ t.Logf("this is sub-%d", i)
+ ready[(i+1)%len(ready)] <- true
+
+ // The actual failure messages we care about.
+ <-ready[i]
+ t.Errorf("error from sub-%d", i)
+ ready[(i+1)%len(ready)] <- true
+ })
+ }
+}
diff --git a/src/cmd/go/testdata/script/test_chatty_parallel_success.txt b/src/cmd/go/testdata/script/test_chatty_parallel_success.txt
new file mode 100644
index 0000000..01653ac
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_chatty_parallel_success.txt
@@ -0,0 +1,52 @@
+# Run parallel chatty tests. Assert on CONT or NAME lines. This test makes sure that
+# multiple parallel outputs have the appropriate test name lines between them.
+go test -parallel 3 chatty_parallel_test.go -v
+stdout -count=2 '^=== (CONT|NAME) TestChattyParallel/sub-0\n chatty_parallel_test.go:32: this is sub-0$'
+stdout -count=2 '^=== (CONT|NAME) TestChattyParallel/sub-1\n chatty_parallel_test.go:32: this is sub-1$'
+stdout -count=2 '^=== (CONT|NAME) TestChattyParallel/sub-2\n chatty_parallel_test.go:32: this is sub-2$'
+
+# Run parallel chatty tests with -json.
+# Assert test2json has properly attributed output.
+go test -json -parallel 3 chatty_parallel_test.go -v
+stdout -count=2 '"Test":"TestChattyParallel/sub-0","Output":" chatty_parallel_test.go:32: this is sub-0\\n"'
+stdout -count=2 '"Test":"TestChattyParallel/sub-1","Output":" chatty_parallel_test.go:32: this is sub-1\\n"'
+stdout -count=2 '"Test":"TestChattyParallel/sub-2","Output":" chatty_parallel_test.go:32: this is sub-2\\n"'
+
+-- chatty_parallel_test.go --
+package chatty_parallel_test
+
+import (
+ "testing"
+ "fmt"
+ "flag"
+)
+
+// This test ensures the order of CONT lines in parallel chatty tests.
+func TestChattyParallel(t *testing.T) {
+ t.Parallel()
+
+ // The number of concurrent tests running. This is closely tied to the
+ // -parallel test flag, so we grab it from the flag rather than setting it
+ // to some constant.
+ parallel := flag.Lookup("test.parallel").Value.(flag.Getter).Get().(int)
+
+ // ready is a synchronization mechanism that causes subtests to execute
+ // round robin.
+ ready := make([]chan bool, parallel)
+ for i := range ready {
+ ready[i] = make(chan bool, 1)
+ }
+ ready[0] <- true
+
+ for i := range ready {
+ i := i
+ t.Run(fmt.Sprintf("sub-%d", i), func(t *testing.T) {
+ t.Parallel()
+ for j := 0; j < 2; j++ {
+ <-ready[i]
+ t.Logf("this is sub-%d", i)
+ ready[(i+1)%len(ready)] <- true
+ }
+ })
+ }
+}
diff --git a/src/cmd/go/testdata/script/test_chatty_parallel_success_run.txt b/src/cmd/go/testdata/script/test_chatty_parallel_success_run.txt
new file mode 100644
index 0000000..1d4b6d6
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_chatty_parallel_success_run.txt
@@ -0,0 +1,41 @@
+# Run parallel chatty tests. Assert on CONT or NAME lines. This test makes sure that
+# multiple parallel outputs have the appropriate CONT lines between them.
+go test -parallel 3 chatty_parallel -v
+
+stdout '=== RUN TestInterruptor/interruption\n=== (CONT|NAME) TestLog\n chatty_parallel_test.go:28: this is the second TestLog log\n--- PASS: Test(Log|Interruptor) \([0-9.]{4}s\)'
+
+-- go.mod --
+module chatty_parallel
+
+go 1.18
+-- chatty_parallel_test.go --
+package chatty_parallel_test
+
+import (
+ "testing"
+)
+
+var (
+ afterFirstLog = make(chan struct{})
+ afterSubTest = make(chan struct{})
+ afterSecondLog = make(chan struct{})
+)
+
+func TestInterruptor(t *testing.T) {
+ t.Parallel()
+
+ <-afterFirstLog
+ t.Run("interruption", func (t *testing.T) {})
+ close(afterSubTest)
+ <-afterSecondLog // Delay the "PASS: TestInterruptor" line until after "CONT TestLog".
+}
+
+func TestLog(t *testing.T) {
+ t.Parallel()
+
+ t.Logf("this is the first TestLog log")
+ close(afterFirstLog)
+ <-afterSubTest
+ t.Logf("this is the second TestLog log")
+ close(afterSecondLog)
+}
diff --git a/src/cmd/go/testdata/script/test_chatty_success.txt b/src/cmd/go/testdata/script/test_chatty_success.txt
new file mode 100644
index 0000000..8bfa569
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_chatty_success.txt
@@ -0,0 +1,27 @@
+# Run chatty tests. Assert on CONT lines.
+go test chatty_test.go -v
+
+# Non-parallel tests should not print CONT.
+! stdout CONT
+
+# The assertion is condensed into one line so that it precisely matches output,
+# rather than skipping lines and allow rogue CONT lines.
+stdout '=== RUN TestChatty\n=== RUN TestChatty/sub-0\n chatty_test.go:12: this is sub-0\n chatty_test.go:12: this is sub-0\n=== RUN TestChatty/sub-1\n chatty_test.go:12: this is sub-1\n chatty_test.go:12: this is sub-1\n=== RUN TestChatty/sub-2\n chatty_test.go:12: this is sub-2\n chatty_test.go:12: this is sub-2\n--- PASS: TestChatty'
+
+-- chatty_test.go --
+package chatty_test
+
+import (
+ "testing"
+ "fmt"
+)
+
+func TestChatty(t *testing.T) {
+ for i := 0; i < 3; i++ {
+ t.Run(fmt.Sprintf("sub-%d", i), func(t *testing.T) {
+ for j := 0; j < 2; j++ {
+ t.Logf("this is sub-%d", i)
+ }
+ })
+ }
+} \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/test_cleanup_failnow.txt b/src/cmd/go/testdata/script/test_cleanup_failnow.txt
new file mode 100644
index 0000000..0aba8c7
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_cleanup_failnow.txt
@@ -0,0 +1,46 @@
+# For issue 41355
+[short] skip
+
+# This test could fail if the testing package does not wait until
+# a panicking test does the panic. Turn off multithreading and GC
+# to increase the probability of such a failure.
+env GOMAXPROCS=1
+env GOGC=off
+
+# If the test exits with 'no tests to run', it means the testing package
+# implementation is incorrect and does not wait until a test panic.
+# If the test exits with '(?s)panic: die.*panic: die', it means
+# the testing package did an extra panic for a panicking test.
+
+! go test -v cleanup_failnow/panic_nocleanup_test.go
+! stdout 'no tests to run'
+stdout '(?s)panic: die \[recovered\].*panic: die'
+! stdout '(?s)panic: die \[recovered\].*panic: die.*panic: die'
+
+! go test -v cleanup_failnow/panic_withcleanup_test.go
+! stdout 'no tests to run'
+stdout '(?s)panic: die \[recovered\].*panic: die'
+! stdout '(?s)panic: die \[recovered\].*panic: die.*panic: die'
+
+-- cleanup_failnow/panic_nocleanup_test.go --
+package panic_nocleanup_test
+import "testing"
+func TestX(t *testing.T) {
+ t.Run("x", func(t *testing.T) {
+ panic("die")
+ })
+}
+
+-- cleanup_failnow/panic_withcleanup_test.go --
+package panic_withcleanup_test
+import "testing"
+func TestCleanupWithFailNow(t *testing.T) {
+ t.Cleanup(func() {
+ t.FailNow()
+ })
+ t.Run("x", func(t *testing.T) {
+ t.Run("y", func(t *testing.T) {
+ panic("die")
+ })
+ })
+} \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/test_compile_binary.txt b/src/cmd/go/testdata/script/test_compile_binary.txt
new file mode 100644
index 0000000..63bb8ec
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_compile_binary.txt
@@ -0,0 +1,8 @@
+env GO111MODULE=off
+
+! go test -c compile_binary/...
+stderr 'build comment'
+
+-- compile_binary/foo_test.go --
+// +build foo
+package foo
diff --git a/src/cmd/go/testdata/script/test_compile_multi_pkg.txt b/src/cmd/go/testdata/script/test_compile_multi_pkg.txt
new file mode 100644
index 0000000..921ef5c
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_compile_multi_pkg.txt
@@ -0,0 +1,50 @@
+[short] skip 'links test binaries'
+
+# Verify test -c can output multiple executables to a directory.
+
+# This test also serves as a regression test for https://go.dev/issue/62221:
+# prior to the fix for that issue, it occasionally failed with ETXTBSY when
+# run on Unix platforms.
+
+go test -c -o $WORK/some/nonexisting/directory/ ./pkg/...
+exists -exec $WORK/some/nonexisting/directory/pkg1.test$GOEXE
+exists -exec $WORK/some/nonexisting/directory/pkg2.test$GOEXE
+
+go test -c ./pkg/...
+exists -exec pkg1.test$GOEXE
+exists -exec pkg2.test$GOEXE
+
+! go test -c -o $WORK/bin/test/bin.test.exe ./pkg/...
+stderr '^with multiple packages, -o must refer to a directory or '$devnull
+
+! go test -c ./...
+stderr '^cannot write test binary pkg1.test for multiple packages:\nexample/anotherpkg/pkg1\nexample/pkg/pkg1'
+
+! go test -c -o $WORK/bin/test/ ./...
+stderr '^cannot write test binary pkg1.test for multiple packages:\nexample/anotherpkg/pkg1\nexample/pkg/pkg1'
+
+! go test -o $WORK/bin/filename.exe ./pkg/...
+stderr '^with multiple packages, -o must refer to a directory or '$devnull
+
+! go test -o $WORK/bin/ ./...
+stderr '^cannot write test binary pkg1.test for multiple packages:\nexample/anotherpkg/pkg1\nexample/pkg/pkg1'
+
+go test -c -o $devnull ./...
+
+rm pkg1.test$GOEXE
+rm pkg2.test$GOEXE
+go test -o . ./pkg/...
+exists -exec pkg1.test$GOEXE
+exists -exec pkg2.test$GOEXE
+
+-- go.mod --
+module example
+
+-- pkg/pkg1/pkg1_test.go --
+package pkg1
+
+-- pkg/pkg2/pkg2_test.go --
+package pkg2
+
+-- anotherpkg/pkg1/pkg1_test.go --
+package pkg1
diff --git a/src/cmd/go/testdata/script/test_compile_tempfile.txt b/src/cmd/go/testdata/script/test_compile_tempfile.txt
new file mode 100644
index 0000000..05f721a
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_compile_tempfile.txt
@@ -0,0 +1,11 @@
+[short] skip
+
+# Ensure that the target of 'go build -o' can be an existing, empty file so that
+# its name can be reserved using os.CreateTemp or the 'mktemp` command.
+
+go build -o empty-file$GOEXE main.go
+
+-- main.go --
+package main
+func main() {}
+-- empty-file$GOEXE --
diff --git a/src/cmd/go/testdata/script/test_deadline.txt b/src/cmd/go/testdata/script/test_deadline.txt
new file mode 100644
index 0000000..06ae16f
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_deadline.txt
@@ -0,0 +1,54 @@
+[short] skip
+
+go test -timeout=0 -run=TestNoDeadline
+go test -timeout=1m -run=TestDeadlineWithinMinute
+go test -timeout=1m -run=TestSubtestDeadlineWithinMinute
+
+-- go.mod --
+module m
+
+go 1.16
+-- deadline_test.go --
+package testing_test
+
+import (
+ "testing"
+ "time"
+)
+
+func TestNoDeadline(t *testing.T) {
+ d, ok := t.Deadline()
+ if ok || !d.IsZero() {
+ t.Fatalf("t.Deadline() = %v, %v; want 0, false", d, ok)
+ }
+}
+
+func TestDeadlineWithinMinute(t *testing.T) {
+ now := time.Now()
+ d, ok := t.Deadline()
+ if !ok || d.IsZero() {
+ t.Fatalf("t.Deadline() = %v, %v; want nonzero deadline", d, ok)
+ }
+ if !d.After(now) {
+ t.Fatalf("t.Deadline() = %v; want after start of test (%v)", d, now)
+ }
+ if d.Sub(now) > time.Minute {
+ t.Fatalf("t.Deadline() = %v; want within one minute of start of test (%v)", d, now)
+ }
+}
+
+func TestSubtestDeadlineWithinMinute(t *testing.T) {
+ t.Run("sub", func(t *testing.T) {
+ now := time.Now()
+ d, ok := t.Deadline()
+ if !ok || d.IsZero() {
+ t.Fatalf("t.Deadline() = %v, %v; want nonzero deadline", d, ok)
+ }
+ if !d.After(now) {
+ t.Fatalf("t.Deadline() = %v; want after start of test (%v)", d, now)
+ }
+ if d.Sub(now) > time.Minute {
+ t.Fatalf("t.Deadline() = %v; want within one minute of start of test (%v)", d, now)
+ }
+ })
+}
diff --git a/src/cmd/go/testdata/script/test_empty.txt b/src/cmd/go/testdata/script/test_empty.txt
new file mode 100644
index 0000000..5ebbecd
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_empty.txt
@@ -0,0 +1,53 @@
+[!race] skip
+
+cd $GOPATH/src/empty/pkg
+go test -cover -coverpkg=. -race
+
+[short] stop # Only run first case in short mode
+
+cd $GOPATH/src/empty/test
+go test -cover -coverpkg=. -race
+
+cd $GOPATH/src/empty/xtest
+go test -cover -coverpkg=. -race
+
+cd $GOPATH/src/empty/pkgtest
+go test -cover -coverpkg=. -race
+
+cd $GOPATH/src/empty/pkgxtest
+go test -cover -coverpkg=. -race
+
+cd $GOPATH/src/empty/pkgtestxtest
+go test -cover -coverpkg=. -race
+
+cd $GOPATH/src/empty/testxtest
+go test -cover -coverpkg=. -race
+
+-- empty/go.mod --
+module empty
+
+go 1.16
+-- empty/pkg/pkg.go --
+package p
+-- empty/pkgtest/pkg.go --
+package p
+-- empty/pkgtest/test_test.go --
+package p
+-- empty/pkgtestxtest/pkg.go --
+package p
+-- empty/pkgtestxtest/test_test.go --
+package p
+-- empty/pkgtestxtest/xtest_test.go --
+package p_test
+-- empty/pkgxtest/pkg.go --
+package p
+-- empty/pkgxtest/xtest_test.go --
+package p_test
+-- empty/test/test_test.go --
+package p
+-- empty/testxtest/test_test.go --
+package p
+-- empty/testxtest/xtest_test.go --
+package p_test
+-- empty/xtest/xtest_test.go --
+package p_test
diff --git a/src/cmd/go/testdata/script/test_env_term.txt b/src/cmd/go/testdata/script/test_env_term.txt
new file mode 100644
index 0000000..8a5f79a
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_env_term.txt
@@ -0,0 +1,15 @@
+# Tests golang.org/issue/12096
+
+env TERM=''
+go test test_test.go
+! stdout '^ok.*\[no tests to run\]'
+stdout '^ok'
+
+-- test_test.go --
+package main
+import ("os"; "testing")
+func TestEnv(t *testing.T) {
+ if os.Getenv("TERM") != "" {
+ t.Fatal("TERM is set")
+ }
+} \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/test_example_goexit.txt b/src/cmd/go/testdata/script/test_example_goexit.txt
new file mode 100644
index 0000000..984f434
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_example_goexit.txt
@@ -0,0 +1,29 @@
+# For issue golang.org/issue/41084
+[short] skip
+
+! go test -v examplegoexit
+stdout '(?s)--- PASS.*--- FAIL.*'
+stdout 'panic: test executed panic\(nil\) or runtime\.Goexit'
+
+-- go.mod --
+module examplegoexit
+
+go 1.16
+-- example_test.go --
+package main
+
+import (
+ "fmt"
+ "runtime"
+)
+
+func ExamplePass() {
+ fmt.Println("pass")
+ // Output:
+ // pass
+}
+
+func ExampleGoexit() {
+ runtime.Goexit()
+ // Output:
+}
diff --git a/src/cmd/go/testdata/script/test_exit.txt b/src/cmd/go/testdata/script/test_exit.txt
new file mode 100644
index 0000000..3703ba5
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_exit.txt
@@ -0,0 +1,131 @@
+# Builds and runs test binaries, so skip in short mode.
+[short] skip
+
+env GO111MODULE=on
+
+# If a test invoked by 'go test' exits with a zero status code,
+# it will panic.
+! go test ./zero
+! stdout ^ok
+! stdout 'exit status'
+stdout 'panic'
+stdout ^FAIL
+
+# If a test exits with a non-zero status code, 'go test' fails normally.
+! go test ./one
+! stdout ^ok
+stdout 'exit status'
+! stdout 'panic'
+stdout ^FAIL
+
+# Ensure that other flags still do the right thing.
+go test -list=. ./zero
+stdout ExitZero
+
+! go test -bench=. ./zero
+stdout 'panic'
+
+# 'go test' with no args streams output without buffering. Ensure that it still
+# catches a zero exit with missing output.
+cd zero
+! go test
+stdout 'panic'
+cd ../normal
+go test
+stdout ^ok
+cd ..
+
+# If a TestMain exits with a zero status code, 'go test' shouldn't
+# complain about that. It's a common way to skip testing a package
+# entirely.
+go test ./main_zero
+! stdout 'skipping all tests'
+stdout ^ok
+
+# With -v, we'll see the warning from TestMain.
+go test -v ./main_zero
+stdout 'skipping all tests'
+stdout ^ok
+
+# Listing all tests won't actually give a result if TestMain exits. That's okay,
+# because this is how TestMain works. If we decide to support -list even when
+# TestMain is used to skip entire packages, we can change this test case.
+go test -list=. ./main_zero
+stdout 'skipping all tests'
+! stdout TestNotListed
+
+# Running the test directly still fails, if we pass the flag.
+go test -c -o ./zero.exe ./zero
+! exec ./zero.exe -test.paniconexit0
+
+# Using -json doesn't affect the exit status.
+! go test -json ./zero
+! stdout '"Output":"ok'
+! stdout 'exit status'
+stdout 'panic'
+stdout '"Output":"FAIL'
+
+# Running the test via test2json also fails.
+! go tool test2json ./zero.exe -test.v -test.paniconexit0
+! stdout '"Output":"ok'
+! stdout 'exit status'
+stdout 'panic'
+
+-- go.mod --
+module m
+
+-- ./normal/normal.go --
+package normal
+-- ./normal/normal_test.go --
+package normal
+
+import "testing"
+
+func TestExitZero(t *testing.T) {
+}
+
+-- ./zero/zero.go --
+package zero
+-- ./zero/zero_test.go --
+package zero
+
+import (
+ "os"
+ "testing"
+)
+
+func TestExitZero(t *testing.T) {
+ os.Exit(0)
+}
+
+-- ./one/one.go --
+package one
+-- ./one/one_test.go --
+package one
+
+import (
+ "os"
+ "testing"
+)
+
+func TestExitOne(t *testing.T) {
+ os.Exit(1)
+}
+
+-- ./main_zero/zero.go --
+package zero
+-- ./main_zero/zero_test.go --
+package zero
+
+import (
+ "fmt"
+ "os"
+ "testing"
+)
+
+func TestMain(m *testing.M) {
+ fmt.Println("skipping all tests")
+ os.Exit(0)
+}
+
+func TestNotListed(t *testing.T) {}
diff --git a/src/cmd/go/testdata/script/test_fail_fast.txt b/src/cmd/go/testdata/script/test_fail_fast.txt
new file mode 100644
index 0000000..132ea70
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fail_fast.txt
@@ -0,0 +1,113 @@
+[short] skip
+
+# test fail fast
+! go test ./failfast_test.go -run='TestFailingA' -failfast=true
+stdout -count=1 'FAIL - '
+! go test ./failfast_test.go -run='TestFailing[AB]' -failfast=true
+stdout -count=1 'FAIL - '
+! go test ./failfast_test.go -run='TestFailing[AB]' -failfast=false
+stdout -count=2 'FAIL - '
+
+# mix with non-failing tests
+! go test ./failfast_test.go -run='TestA|TestFailing[AB]' -failfast=true
+stdout -count=1 'FAIL - '
+! go test ./failfast_test.go -run='TestA|TestFailing[AB]' -failfast=false
+stdout -count=2 'FAIL - '
+
+# mix with parallel tests
+! go test ./failfast_test.go -run='TestFailingB|TestParallelFailingA' -failfast=true
+stdout -count=2 'FAIL - '
+! go test ./failfast_test.go -run='TestFailingB|TestParallelFailingA' -failfast=false
+stdout -count=2 'FAIL - '
+! go test ./failfast_test.go -run='TestFailingB|TestParallelFailing[AB]' -failfast=true
+stdout -count=3 'FAIL - '
+! go test ./failfast_test.go -run='TestFailingB|TestParallelFailing[AB]' -failfast=false
+stdout -count=3 'FAIL - '
+
+# mix with parallel sub-tests
+! go test ./failfast_test.go -run='TestFailingB|TestParallelFailing[AB]|TestParallelFailingSubtestsA' -failfast=true
+stdout -count=3 'FAIL - '
+! go test ./failfast_test.go -run='TestFailingB|TestParallelFailing[AB]|TestParallelFailingSubtestsA' -failfast=false
+stdout -count=5 'FAIL - '
+! go test ./failfast_test.go -run='TestParallelFailingSubtestsA' -failfast=true
+stdout -count=1 'FAIL - '
+
+# only parallels
+! go test ./failfast_test.go -run='TestParallelFailing[AB]' -failfast=false
+stdout -count=2 'FAIL - '
+
+# non-parallel subtests
+! go test ./failfast_test.go -run='TestFailingSubtestsA' -failfast=true
+stdout -count=1 'FAIL - '
+! go test ./failfast_test.go -run='TestFailingSubtestsA' -failfast=false
+stdout -count=2 'FAIL - '
+
+# fatal test
+! go test ./failfast_test.go -run='TestFatal[CD]' -failfast=true
+stdout -count=1 'FAIL - '
+! go test ./failfast_test.go -run='TestFatal[CD]' -failfast=false
+stdout -count=2 'FAIL - '
+
+-- failfast_test.go --
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package failfast
+
+import "testing"
+
+func TestA(t *testing.T) {
+ // Edge-case testing, mixing unparallel tests too
+ t.Logf("LOG: %s", t.Name())
+}
+
+func TestFailingA(t *testing.T) {
+ t.Errorf("FAIL - %s", t.Name())
+}
+
+func TestB(t *testing.T) {
+ // Edge-case testing, mixing unparallel tests too
+ t.Logf("LOG: %s", t.Name())
+}
+
+func TestParallelFailingA(t *testing.T) {
+ t.Parallel()
+ t.Errorf("FAIL - %s", t.Name())
+}
+
+func TestParallelFailingB(t *testing.T) {
+ t.Parallel()
+ t.Errorf("FAIL - %s", t.Name())
+}
+
+func TestParallelFailingSubtestsA(t *testing.T) {
+ t.Parallel()
+ t.Run("TestFailingSubtestsA1", func(t *testing.T) {
+ t.Errorf("FAIL - %s", t.Name())
+ })
+ t.Run("TestFailingSubtestsA2", func(t *testing.T) {
+ t.Errorf("FAIL - %s", t.Name())
+ })
+}
+
+func TestFailingSubtestsA(t *testing.T) {
+ t.Run("TestFailingSubtestsA1", func(t *testing.T) {
+ t.Errorf("FAIL - %s", t.Name())
+ })
+ t.Run("TestFailingSubtestsA2", func(t *testing.T) {
+ t.Errorf("FAIL - %s", t.Name())
+ })
+}
+
+func TestFailingB(t *testing.T) {
+ t.Errorf("FAIL - %s", t.Name())
+}
+
+func TestFatalC(t *testing.T) {
+ t.Fatalf("FAIL - %s", t.Name())
+}
+
+func TestFatalD(t *testing.T) {
+ t.Fatalf("FAIL - %s", t.Name())
+}
diff --git a/src/cmd/go/testdata/script/test_fail_newline.txt b/src/cmd/go/testdata/script/test_fail_newline.txt
new file mode 100644
index 0000000..43cee56
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fail_newline.txt
@@ -0,0 +1,65 @@
+[short] skip
+
+# In package list mode, output is buffered.
+# Check that a newline is printed after the buffer's contents.
+cd fail
+! go test .
+! stderr .
+stdout '^exitcode=1\n'
+stdout '^FAIL\s+example/fail'
+
+# In local directory mode output is streamed, so we don't know
+# whether the test printed anything at all, so we print the exit code
+# (just in case it failed without emitting any output at all),
+# and that happens to add the needed newline as well.
+! go test
+! stderr .
+stdout '^exitcode=1exit status 1\n'
+stdout '^FAIL\s+example/fail'
+
+# In package list mode, if the test passes the 'ok' message appears
+# on its own line.
+cd ../skip
+go test -v .
+! stderr .
+stdout '^skipping\n'
+stdout '^ok\s+example/skip'
+
+# If the output is streamed and the test passes, we can't tell whether it ended
+# in a partial line, and don't want to emit any extra output in the
+# overwhelmingly common case that it did not.
+# (In theory we could hook the 'os' package to report whether output
+# was emitted and whether it ended in a newline, but that seems too invasive.)
+go test
+! stderr .
+stdout '^skippingok\s+example/skip'
+
+
+-- go.mod --
+module example
+
+go 1.18
+-- fail/fail_test.go --
+package fail
+
+import (
+ "os"
+ "testing"
+)
+
+func TestMain(m *testing.M) {
+ os.Stderr.WriteString("exitcode=1")
+ os.Exit(1)
+}
+-- skip/skip_test.go --
+package skip
+
+import (
+ "os"
+ "testing"
+)
+
+func TestMain(m *testing.M) {
+ os.Stderr.WriteString("skipping")
+ os.Exit(0)
+}
diff --git a/src/cmd/go/testdata/script/test_finished_subtest_goroutines.txt b/src/cmd/go/testdata/script/test_finished_subtest_goroutines.txt
new file mode 100644
index 0000000..8db821e
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_finished_subtest_goroutines.txt
@@ -0,0 +1,52 @@
+# Regression test for https://golang.org/issue/45127:
+# Goroutines for completed parallel subtests should exit immediately,
+# not block until earlier subtests have finished.
+
+[short] skip
+
+! go test .
+stdout 'panic: slow failure'
+! stdout '\[chan send'
+
+-- go.mod --
+module golang.org/issue45127
+
+go 1.16
+-- issue45127_test.go --
+package main
+
+import (
+ "fmt"
+ "runtime"
+ "runtime/debug"
+ "sync"
+ "testing"
+)
+
+func TestTestingGoroutineLeak(t *testing.T) {
+ debug.SetTraceback("all")
+
+ var wg sync.WaitGroup
+ const nFast = 10
+
+ t.Run("slow", func(t *testing.T) {
+ t.Parallel()
+ wg.Wait()
+ for i := 0; i < nFast; i++ {
+ // If the subtest goroutines are going to park on the channel
+ // send, allow them to park now. If they're not going to park,
+ // make sure they have had a chance to run to completion so
+ // that they aren't spuriously parked when we panic.
+ runtime.Gosched()
+ }
+ panic("slow failure")
+ })
+
+ wg.Add(nFast)
+ for i := 0; i < nFast; i++ {
+ t.Run(fmt.Sprintf("leaky%d", i), func(t *testing.T) {
+ t.Parallel()
+ wg.Done()
+ })
+ }
+}
diff --git a/src/cmd/go/testdata/script/test_flag.txt b/src/cmd/go/testdata/script/test_flag.txt
new file mode 100644
index 0000000..6ef4529
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_flag.txt
@@ -0,0 +1,38 @@
+[short] skip
+
+go test flag_test.go -v -args -v=7 # Two distinct -v flags
+go test -v flag_test.go -args -v=7 # Two distinct -v flags
+
+# Using a custom flag mixed with regular 'go test' flags should be OK.
+go test -count=1 -custom -args -v=7
+
+# However, it should be an error to use custom flags when -c is used,
+# since we know for sure that no test binary will run at all.
+! go test -c -custom
+stderr '^go: unknown flag -custom cannot be used with -c$'
+
+# The same should apply even if -c comes after a custom flag.
+! go test -custom -c
+stderr '^go: unknown flag -custom cannot be used with -c$'
+
+-- go.mod --
+module m
+-- flag_test.go --
+package flag_test
+
+import (
+ "flag"
+ "log"
+ "testing"
+)
+
+var v = flag.Int("v", 0, "v flag")
+
+var custom = flag.Bool("custom", false, "")
+
+// Run this as go test pkg -v=7
+func TestVFlagIsSet(t *testing.T) {
+ if *v != 7 {
+ log.Fatal("v flag not set")
+ }
+}
diff --git a/src/cmd/go/testdata/script/test_flags.txt b/src/cmd/go/testdata/script/test_flags.txt
new file mode 100644
index 0000000..3f7964b
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_flags.txt
@@ -0,0 +1,131 @@
+env GO111MODULE=on
+
+[short] skip
+
+# Arguments after the flag terminator should be ignored.
+# If we pass '-- -test.v', we should not get verbose output
+# *and* output from the test should not be echoed.
+go test ./x -- -test.v
+stdout '\Aok\s+example.com/x\s+[0-9.s]+\n\z'
+! stderr .
+
+# For backward-compatibility with previous releases of the 'go' command,
+# arguments that appear after unrecognized flags should not be treated
+# as packages, even if they are unambiguously not arguments to flags.
+# Even though ./x looks like a package path, the real package should be
+# the implicit '.'.
+! go test --answer=42 ./x
+stderr '^no Go files in '$PWD'$'
+
+# However, *flags* that appear after unrecognized flags should still be
+# interpreted as flags, under the (possibly-erroneous) assumption that
+# unrecognized flags are non-boolean.
+
+go test -v -x ./x -timeout 24h -boolflag=true foo -timeout 25h
+stdout 'args: foo -timeout 25h'
+stdout 'timeout: 24h0m0s$' # -timeout is unambiguously not a flag, so the real flag wins.
+
+go test -v -x ./x -timeout 24h -boolflag foo -timeout 25h
+stdout 'args: foo -test\.timeout=25h0m0s' # For legacy reasons, '-timeout ' is erroneously rewritten to -test.timeout; see https://golang.org/issue/40763.
+stdout 'timeout: 24h0m0s$' # Actual flag wins.
+
+go test -v -x ./x -timeout 24h -stringflag foo -timeout 25h
+stdout 'args: $'
+stdout 'timeout: 25h0m0s$' # Later flag wins.
+
+# An explicit '-outputdir=' argument should set test.outputdir
+# to the 'go' command's working directory, not zero it out
+# for the test binary.
+go test -x -coverprofile=cover.out '-outputdir=' ./x
+stderr '-test.outputdir=[^ ]'
+exists ./cover.out
+! exists ./x/cover.out
+
+# Test flags from GOFLAGS should be forwarded to the test binary,
+# with the 'test.' prefix in the GOFLAGS entry...
+env GOFLAGS='-test.timeout=24h0m0s -count=1'
+go test -v -x ./x
+stdout 'timeout: 24h0m0s$'
+stderr '-test.count=1'
+
+# ...or without.
+env GOFLAGS='-timeout=24h0m0s -count=1'
+go test -v -x ./x
+stdout 'timeout: 24h0m0s$'
+stderr '-test.count=1'
+
+# Arguments from the command line should override GOFLAGS...
+go test -v -x -timeout=25h0m0s ./x
+stdout 'timeout: 25h0m0s$'
+stderr '-test.count=1'
+
+# ...even if they use a different flag name.
+go test -v -x -test.timeout=26h0m0s ./x
+stdout 'timeout: 26h0m0s$'
+stderr '-test\.timeout=26h0m0s'
+! stderr 'timeout=24h0m0s'
+stderr '-test.count=1'
+
+# Invalid flags should be reported exactly once.
+! go test -covermode=walrus ./x
+stderr -count=1 'invalid value "walrus" for flag -covermode: valid modes are .*$'
+stderr '^usage: go test .*$'
+stderr '^Run ''go help test'' and ''go help testflag'' for details.$'
+
+# Passing -help to the test binary should show flag help.
+go test ./x -args -help
+stdout 'usage_message'
+
+# -covermode, -coverpkg, and -coverprofile should imply -cover
+go test -covermode=set ./x
+stdout '\s+coverage:\s+'
+
+go test -coverpkg=encoding/binary ./x
+stdout '\s+coverage:\s+'
+
+go test -coverprofile=cover.out ./x
+stdout '\s+coverage:\s+'
+exists ./cover.out
+rm ./cover.out
+
+# -*profile and -trace flags should force output to the current working directory
+# or -outputdir, not the directory containing the test.
+
+go test -memprofile=mem.out ./x
+exists ./mem.out
+rm ./mem.out
+
+go test -trace=trace.out ./x
+exists ./trace.out
+rm ./trace.out
+
+# Relative paths with -outputdir should be relative to the go command's working
+# directory, not the directory containing the test.
+mkdir profiles
+go test -memprofile=mem.out -outputdir=./profiles ./x
+exists ./profiles/mem.out
+rm profiles
+
+-- go.mod --
+module example.com
+go 1.14
+-- x/x_test.go --
+package x
+
+import (
+ "flag"
+ "strings"
+ "testing"
+)
+
+var _ = flag.String("usage_message", "", "dummy flag to check usage message")
+var boolflag = flag.Bool("boolflag", false, "ignored boolean flag")
+var stringflag = flag.String("stringflag", "", "ignored string flag")
+
+func TestLogTimeout(t *testing.T) {
+ t.Logf("timeout: %v", flag.Lookup("test.timeout").Value)
+}
+
+func TestLogArgs(t *testing.T) {
+ t.Logf("args: %s", strings.Join(flag.Args(), " "))
+}
diff --git a/src/cmd/go/testdata/script/test_fullpath.txt b/src/cmd/go/testdata/script/test_fullpath.txt
new file mode 100644
index 0000000..8e01552
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fullpath.txt
@@ -0,0 +1,21 @@
+[short] skip
+
+# test with -fullpath
+! go test ./x/... -fullpath
+stdout '^ +.+/gopath/src/x/fullpath/fullpath_test.go:8: test failed'
+# test without -fullpath
+! go test ./x/...
+stdout '^ +fullpath_test.go:8: test failed'
+
+-- go.mod --
+module example
+-- x/fullpath/fullpath_test.go --
+package fullpath_test
+
+import (
+ "testing"
+)
+
+func TestFullPath(t *testing.T) {
+ t.Error("test failed")
+}
diff --git a/src/cmd/go/testdata/script/test_fuzz.txt b/src/cmd/go/testdata/script/test_fuzz.txt
new file mode 100644
index 0000000..37170bf
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fuzz.txt
@@ -0,0 +1,500 @@
+[!fuzz] skip
+[short] skip
+env GOCACHE=$WORK/cache
+
+# Test that running a fuzz target that returns without failing or calling
+# f.Fuzz fails and causes a non-zero exit status.
+! go test noop_fuzz_test.go
+! stdout ^ok
+stdout FAIL
+
+# Test that fuzzing a fuzz target that returns without failing or calling
+# f.Fuzz fails and causes a non-zero exit status.
+! go test -fuzz=Fuzz -fuzztime=1x noop_fuzz_test.go
+! stdout ^ok
+stdout FAIL
+
+# Test that calling f.Error in a fuzz target causes a non-zero exit status.
+! go test -fuzz=Fuzz -fuzztime=1x error_fuzz_test.go
+! stdout ^ok
+stdout FAIL
+
+# Test that calling f.Fatal in a fuzz target causes a non-zero exit status.
+! go test fatal_fuzz_test.go
+! stdout ^ok
+stdout FAIL
+
+# Test that successful test exits cleanly.
+go test success_fuzz_test.go
+stdout ^ok
+! stdout FAIL
+
+# Test that successful fuzzing exits cleanly.
+go test -fuzz=Fuzz -fuzztime=1x success_fuzz_test.go
+stdout ok
+! stdout FAIL
+
+# Test that calling f.Fatal while fuzzing causes a non-zero exit status.
+! go test -fuzz=Fuzz -fuzztime=1x fatal_fuzz_test.go
+! stdout ^ok
+stdout FAIL
+
+# Test error with seed corpus in f.Fuzz
+! go test -run FuzzError fuzz_add_test.go
+! stdout ^ok
+stdout FAIL
+stdout 'error here'
+
+[short] stop
+
+# Test that calling panic(nil) in a fuzz target causes a non-zero exit status.
+! go test panic_fuzz_test.go
+! stdout ^ok
+stdout FAIL
+
+# Test that skipped test exits cleanly.
+go test skipped_fuzz_test.go
+stdout ok
+! stdout FAIL
+
+# Test that f.Fatal within f.Fuzz panics
+! go test fatal_fuzz_fn_fuzz_test.go
+! stdout ^ok
+! stdout 'fatal here'
+stdout FAIL
+stdout 'fuzz target'
+
+# Test that f.Error within f.Fuzz panics
+! go test error_fuzz_fn_fuzz_test.go
+! stdout ^ok
+! stdout 'error here'
+stdout FAIL
+stdout 'fuzz target'
+
+# Test that f.Fail within f.Fuzz panics
+! go test fail_fuzz_fn_fuzz_test.go
+! stdout ^ok
+stdout FAIL
+stdout 'fuzz target'
+
+# Test that f.Skip within f.Fuzz panics
+! go test skip_fuzz_fn_fuzz_test.go
+! stdout ^ok
+! stdout 'skip here'
+stdout FAIL
+stdout 'fuzz target'
+
+# Test that f.Skipped within f.Fuzz panics
+! go test skipped_fuzz_fn_fuzz_test.go
+! stdout ^ok
+! stdout 'f.Skipped is'
+stdout FAIL
+stdout 'fuzz target'
+stdout 't.Skipped is false'
+
+# Test that runtime.Goexit within the fuzz function is an error.
+! go test goexit_fuzz_fn_fuzz_test.go
+! stdout ^ok
+stdout FAIL
+
+# Test that a call to f.Fatal after the Fuzz func is executed.
+! go test fatal_after_fuzz_func_fuzz_test.go
+! stdout ok
+stdout FAIL
+
+# Test that missing *T in f.Fuzz causes a non-zero exit status.
+! go test incomplete_fuzz_call_fuzz_test.go
+! stdout ^ok
+stdout FAIL
+
+# Test that a panic in the Cleanup func is executed.
+! go test cleanup_fuzz_test.go
+! stdout ^ok
+stdout FAIL
+stdout 'failed some precondition'
+
+# Test success with seed corpus in f.Fuzz
+go test -run FuzzPass fuzz_add_test.go
+stdout ok
+! stdout FAIL
+! stdout 'off by one error'
+
+# Test fatal with seed corpus in f.Fuzz
+! go test -run FuzzFatal fuzz_add_test.go
+! stdout ^ok
+stdout FAIL
+stdout 'fatal here'
+
+# Test panic with seed corpus in f.Fuzz
+! go test -run FuzzPanic fuzz_add_test.go
+! stdout ^ok
+stdout FAIL
+stdout 'off by one error'
+
+# Test panic(nil) with seed corpus in f.Fuzz
+! go test -run FuzzNilPanic fuzz_add_test.go
+! stdout ^ok
+stdout FAIL
+
+# Test panic with unsupported seed corpus
+! go test -run FuzzUnsupported fuzz_add_test.go
+! stdout ^ok
+stdout FAIL
+
+# Test panic with different number of args to f.Add
+! go test -run FuzzAddDifferentNumber fuzz_add_test.go
+! stdout ^ok
+stdout FAIL
+
+# Test panic with different type of args to f.Add
+! go test -run FuzzAddDifferentType fuzz_add_test.go
+! stdout ^ok
+stdout FAIL
+
+# Test that the wrong type given with f.Add will fail.
+! go test -run FuzzWrongType fuzz_add_test.go
+! stdout ^ok
+stdout '\[string int\], want \[\[\]uint8 int8\]'
+stdout FAIL
+
+# Test fatal with testdata seed corpus
+! go test -run FuzzFail corpustesting/fuzz_testdata_corpus_test.go
+! stdout ^ok
+stdout FAIL
+stdout 'fatal here'
+
+# Test pass with testdata seed corpus
+go test -run FuzzPass corpustesting/fuzz_testdata_corpus_test.go
+stdout ok
+! stdout FAIL
+! stdout 'fatal here'
+
+# Test pass with testdata and f.Add seed corpus
+go test -run FuzzPassString corpustesting/fuzz_testdata_corpus_test.go
+stdout ok
+! stdout FAIL
+
+# Fuzzing pass with testdata and f.Add seed corpus (skip running tests first)
+go test -run=None -fuzz=FuzzPassString corpustesting/fuzz_testdata_corpus_test.go -fuzztime=10x
+stdout ok
+! stdout FAIL
+
+# Fuzzing pass with testdata and f.Add seed corpus
+go test -run=FuzzPassString -fuzz=FuzzPassString corpustesting/fuzz_testdata_corpus_test.go -fuzztime=10x
+stdout ok
+! stdout FAIL
+
+# Test panic with malformed seed corpus
+! go test -run FuzzFail corpustesting/fuzz_testdata_corpus_test.go
+! stdout ^ok
+stdout FAIL
+
+# Test pass with file in other nested testdata directory
+go test -run FuzzInNestedDir corpustesting/fuzz_testdata_corpus_test.go
+stdout ok
+! stdout FAIL
+! stdout 'fatal here'
+
+# Test fails with file containing wrong type
+! go test -run FuzzWrongType corpustesting/fuzz_testdata_corpus_test.go
+! stdout ^ok
+stdout FAIL
+
+-- noop_fuzz_test.go --
+package noop_fuzz
+
+import "testing"
+
+func Fuzz(f *testing.F) {}
+
+-- error_fuzz_test.go --
+package error_fuzz
+
+import "testing"
+
+func Fuzz(f *testing.F) {
+ f.Error("error in target")
+}
+
+-- fatal_fuzz_test.go --
+package fatal_fuzz
+
+import "testing"
+
+func Fuzz(f *testing.F) {
+ f.Fatal("fatal in target")
+}
+
+-- panic_fuzz_test.go --
+package panic_fuzz
+
+import "testing"
+
+func FuzzPanic(f *testing.F) {
+ panic(nil)
+}
+
+-- success_fuzz_test.go --
+package success_fuzz
+
+import "testing"
+
+func Fuzz(f *testing.F) {
+ f.Fuzz(func (*testing.T, []byte) {})
+}
+
+-- skipped_fuzz_test.go --
+package skipped_fuzz
+
+import "testing"
+
+func Fuzz(f *testing.F) {
+ f.Skip()
+}
+
+-- fatal_fuzz_fn_fuzz_test.go --
+package fatal_fuzz_fn_fuzz
+
+import "testing"
+
+func Fuzz(f *testing.F) {
+ f.Add([]byte("aa"))
+ f.Fuzz(func(t *testing.T, b []byte) {
+ f.Fatal("fatal here")
+ })
+}
+
+-- error_fuzz_fn_fuzz_test.go --
+package error_fuzz_fn_fuzz
+
+import "testing"
+
+func Fuzz(f *testing.F) {
+ f.Add([]byte("aa"))
+ f.Fuzz(func(t *testing.T, b []byte) {
+ f.Error("error here")
+ })
+}
+
+-- fail_fuzz_fn_fuzz_test.go --
+package skip_fuzz_fn_fuzz
+
+import "testing"
+
+func Fuzz(f *testing.F) {
+ f.Add([]byte("aa"))
+ f.Fuzz(func(t *testing.T, b []byte) {
+ f.Fail()
+ })
+}
+
+-- skip_fuzz_fn_fuzz_test.go --
+package skip_fuzz_fn_fuzz
+
+import "testing"
+
+func Fuzz(f *testing.F) {
+ f.Add([]byte("aa"))
+ f.Fuzz(func(t *testing.T, b []byte) {
+ f.Skip("skip here")
+ })
+}
+
+-- skipped_fuzz_fn_fuzz_test.go --
+package skipped_fuzz_fn_fuzz
+
+import "testing"
+
+func Fuzz(f *testing.F) {
+ f.Add([]byte("aa"))
+ f.Fuzz(func(t *testing.T, b []byte) {
+ t.Logf("t.Skipped is %t\n", t.Skipped())
+ t.Logf("f.Skipped is %t\n", f.Skipped())
+ })
+}
+
+-- goexit_fuzz_fn_fuzz_test.go --
+package goexit_fuzz_fn_fuzz
+
+import "testing"
+
+func Fuzz(f *testing.F) {
+ f.Add([]byte("aa"))
+ f.Fuzz(func(t *testing.T, b []byte) {
+ runtime.Goexit()
+ })
+}
+
+-- fatal_after_fuzz_func_fuzz_test.go --
+package fatal_after_fuzz_func_fuzz
+
+import "testing"
+
+func Fuzz(f *testing.F) {
+ f.Fuzz(func(t *testing.T, b []byte) {
+ // no-op
+ })
+ f.Fatal("this shouldn't be called")
+}
+
+-- incomplete_fuzz_call_fuzz_test.go --
+package incomplete_fuzz_call_fuzz
+
+import "testing"
+
+func Fuzz(f *testing.F) {
+ f.Fuzz(func(b []byte) {
+ // this is missing *testing.T as the first param, so should panic
+ })
+}
+
+-- cleanup_fuzz_test.go --
+package cleanup_fuzz_test
+
+import "testing"
+
+func Fuzz(f *testing.F) {
+ f.Cleanup(func() {
+ panic("failed some precondition")
+ })
+ f.Fuzz(func(t *testing.T, b []byte) {
+ // no-op
+ })
+}
+
+-- fuzz_add_test.go --
+package fuzz_add
+
+import "testing"
+
+func add(f *testing.F) {
+ f.Helper()
+ f.Add([]byte("123"))
+ f.Add([]byte("12345"))
+ f.Add([]byte(""))
+}
+
+func FuzzPass(f *testing.F) {
+ add(f)
+ f.Fuzz(func(t *testing.T, b []byte) {
+ if len(b) == -1 {
+ t.Fatal("fatal here") // will not be executed
+ }
+ })
+}
+
+func FuzzError(f *testing.F) {
+ add(f)
+ f.Fuzz(func(t *testing.T, b []byte) {
+ if len(b) == 3 {
+ t.Error("error here")
+ }
+ })
+}
+
+func FuzzFatal(f *testing.F) {
+ add(f)
+ f.Fuzz(func(t *testing.T, b []byte) {
+ if len(b) == 0 {
+ t.Fatal("fatal here")
+ }
+ })
+}
+
+func FuzzPanic(f *testing.F) {
+ add(f)
+ f.Fuzz(func(t *testing.T, b []byte) {
+ if len(b) == 5 {
+ panic("off by one error")
+ }
+ })
+}
+
+func FuzzNilPanic(f *testing.F) {
+ add(f)
+ f.Fuzz(func(t *testing.T, b []byte) {
+ if len(b) == 3 {
+ panic(nil)
+ }
+ })
+}
+
+func FuzzUnsupported(f *testing.F) {
+ m := make(map[string]bool)
+ f.Add(m)
+ f.Fuzz(func(*testing.T, []byte) {})
+}
+
+func FuzzAddDifferentNumber(f *testing.F) {
+ f.Add([]byte("a"))
+ f.Add([]byte("a"), []byte("b"))
+ f.Fuzz(func(*testing.T, []byte) {})
+}
+
+func FuzzAddDifferentType(f *testing.F) {
+ f.Add(false)
+ f.Add(1234)
+ f.Fuzz(func(*testing.T, []byte) {})
+}
+
+func FuzzWrongType(f *testing.F) {
+ f.Add("hello", 50)
+ f.Fuzz(func(*testing.T, []byte, int8) {})
+}
+
+-- corpustesting/fuzz_testdata_corpus_test.go --
+package fuzz_testdata_corpus
+
+import "testing"
+
+func fuzzFn(f *testing.F) {
+ f.Helper()
+ f.Fuzz(func(t *testing.T, b []byte) {
+ if string(b) == "12345" {
+ t.Fatal("fatal here")
+ }
+ })
+}
+
+func FuzzFail(f *testing.F) {
+ fuzzFn(f)
+}
+
+func FuzzPass(f *testing.F) {
+ fuzzFn(f)
+}
+
+func FuzzPassString(f *testing.F) {
+ f.Add("some seed corpus")
+ f.Fuzz(func(*testing.T, string) {})
+}
+
+func FuzzPanic(f *testing.F) {
+ f.Fuzz(func(t *testing.T, b []byte) {})
+}
+
+func FuzzInNestedDir(f *testing.F) {
+ f.Fuzz(func(t *testing.T, b []byte) {})
+}
+
+func FuzzWrongType(f *testing.F) {
+ f.Fuzz(func(t *testing.T, b []byte) {})
+}
+
+-- corpustesting/testdata/fuzz/FuzzFail/1 --
+go test fuzz v1
+[]byte("12345")
+-- corpustesting/testdata/fuzz/FuzzPass/1 --
+go test fuzz v1
+[]byte("00000")
+-- corpustesting/testdata/fuzz/FuzzPassString/1 --
+go test fuzz v1
+string("hello")
+-- corpustesting/testdata/fuzz/FuzzPanic/1 --
+malformed
+-- corpustesting/testdata/fuzz/FuzzInNestedDir/anotherdir/1 --
+go test fuzz v1
+[]byte("12345")
+-- corpustesting/testdata/fuzz/FuzzWrongType/1 --
+go test fuzz v1
+int("00000")
diff --git a/src/cmd/go/testdata/script/test_fuzz_cache.txt b/src/cmd/go/testdata/script/test_fuzz_cache.txt
new file mode 100644
index 0000000..752ab3a
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fuzz_cache.txt
@@ -0,0 +1,97 @@
+[!fuzz-instrumented] skip
+
+[short] skip
+env GOCACHE=$WORK/cache
+
+# Fuzz cache should not exist after a regular test run.
+go test .
+exists $GOCACHE
+! exists $GOCACHE/fuzz
+
+# Fuzzing should write interesting values to the cache.
+go test -fuzz=FuzzY -fuzztime=100x .
+go run ./contains_files $GOCACHE/fuzz/example.com/y/FuzzY
+
+# 'go clean -cache' should not delete the fuzz cache.
+go clean -cache
+exists $GOCACHE/fuzz
+
+# 'go clean -fuzzcache' should delete the fuzz cache but not the build cache.
+go build -x ./empty
+stderr '(compile|gccgo)( |\.exe).*empty.go'
+go clean -fuzzcache
+! exists $GOCACHE/fuzz
+go build -x ./empty
+! stderr '(compile|gccgo)( |\.exe).*empty.go'
+
+# Fuzzing indicates that one new interesting value was found with an empty
+# corpus, and the total size of the cache is now 1.
+go clean -fuzzcache
+go test -fuzz=FuzzEmpty -fuzztime=10000x .
+stdout 'new interesting: 1'
+stdout 'total: 1'
+
+# Fuzzing again with a small fuzztime does not find any other interesting
+# values but still indicates that the cache size is 1.
+go test -fuzz=FuzzEmpty -fuzztime=2x .
+stdout 'new interesting: 0'
+stdout 'total: 1'
+
+! go clean -fuzzcache example.com/y
+stderr 'go: clean -fuzzcache cannot be used with package arguments'
+
+-- go.mod --
+module example.com/y
+
+go 1.16
+-- y_test.go --
+package y
+
+import (
+ "io"
+ "testing"
+)
+
+func FuzzEmpty(f *testing.F) {
+ f.Fuzz(func (*testing.T, []byte) {})
+}
+
+func FuzzY(f *testing.F) {
+ f.Add([]byte("y"))
+ f.Fuzz(func(t *testing.T, b []byte) { Y(io.Discard, b) })
+}
+-- y.go --
+package y
+
+import (
+ "bytes"
+ "io"
+)
+
+func Y(w io.Writer, b []byte) {
+ if !bytes.Equal(b, []byte("y")) {
+ w.Write([]byte("not equal"))
+ }
+}
+-- empty/empty.go --
+package empty
+-- contains_files/contains_files.go --
+package main
+
+import (
+ "fmt"
+ "path/filepath"
+ "io/ioutil"
+ "os"
+)
+
+func main() {
+ infos, err := ioutil.ReadDir(filepath.Clean(os.Args[1]))
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ if len(infos) == 0 {
+ os.Exit(1)
+ }
+}
diff --git a/src/cmd/go/testdata/script/test_fuzz_chatty.txt b/src/cmd/go/testdata/script/test_fuzz_chatty.txt
new file mode 100644
index 0000000..01a68cb
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fuzz_chatty.txt
@@ -0,0 +1,103 @@
+[!fuzz] skip
+[short] skip
+env GOCACHE=$WORK/cache
+
+# Run chatty fuzz targets with an error.
+! go test -v chatty_error_fuzz_test.go
+! stdout '^ok'
+stdout 'FAIL'
+stdout 'error in target'
+
+# Run chatty fuzz targets with a fatal.
+! go test -v chatty_fatal_fuzz_test.go
+! stdout '^ok'
+stdout 'FAIL'
+stdout 'fatal in target'
+
+# Run chatty fuzz target with a panic
+! go test -v chatty_panic_fuzz_test.go
+! stdout ^ok
+stdout FAIL
+stdout 'this is bad'
+
+# Run skipped chatty fuzz targets.
+go test -v chatty_skipped_fuzz_test.go
+stdout ok
+stdout SKIP
+! stdout FAIL
+
+# Run successful chatty fuzz targets.
+go test -v chatty_fuzz_test.go
+stdout ok
+stdout PASS
+stdout 'all good here'
+! stdout FAIL
+
+# Fuzz successful chatty fuzz target that includes a separate unit test.
+go test -v chatty_with_test_fuzz_test.go -fuzz=Fuzz -fuzztime=1x
+stdout ok
+stdout PASS
+! stdout FAIL
+stdout -count=1 'all good here'
+# Verify that the unit test is only run once.
+stdout -count=1 'logged foo'
+
+-- chatty_error_fuzz_test.go --
+package chatty_error_fuzz
+
+import "testing"
+
+func Fuzz(f *testing.F) {
+ f.Error("error in target")
+}
+
+-- chatty_fatal_fuzz_test.go --
+package chatty_fatal_fuzz
+
+import "testing"
+
+func Fuzz(f *testing.F) {
+ f.Fatal("fatal in target")
+}
+
+-- chatty_panic_fuzz_test.go --
+package chatty_panic_fuzz
+
+import "testing"
+
+func Fuzz(f *testing.F) {
+ panic("this is bad")
+}
+
+-- chatty_skipped_fuzz_test.go --
+package chatty_skipped_fuzz
+
+import "testing"
+
+func Fuzz(f *testing.F) {
+ f.Skip()
+}
+
+-- chatty_fuzz_test.go --
+package chatty_fuzz
+
+import "testing"
+
+func Fuzz(f *testing.F) {
+ f.Log("all good here")
+ f.Fuzz(func(*testing.T, []byte) {})
+}
+
+-- chatty_with_test_fuzz_test.go --
+package chatty_with_test_fuzz
+
+import "testing"
+
+func TestFoo(t *testing.T) {
+ t.Log("logged foo")
+}
+
+func Fuzz(f *testing.F) {
+ f.Log("all good here")
+ f.Fuzz(func(*testing.T, []byte) {})
+}
diff --git a/src/cmd/go/testdata/script/test_fuzz_cleanup.txt b/src/cmd/go/testdata/script/test_fuzz_cleanup.txt
new file mode 100644
index 0000000..5f86498
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fuzz_cleanup.txt
@@ -0,0 +1,67 @@
+[!fuzz] skip
+[short] skip
+env GOCACHE=$WORK/cache
+
+# Cleanup should run after F.Skip.
+go test -run=FuzzTargetSkip
+stdout cleanup
+
+# Cleanup should run after F.Fatal.
+! go test -run=FuzzTargetFatal
+stdout cleanup
+
+# Cleanup should run after an unexpected runtime.Goexit.
+! go test -run=FuzzTargetGoexit
+stdout cleanup
+
+# Cleanup should run after panic.
+! go test -run=FuzzTargetPanic
+stdout cleanup
+
+# Cleanup should run in fuzz function on seed corpus.
+go test -v -run=FuzzFunction
+stdout '(?s)inner.*outer'
+
+# TODO(jayconrod): test cleanup while fuzzing. For now, the worker process's
+# stdout and stderr is connected to the coordinator's, but it should eventually
+# be connected to os.DevNull, so we wouldn't see t.Log output.
+
+-- go.mod --
+module cleanup
+
+go 1.15
+-- cleanup_test.go --
+package cleanup
+
+import (
+ "runtime"
+ "testing"
+)
+
+func FuzzTargetSkip(f *testing.F) {
+ f.Cleanup(func() { f.Log("cleanup") })
+ f.Skip()
+}
+
+func FuzzTargetFatal(f *testing.F) {
+ f.Cleanup(func() { f.Log("cleanup") })
+ f.Fatal()
+}
+
+func FuzzTargetGoexit(f *testing.F) {
+ f.Cleanup(func() { f.Log("cleanup") })
+ runtime.Goexit()
+}
+
+func FuzzTargetPanic(f *testing.F) {
+ f.Cleanup(func() { f.Log("cleanup") })
+ panic("oh no")
+}
+
+func FuzzFunction(f *testing.F) {
+ f.Add([]byte{0})
+ f.Cleanup(func() { f.Log("outer") })
+ f.Fuzz(func(t *testing.T, b []byte) {
+ t.Cleanup(func() { t.Logf("inner") })
+ })
+}
diff --git a/src/cmd/go/testdata/script/test_fuzz_cov.txt b/src/cmd/go/testdata/script/test_fuzz_cov.txt
new file mode 100644
index 0000000..c0844a3
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fuzz_cov.txt
@@ -0,0 +1,36 @@
+# Test that coverage instrumentation is working. Without the instrumentation
+# it is _extremely_ unlikely that the fuzzer would produce this particular
+# input in any reasonable amount of time.
+
+[short] skip
+[!fuzz-instrumented] skip
+env GOCACHE=$WORK/cache
+
+# TODO(#51484): enabled debugging info to help diagnose a deadlock in the fuzzer
+env GODEBUG=fuzzdebug=1
+! go test -fuzz=FuzzCov -v
+! stderr 'cov instrumentation working'
+
+-- go.mod --
+module test
+
+-- cov_test.go --
+package cov
+
+import "testing"
+
+func FuzzCov(f *testing.F) {
+ f.Fuzz(func(t *testing.T, b []byte) {
+ if len(b) == 8 &&
+ b[0] == 'h' &&
+ b[1] == 'e' &&
+ b[2] == 'l' &&
+ b[3] == 'l' &&
+ b[4] == 'o' &&
+ b[5] == ' ' &&
+ b[6] == ':' &&
+ b[7] == ')' {
+ panic("cov instrumentation working")
+ }
+ })
+}
diff --git a/src/cmd/go/testdata/script/test_fuzz_deadline.txt b/src/cmd/go/testdata/script/test_fuzz_deadline.txt
new file mode 100644
index 0000000..46d3521
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fuzz_deadline.txt
@@ -0,0 +1,36 @@
+[!fuzz] skip
+[short] skip
+env GOCACHE=$WORK/cache
+
+# The fuzz function should be able to detect whether -timeout
+# was set with T.Deadline. Note there is no F.Deadline, and
+# there is no timeout while fuzzing, even if -fuzztime is set.
+go test -run=FuzzDeadline -wantdeadline=true # -timeout defaults to 10m
+go test -run=FuzzDeadline -timeout=0 -wantdeadline=false
+! go test -run=FuzzDeadline -timeout=1s -wantdeadline=false
+go test -run=FuzzDeadline -timeout=1s -wantdeadline=true
+go test -fuzz=FuzzDeadline -timeout=0 -fuzztime=1s -wantdeadline=false
+go test -fuzz=FuzzDeadline -timeout=0 -fuzztime=100x -wantdeadline=false
+
+-- go.mod --
+module fuzz
+
+go 1.16
+-- fuzz_deadline_test.go --
+package fuzz_test
+
+import (
+ "flag"
+ "testing"
+)
+
+var wantDeadline = flag.Bool("wantdeadline", false, "whether the test should have a deadline")
+
+func FuzzDeadline(f *testing.F) {
+ f.Add("run once")
+ f.Fuzz(func (t *testing.T, _ string) {
+ if _, hasDeadline := t.Deadline(); hasDeadline != *wantDeadline {
+ t.Fatalf("function got %v; want %v", hasDeadline, *wantDeadline)
+ }
+ })
+}
diff --git a/src/cmd/go/testdata/script/test_fuzz_dup_cache.txt b/src/cmd/go/testdata/script/test_fuzz_dup_cache.txt
new file mode 100644
index 0000000..f54a77c
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fuzz_dup_cache.txt
@@ -0,0 +1,53 @@
+[!fuzz] skip
+[short] skip
+env GOCACHE=$WORK/cache
+
+# This test checks that cached corpus loading properly handles duplicate entries (this can
+# happen when a f.Add value has a duplicate entry in the cached corpus.) Duplicate entries
+# should be discarded, and the rest of the cache should be loaded as normal.
+
+env GOCACHE=$WORK/cache
+env GODEBUG=fuzzdebug=1
+
+mkdir -p $GOCACHE/fuzz/fuzztest/FuzzTarget
+go run ./populate $GOCACHE/fuzz/fuzztest/FuzzTarget
+
+go test -fuzz=FuzzTarget -fuzztime=10x .
+stdout 'entries: 5'
+
+-- go.mod --
+module fuzztest
+
+go 1.17
+
+-- fuzz_test.go --
+package fuzz
+
+import "testing"
+
+func FuzzTarget(f *testing.F) {
+ f.Add(int(0))
+ f.Fuzz(func(t *testing.T, _ int) {})
+}
+
+-- populate/main.go --
+package main
+
+import (
+ "path/filepath"
+ "fmt"
+ "os"
+)
+
+func main() {
+ for i := 0; i < 10; i++ {
+ b := byte(0)
+ if i > 5 {
+ b = byte(i)
+ }
+ tmpl := "go test fuzz v1\nint(%d)\n"
+ if err := os.WriteFile(filepath.Join(os.Args[1], fmt.Sprint(i)), []byte(fmt.Sprintf(tmpl, b)), 0777); err != nil {
+ panic(err)
+ }
+ }
+} \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/test_fuzz_err_deadlock.txt b/src/cmd/go/testdata/script/test_fuzz_err_deadlock.txt
new file mode 100644
index 0000000..4feb41a
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fuzz_err_deadlock.txt
@@ -0,0 +1,50 @@
+[short] skip
+[!fuzz-instrumented] skip
+
+env GOCACHE=$WORK/cache
+! go test -fuzz=FuzzDead -v
+# This is a somewhat inexact check, but since we don't prefix the error with anything
+# and as the error suffix is platform dependent, this is the best we can do. In the
+# deadlock failure case, the test will just deadlock and timeout anyway, so it should
+# be clear that that failure mode is different.
+stdout 'open'
+
+-- go.mod --
+module test
+
+-- cov_test.go --
+package dead
+
+import (
+ "os"
+ "path/filepath"
+ "testing"
+ "time"
+)
+
+func FuzzDead(f *testing.F) {
+ go func() {
+ c := filepath.Join(os.Getenv("GOCACHE"), "fuzz", "test", "FuzzDead")
+ t := time.NewTicker(time.Second)
+ for range t.C {
+ files, _ := os.ReadDir(c)
+ if len(files) > 0 {
+ os.RemoveAll(c)
+ }
+ }
+ }()
+
+ f.Fuzz(func(t *testing.T, b []byte) {
+ if len(b) == 8 &&
+ b[0] == 'h' &&
+ b[1] == 'e' &&
+ b[2] == 'l' &&
+ b[3] == 'l' &&
+ b[4] == 'o' &&
+ b[5] == ' ' &&
+ b[6] == ':' &&
+ b[7] == ')' {
+ return
+ }
+ })
+}
diff --git a/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt b/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt
new file mode 100644
index 0000000..28ef3bf
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt
@@ -0,0 +1,120 @@
+[!fuzz] skip
+[short] skip
+env GOCACHE=$WORK/cache
+
+# There are no seed values, so 'go test' should finish quickly.
+go test
+
+# Fuzzing should exit 0 after fuzztime, even if timeout is short.
+go test -timeout=3s -fuzz=FuzzFast -fuzztime=5s
+
+# We should see the same behavior when invoking the test binary directly.
+go test -c
+exec ./fuzz.test$GOEXE -test.timeout=3s -test.fuzz=FuzzFast -test.fuzztime=5s -test.parallel=1 -test.fuzzcachedir=$WORK/cache
+
+# Timeout should not cause inputs to be written as crashers.
+! exists testdata/fuzz
+
+# When we use fuzztime with an "x" suffix, it runs a specific number of times.
+# This fuzz function creates a file with a unique name ($pid.$count) on each
+# run. We count the files to find the number of runs.
+mkdir count
+go test -fuzz=FuzzTestCount -fuzztime=1000x -fuzzminimizetime=1x
+go run check_file_count.go count 1000
+
+# When we use fuzzminimizetime with an "x" suffix, it runs a specific number of
+# times while minimizing. This fuzz function creates a file with a unique name
+# ($pid.$count) on each run once the first crash has been found. That means that
+# there should be one file for each execution of the fuzz function during
+# minimization, so we count these to determine how many times minimization was
+# run.
+mkdir minimizecount
+! go test -fuzz=FuzzMinimizeCount -fuzzminimizetime=3x -parallel=1
+go run check_file_count.go minimizecount 3
+
+-- go.mod --
+module fuzz
+
+go 1.16
+-- fuzz_fast_test.go --
+package fuzz_test
+
+import "testing"
+
+func FuzzFast(f *testing.F) {
+ f.Fuzz(func (*testing.T, []byte) {})
+}
+-- fuzz_count_test.go --
+package fuzz
+
+import (
+ "fmt"
+ "os"
+ "testing"
+)
+
+func FuzzTestCount(f *testing.F) {
+ pid := os.Getpid()
+ n := 0
+ f.Fuzz(func(t *testing.T, _ []byte) {
+ name := fmt.Sprintf("count/%v.%d", pid, n)
+ if err := os.WriteFile(name, nil, 0666); err != nil {
+ t.Fatal(err)
+ }
+ n++
+ })
+}
+-- fuzz_minimize_count_test.go --
+package fuzz
+
+import (
+ "bytes"
+ "fmt"
+ "os"
+ "testing"
+)
+
+func FuzzMinimizeCount(f *testing.F) {
+ pid := os.Getpid()
+ n := 0
+ seed := bytes.Repeat([]byte("a"), 357)
+ f.Add(seed)
+ crashFound := false
+ f.Fuzz(func(t *testing.T, b []byte) {
+ if crashFound {
+ name := fmt.Sprintf("minimizecount/%v.%d", pid, n)
+ if err := os.WriteFile(name, nil, 0666); err != nil {
+ t.Fatal(err)
+ }
+ n++
+ }
+ if !bytes.Equal(b, seed) { // this should happen right away
+ crashFound = true
+ t.Error("minimize this!")
+ }
+ })
+}
+-- check_file_count.go --
+// +build ignore
+
+package main
+
+import (
+ "fmt"
+ "os"
+ "strconv"
+)
+
+func main() {
+ dir, err := os.ReadDir(os.Args[1])
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ got := len(dir)
+ want, _ := strconv.Atoi(os.Args[2])
+ if got != want {
+ fmt.Fprintf(os.Stderr, "got %d files; want %d\n", got, want)
+ os.Exit(1)
+ }
+}
diff --git a/src/cmd/go/testdata/script/test_fuzz_io_error.txt b/src/cmd/go/testdata/script/test_fuzz_io_error.txt
new file mode 100644
index 0000000..01b4da6
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fuzz_io_error.txt
@@ -0,0 +1,102 @@
+# Test that when the coordinator experiences an I/O error communicating
+# with a worker, the coordinator stops the worker and reports the error.
+# The coordinator should not record a crasher.
+#
+# We simulate an I/O error in the test by writing garbage to fuzz_out.
+# This is unlikely, but possible. It's difficult to simulate interruptions
+# due to ^C and EOF errors which are more common. We don't report those.
+[short] skip
+[!fuzz] skip
+env GOCACHE=$WORK/cache
+
+# If the I/O error occurs before F.Fuzz is called, the coordinator should
+# stop the worker and say that.
+! go test -fuzz=FuzzClosePipeBefore -parallel=1
+stdout '\s*fuzzing process terminated without fuzzing:'
+! stdout 'communicating with fuzzing process'
+! exists testdata
+
+# If the I/O error occurs after F.Fuzz is called (unlikely), just exit.
+# It's hard to distinguish this case from the worker being interrupted by ^C
+# or exiting with status 0 (which it should do when interrupted by ^C).
+! go test -fuzz=FuzzClosePipeAfter -parallel=1
+stdout '^\s*communicating with fuzzing process: invalid character ''!'' looking for beginning of value$'
+! exists testdata
+
+-- go.mod --
+module test
+
+go 1.17
+-- io_error_test.go --
+package io_error
+
+import (
+ "flag"
+ "testing"
+ "time"
+)
+
+func isWorker() bool {
+ f := flag.Lookup("test.fuzzworker")
+ if f == nil {
+ return false
+ }
+ get, ok := f.Value.(flag.Getter)
+ if !ok {
+ return false
+ }
+ return get.Get() == interface{}(true)
+}
+
+func FuzzClosePipeBefore(f *testing.F) {
+ if isWorker() {
+ sendGarbageToCoordinator(f)
+ time.Sleep(3600 * time.Second) // pause until coordinator terminates the process
+ }
+ f.Fuzz(func(*testing.T, []byte) {})
+}
+
+func FuzzClosePipeAfter(f *testing.F) {
+ f.Fuzz(func(t *testing.T, _ []byte) {
+ if isWorker() {
+ sendGarbageToCoordinator(t)
+ time.Sleep(3600 * time.Second) // pause until coordinator terminates the process
+ }
+ })
+}
+-- io_error_windows_test.go --
+package io_error
+
+import (
+ "fmt"
+ "os"
+ "testing"
+)
+
+func sendGarbageToCoordinator(tb testing.TB) {
+ v := os.Getenv("GO_TEST_FUZZ_WORKER_HANDLES")
+ var fuzzInFD, fuzzOutFD uintptr
+ if _, err := fmt.Sscanf(v, "%x,%x", &fuzzInFD, &fuzzOutFD); err != nil {
+ tb.Fatalf("parsing GO_TEST_FUZZ_WORKER_HANDLES: %v", err)
+ }
+ f := os.NewFile(fuzzOutFD, "fuzz_out")
+ if _, err := f.Write([]byte("!!")); err != nil {
+ tb.Fatalf("writing fuzz_out: %v", err)
+ }
+}
+-- io_error_notwindows_test.go --
+// +build !windows
+
+package io_error
+
+import (
+ "os"
+ "testing"
+)
+
+func sendGarbageToCoordinator(tb testing.TB) {
+ f := os.NewFile(4, "fuzz_out")
+ if _, err := f.Write([]byte("!!")); err != nil {
+ tb.Fatalf("writing fuzz_out: %v", err)
+ }
+}
diff --git a/src/cmd/go/testdata/script/test_fuzz_limit_dup_entry.txt b/src/cmd/go/testdata/script/test_fuzz_limit_dup_entry.txt
new file mode 100644
index 0000000..d69f6e0
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fuzz_limit_dup_entry.txt
@@ -0,0 +1,37 @@
+[!fuzz] skip
+[short] skip
+env GOCACHE=$WORK/cache
+
+# FuzzA attempts to cause the mutator to create duplicate inputs that generate
+# new coverage. Previously this would trigger a corner case when the fuzzer
+# had an execution limit, causing it to deadlock and sit in the coordinator
+# loop indefinitely, failing to exit once the limit had been exhausted.
+
+go test -fuzz=FuzzA -fuzztime=100x -parallel=1
+
+-- go.mod --
+module m
+
+go 1.16
+-- fuzz_test.go --
+package fuzz_test
+
+import (
+ "fmt"
+ "testing"
+)
+
+func FuzzA(f *testing.F) {
+ f.Add([]byte("seed"))
+ i := 0
+ f.Fuzz(func(t *testing.T, b []byte) {
+ i++
+ if string(b) == "seed" {
+ if i == 0 {
+ fmt.Println("a")
+ } else if i > 1 {
+ fmt.Println("b")
+ }
+ }
+ })
+}
diff --git a/src/cmd/go/testdata/script/test_fuzz_match.txt b/src/cmd/go/testdata/script/test_fuzz_match.txt
new file mode 100644
index 0000000..d149586
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fuzz_match.txt
@@ -0,0 +1,40 @@
+[!fuzz] skip
+[short] skip
+env GOCACHE=$WORK/cache
+
+# Matches only fuzz targets to test.
+go test standalone_fuzz_test.go
+! stdout '^ok.*\[no tests to run\]'
+stdout '^ok'
+
+# Matches only for fuzzing.
+go test -fuzz Fuzz -fuzztime 1x standalone_fuzz_test.go
+! stdout '^ok.*\[no tests to run\]'
+stdout '^ok'
+
+# Matches none for fuzzing but will run the fuzz target as a test.
+go test -fuzz ThisWillNotMatch -fuzztime 1x standalone_fuzz_test.go
+! stdout '^ok.*no tests to run'
+stdout '^ok'
+stdout 'no fuzz tests to fuzz'
+
+[short] stop
+
+# Matches only fuzz targets to test with -run.
+go test -run Fuzz standalone_fuzz_test.go
+! stdout '^ok.*\[no tests to run\]'
+stdout '^ok'
+
+# Matches no fuzz targets.
+go test -run ThisWillNotMatch standalone_fuzz_test.go
+stdout '^ok.*no tests to run'
+! stdout 'no fuzz tests to fuzz'
+
+-- standalone_fuzz_test.go --
+package standalone_fuzz
+
+import "testing"
+
+func Fuzz(f *testing.F) {
+ f.Fuzz(func (*testing.T, []byte) {})
+}
diff --git a/src/cmd/go/testdata/script/test_fuzz_minimize.txt b/src/cmd/go/testdata/script/test_fuzz_minimize.txt
new file mode 100644
index 0000000..a6dc3f1
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fuzz_minimize.txt
@@ -0,0 +1,203 @@
+[!fuzz] skip
+[short] skip
+
+# We clean the fuzz cache during this test. Don't clean the user's cache.
+env GOCACHE=$WORK/gocache
+
+# Test that fuzzminimizetime cannot be negative seconds
+! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=10000x -fuzzminimizetime=-1ms .
+! stdout '^ok'
+! stdout 'contains a non-zero byte'
+stdout 'invalid duration'
+stdout FAIL
+
+# Test that fuzzminimizetime cannot be negative times
+! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=10000x -fuzzminimizetime=-1x .
+! stdout '^ok'
+! stdout 'contains a non-zero byte'
+stdout 'invalid count'
+stdout FAIL
+
+# Test that fuzzminimizetime can be zero seconds, and minimization is disabled
+! go test -fuzz=FuzzMinimizeZeroDurationSet -run=FuzzMinimizeZeroDurationSet -fuzztime=10000x -fuzzminimizetime=0s .
+! stdout '^ok'
+! stdout 'minimizing'
+stdout 'there was an Error'
+stdout FAIL
+
+# Test that fuzzminimizetime can be zero times, and minimization is disabled
+! go test -fuzz=FuzzMinimizeZeroLimitSet -run=FuzzMinimizeZeroLimitSet -fuzztime=10000x -fuzzminimizetime=0x .
+! stdout '^ok'
+! stdout 'minimizing'
+stdout -count=1 'there was an Error'
+stdout FAIL
+
+# Test that minimization is working for recoverable errors.
+! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=10000x .
+! stdout '^ok'
+stdout 'got the minimum size!'
+# The error message that was printed should be for the one written to testdata.
+stdout 'contains a non-zero byte of length 50'
+stdout FAIL
+
+# Check that the bytes written to testdata are of length 50 (the minimum size)
+go run ./check_testdata FuzzMinimizerRecoverable 50
+
+# Test that re-running the minimized value causes a crash.
+! go test -run=FuzzMinimizerRecoverable .
+rm testdata
+
+# Test that minimization is working for recoverable errors. Run it with -v this
+# time to ensure the command line output still looks right.
+! go test -v -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=10000x .
+! stdout '^ok'
+stdout 'got the minimum size!'
+# The error message that was printed should be for the one written to testdata.
+stdout 'contains a non-zero byte of length 50'
+stdout FAIL
+
+# Check that the bytes written to testdata are of length 50 (the minimum size)
+go run ./check_testdata FuzzMinimizerRecoverable 50
+
+# Test that re-running the minimized value causes a crash.
+! go test -run=FuzzMinimizerRecoverable .
+rm testdata
+
+# Test that minimization doesn't run for non-recoverable errors.
+! go test -fuzz=FuzzMinimizerNonrecoverable -run=FuzzMinimizerNonrecoverable -fuzztime=10000x .
+! stdout '^ok'
+! stdout 'minimizing'
+stdout -count=1 '^\s+fuzzing process hung or terminated unexpectedly: exit status 99'
+stdout FAIL
+
+# Check that re-running the value causes a crash.
+! go test -run=FuzzMinimizerNonrecoverable .
+rm testdata
+
+# Clear the fuzzing cache. There may already be minimized inputs that would
+# interfere with the next stage of the test.
+go clean -fuzzcache
+
+# Test that minimization can be cancelled by fuzzminimizetime and the latest
+# crash will still be logged and written to testdata.
+! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=100x -fuzzminimizetime=1x .
+! stdout '^ok'
+stdout 'testdata[/\\]fuzz[/\\]FuzzMinimizerRecoverable[/\\]'
+! stdout 'got the minimum size!' # it shouldn't have had enough time to minimize it
+stdout FAIL
+
+# Test that re-running the unminimized value causes a crash.
+! go test -run=FuzzMinimizerRecoverable .
+
+# TODO(jayconrod,katiehockman): add a test which verifies that the right bytes
+# are written to testdata in the case of an interrupt during minimization.
+
+-- go.mod --
+module example.com/y
+
+go 1.16
+-- y_test.go --
+package y
+
+import (
+ "os"
+ "testing"
+)
+
+func FuzzMinimizeZeroDurationSet(f *testing.F) {
+ f.Fuzz(func(t *testing.T, b []byte) {
+ if len(b) > 5 {
+ t.Errorf("there was an Error")
+ }
+ })
+}
+
+func FuzzMinimizeZeroLimitSet(f *testing.F) {
+ f.Fuzz(func(t *testing.T, b []byte) {
+ if len(b) > 5 {
+ t.Errorf("there was an Error")
+ }
+ })
+}
+
+func FuzzMinimizerRecoverable(f *testing.F) {
+ f.Add(make([]byte, 100))
+ f.Fuzz(func(t *testing.T, b []byte) {
+ if len(b) < 50 {
+ // Make sure that b is large enough that it can be minimized
+ return
+ }
+ // Given the randomness of the mutations, this should allow the
+ // minimizer to trim down the value a bit.
+ for _, n := range b {
+ if n != 0 {
+ if len(b) == 50 {
+ t.Log("got the minimum size!")
+ }
+ t.Fatalf("contains a non-zero byte of length %d", len(b))
+ }
+ }
+ })
+}
+
+func FuzzMinimizerNonrecoverable(f *testing.F) {
+ f.Fuzz(func(t *testing.T, b []byte) {
+ os.Exit(99)
+ })
+}
+-- empty/empty.go --
+package empty
+-- check_testdata/check_testdata.go --
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "strconv"
+)
+
+func main() {
+ target := os.Args[1]
+ numBytes, err := strconv.Atoi(os.Args[2])
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+
+ // Open the file in testdata (there should only be one)
+ dir := fmt.Sprintf("testdata/fuzz/%s", target)
+ files, err := ioutil.ReadDir(dir)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ if len(files) != 1 {
+ fmt.Fprintf(os.Stderr, "expected one file, got %d", len(files))
+ os.Exit(1)
+ }
+ got, err := ioutil.ReadFile(filepath.Join(dir, files[0].Name()))
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+
+ // Trim the newline at the end of the file
+ got = bytes.TrimSpace(got)
+
+ // Make sure that there were exactly 100 bytes written to the corpus entry
+ prefix := []byte("[]byte(")
+ i := bytes.Index(got, prefix)
+ gotBytes := got[i+len(prefix) : len(got)-1]
+ s, err := strconv.Unquote(string(gotBytes))
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ if want, got := numBytes, len(s); want != got {
+ fmt.Fprintf(os.Stderr, "want %d bytes, got %d\n", want, got)
+ os.Exit(1)
+ }
+}
diff --git a/src/cmd/go/testdata/script/test_fuzz_minimize_dirty_cov.txt b/src/cmd/go/testdata/script/test_fuzz_minimize_dirty_cov.txt
new file mode 100644
index 0000000..c8af9be
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fuzz_minimize_dirty_cov.txt
@@ -0,0 +1,85 @@
+# Test that minimization doesn't use dirty coverage snapshots when it
+# is unable to actually minimize the input. We do this by checking that
+# an expected value appears in the cache. If a dirty coverage map is used
+# (i.e. the coverage map generated during the last minimization step,
+# rather than the map provided with the initial input) then this value
+# is unlikely to appear in the cache, since the map generated during
+# the last minimization step should not increase the coverage.
+
+[short] skip
+[!fuzz-instrumented] skip
+
+env GOCACHE=$WORK/gocache
+go test -fuzz=FuzzCovMin -fuzztime=500000x -test.fuzzcachedir=$GOCACHE/fuzz
+go run check_file/main.go $GOCACHE/fuzz/FuzzCovMin ab
+
+-- go.mod --
+module test
+
+-- covmin_test.go --
+package covmin
+
+import "testing"
+
+func FuzzCovMin(f *testing.F) {
+ f.Add([]byte("aa"))
+ f.Fuzz(func(t *testing.T, data []byte) {
+ if len(data) == 2 && data[0] == 'a' && data[1] == 'b' {
+ return
+ }
+ })
+}
+
+-- check_file/main.go --
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "os"
+ "path/filepath"
+ "regexp"
+ "strconv"
+)
+
+func checkFile(name, expected string) (bool, error) {
+ data, err := os.ReadFile(name)
+ if err != nil {
+ return false, err
+ }
+ for _, line := range bytes.Split(data, []byte("\n")) {
+ m := valRe.FindSubmatch(line)
+ if m == nil {
+ continue
+ }
+ fmt.Println(strconv.Unquote(string(m[1])))
+ if s, err := strconv.Unquote(string(m[1])); err != nil {
+ return false, err
+ } else if s == expected {
+ return true, nil
+ }
+ }
+ return false, nil
+}
+
+var valRe = regexp.MustCompile(`^\[\]byte\(([^)]+)\)$`)
+
+func main() {
+ dir, expected := os.Args[1], os.Args[2]
+ ents, err := os.ReadDir(dir)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ for _, ent := range ents {
+ name := filepath.Join(dir, ent.Name())
+ if good, err := checkFile(name, expected); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ } else if good {
+ os.Exit(0)
+ }
+ }
+ fmt.Fprintln(os.Stderr, "input over minimized")
+ os.Exit(1)
+}
diff --git a/src/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt b/src/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt
new file mode 100644
index 0000000..11aaaca
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt
@@ -0,0 +1,230 @@
+[short] skip
+[!fuzz-instrumented] skip
+
+# Test that when an interesting value is discovered (one that expands coverage),
+# the fuzzing engine minimizes it before writing it to the cache.
+#
+# The program below starts with a seed value of length 100, but more coverage
+# will be found for any value other than the seed. We should end with a value
+# in the cache of length 1 (the minimizer currently does not produce empty
+# strings). check_cache.go confirms that.
+#
+# We would like to verify that ALL values in the cache were minimized to a
+# length of 1, but this isn't always possible when new coverage is found in
+# functions called by testing or internal/fuzz in the background.
+
+go test -c -fuzz=. # Build using shared build cache for speed.
+env GOCACHE=$WORK/gocache
+exec ./fuzz.test$GOEXE -test.fuzzcachedir=$GOCACHE/fuzz -test.fuzz=FuzzMinCache -test.fuzztime=1000x
+go run check_cache/check_cache.go $GOCACHE/fuzz/FuzzMinCache
+
+# Test that minimization occurs for a crash that appears while minimizing a
+# newly found interesting input. There must be only one worker for this test to
+# be flaky like we want.
+! exec ./fuzz.test$GOEXE -test.fuzzcachedir=$GOCACHE/fuzz -test.fuzz=FuzzMinimizerCrashInMinimization -test.run=^$ -test.fuzztime=10000x -test.parallel=1
+! stdout '^ok'
+stdout -count=1 'got the minimum size!'
+stdout -count=1 'bad input'
+stdout FAIL
+# Check that the input written to testdata will reproduce the error, and is the
+# smallest possible.
+go run check_testdata/check_testdata.go FuzzMinimizerCrashInMinimization 1
+
+# Test that a nonrecoverable error that occurs while minimizing an interesting
+# input is reported correctly.
+! exec ./fuzz.test$GOEXE -test.fuzzcachedir=$GOCACHE/fuzz -test.fuzz=FuzzMinimizerNonrecoverableCrashInMinimization -test.run=^$ -test.fuzztime=10000x -test.parallel=1
+! stdout '^ok'
+stdout -count=1 'fuzzing process hung or terminated unexpectedly while minimizing'
+stdout -count=1 'EOF'
+stdout FAIL
+# Check that the input written to testdata will reproduce the error.
+go run check_testdata/check_testdata.go FuzzMinimizerNonrecoverableCrashInMinimization 1
+
+-- go.mod --
+module fuzz
+
+go 1.17
+-- y.go --
+package fuzz
+
+import (
+ "bytes"
+ "io"
+)
+
+func Y(w io.Writer, s string) {
+ if !bytes.Equal([]byte(s), []byte("y")) {
+ w.Write([]byte("not equal"))
+ }
+}
+-- fuzz_test.go --
+package fuzz
+
+import (
+ "bytes"
+ "os"
+ "testing"
+)
+
+func FuzzMinimizerCrashInMinimization(f *testing.F) {
+ seed := bytes.Repeat([]byte{255}, 100)
+ f.Add(seed)
+ f.Fuzz(func(t *testing.T, b []byte) {
+ if bytes.Equal(seed, b) {
+ return
+ }
+ t.Error("bad input")
+ if len(b) == 1 {
+ t.Error("got the minimum size!")
+ }
+ })
+}
+
+var fuzzing bool
+
+func FuzzMinimizerNonrecoverableCrashInMinimization(f *testing.F) {
+ seed := bytes.Repeat([]byte{255}, 100)
+ f.Add(seed)
+ f.Fuzz(func(t *testing.T, b []byte) {
+ if bytes.Equal(seed, b) {
+ return
+ } else if len(b) == 1 {
+ os.Exit(1)
+ }
+ })
+}
+
+func FuzzMinCache(f *testing.F) {
+ seed := bytes.Repeat([]byte("a"), 20)
+ f.Add(seed)
+ f.Fuzz(func(t *testing.T, buf []byte) {
+ if bytes.Equal(buf, seed) {
+ return
+ }
+ })
+}
+-- check_testdata/check_testdata.go --
+//go:build ignore
+// +build ignore
+
+// check_testdata.go checks that the string written
+// is not longer than the provided length.
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "regexp"
+ "strconv"
+)
+
+func main() {
+ wantLen, err := strconv.Atoi(os.Args[2])
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ testName := os.Args[1]
+ dir := filepath.Join("testdata/fuzz", testName)
+
+ files, err := ioutil.ReadDir(dir)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+
+ if len(files) == 0 {
+ fmt.Fprintf(os.Stderr, "expect at least one failure to be written to testdata\n")
+ os.Exit(1)
+ }
+
+ for _, f := range files {
+ data, err := ioutil.ReadFile(filepath.Join(dir, f.Name()))
+ if err != nil {
+ panic(err)
+ }
+ var containsVal bool
+ for _, line := range bytes.Split(data, []byte("\n")) {
+ m := valRe.FindSubmatch(line)
+ if m == nil {
+ continue
+ }
+ containsVal = true
+ s, err := strconv.Unquote(string(m[1]))
+ if err != nil {
+ panic(err)
+ }
+ if len(s) != wantLen {
+ fmt.Fprintf(os.Stderr, "expect length %d, got %d (%q)\n", wantLen, len(s), line)
+ os.Exit(1)
+ }
+ }
+ if !containsVal {
+ fmt.Fprintln(os.Stderr, "corpus file contained no values")
+ os.Exit(1)
+ }
+ }
+}
+
+var valRe = regexp.MustCompile(`^\[\]byte\(([^)]+)\)$`)
+
+-- check_cache/check_cache.go --
+//go:build ignore
+// +build ignore
+
+// check_cache.go checks that each file in the cached corpus has a []byte
+// of length at most 1. This verifies that at least one cached input is minimized.
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "os"
+ "path/filepath"
+ "regexp"
+ "strconv"
+)
+
+func main() {
+ dir := os.Args[1]
+ ents, err := os.ReadDir(dir)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ for _, ent := range ents {
+ name := filepath.Join(dir, ent.Name())
+ if good, err := checkCacheFile(name); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ } else if good {
+ os.Exit(0)
+ }
+ }
+ fmt.Fprintln(os.Stderr, "no cached inputs were minimized")
+ os.Exit(1)
+}
+
+func checkCacheFile(name string) (good bool, err error) {
+ data, err := os.ReadFile(name)
+ if err != nil {
+ return false, err
+ }
+ for _, line := range bytes.Split(data, []byte("\n")) {
+ m := valRe.FindSubmatch(line)
+ if m == nil {
+ continue
+ }
+ if s, err := strconv.Unquote(string(m[1])); err != nil {
+ return false, err
+ } else if len(s) <= 1 {
+ return true, nil
+ }
+ }
+ return false, nil
+}
+
+var valRe = regexp.MustCompile(`^\[\]byte\(([^)]+)\)$`)
diff --git a/src/cmd/go/testdata/script/test_fuzz_modcache.txt b/src/cmd/go/testdata/script/test_fuzz_modcache.txt
new file mode 100644
index 0000000..c0f18ea
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fuzz_modcache.txt
@@ -0,0 +1,58 @@
+# This test demonstrates the fuzz corpus behavior for packages outside of the main module.
+# (See https://golang.org/issue/48495.)
+
+[short] skip
+
+# Set -modcacherw so that the test behaves the same regardless of whether the
+# module cache is writable. (For example, on some platforms it can always be
+# written if the user is running as root.) At one point, a failing fuzz test
+# in a writable module cache would corrupt module checksums in the cache.
+env GOFLAGS=-modcacherw
+
+
+# When the upstream module has no test corpus, running 'go test' should succeed,
+# but 'go test -fuzz=.' should error out before running the test.
+# (It should NOT corrupt the module cache by writing out new fuzz inputs,
+# even if the cache is writable.)
+
+go get -t example.com/fuzzfail@v0.1.0
+go test example.com/fuzzfail
+
+! go test -fuzz=. example.com/fuzzfail
+! stdout .
+stderr '^cannot use -fuzz flag on package outside the main module$'
+
+go mod verify
+
+
+# If the module does include a test corpus, 'go test' (without '-fuzz') should
+# load that corpus and run the fuzz tests against it, but 'go test -fuzz=.'
+# should continue to be rejected.
+
+go get -t example.com/fuzzfail@v0.2.0
+
+! go test example.com/fuzzfail
+stdout '^\s*fuzzfail_test\.go:7: oops:'
+
+! go test -fuzz=. example.com/fuzzfail
+! stdout .
+stderr '^cannot use -fuzz flag on package outside the main module$'
+
+go mod verify
+
+
+# Packages in 'std' cannot be fuzzed when the corresponding GOROOT module is not
+# the main module — either the failures would not be recorded or the behavior of
+# the 'std' tests would change globally.
+
+! go test -fuzz . encoding/json
+stderr '^cannot use -fuzz flag on package outside the main module$'
+
+! go test -fuzz . cmd/buildid
+stderr '^cannot use -fuzz flag on package outside the main module$'
+
+
+-- go.mod --
+module example.com/m
+
+go 1.18
diff --git a/src/cmd/go/testdata/script/test_fuzz_multiple.txt b/src/cmd/go/testdata/script/test_fuzz_multiple.txt
new file mode 100644
index 0000000..c96112f
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fuzz_multiple.txt
@@ -0,0 +1,50 @@
+# This test checks that 'go test' prints a reasonable error when fuzzing is
+# enabled, and multiple package or multiple fuzz targets match.
+# TODO(#46312): support fuzzing multiple targets in multiple packages.
+
+[!fuzz] skip
+[short] skip
+env GOCACHE=$WORK/cache
+
+# With fuzzing disabled, multiple targets can be tested.
+go test ./...
+
+# With fuzzing enabled, at most one package may be tested,
+# even if only one package contains fuzz targets.
+! go test -fuzz=. ./...
+stderr '^cannot use -fuzz flag with multiple packages$'
+! go test -fuzz=. ./zero ./one
+stderr '^cannot use -fuzz flag with multiple packages$'
+go test -fuzz=. -fuzztime=1x ./one
+
+# With fuzzing enabled, at most one target in the same package may match.
+! go test -fuzz=. ./two
+stdout '^testing: will not fuzz, -fuzz matches more than one fuzz test: \[FuzzOne FuzzTwo\]$'
+go test -fuzz=FuzzTwo -fuzztime=1x ./two
+
+-- go.mod --
+module fuzz
+
+go 1.18
+-- zero/zero.go --
+package zero
+-- one/one_test.go --
+package one
+
+import "testing"
+
+func FuzzOne(f *testing.F) {
+ f.Fuzz(func(*testing.T, []byte) {})
+}
+-- two/two_test.go --
+package two
+
+import "testing"
+
+func FuzzOne(f *testing.F) {
+ f.Fuzz(func(*testing.T, []byte) {})
+}
+
+func FuzzTwo(f *testing.F) {
+ f.Fuzz(func(*testing.T, []byte) {})
+}
diff --git a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt
new file mode 100644
index 0000000..4b9b36d
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt
@@ -0,0 +1,323 @@
+[!fuzz] skip
+
+# Tests that a crash caused by a mutator-discovered input writes the bad input
+# to testdata, and fails+reports correctly. This tests the end-to-end behavior
+# of the mutator finding a crash while fuzzing, adding it as a regression test
+# to the seed corpus in testdata, and failing the next time the test is run.
+
+[short] skip
+env GOCACHE=$WORK/cache
+
+# Running the seed corpus for all of the targets should pass the first
+# time, since nothing in the seed corpus will cause a crash.
+go test
+
+# Running the fuzzer should find a crashing input quickly.
+! go test -fuzz=FuzzWithBug -fuzztime=100x -fuzzminimizetime=1000x
+stdout 'testdata[/\\]fuzz[/\\]FuzzWithBug[/\\]'
+stdout 'this input caused a crash!'
+go run check_testdata.go FuzzWithBug
+
+# Now, the failing bytes should have been added to the seed corpus for
+# the target, and should fail when run without fuzzing.
+! go test
+stdout 'FuzzWithBug/[a-f0-9]{16}'
+stdout 'this input caused a crash!'
+
+! go test -run=FuzzWithNilPanic -fuzz=FuzzWithNilPanic -fuzztime=100x -fuzzminimizetime=1000x
+stdout 'testdata[/\\]fuzz[/\\]FuzzWithNilPanic[/\\]'
+stdout 'panic called with nil argument|test executed panic.nil. or runtime.Goexit'
+go run check_testdata.go FuzzWithNilPanic
+
+! go test -run=FuzzWithGoexit -fuzz=FuzzWithGoexit -fuzztime=100x -fuzzminimizetime=1000x
+stdout 'testdata[/\\]fuzz[/\\]FuzzWithGoexit[/\\]'
+stdout 'runtime.Goexit'
+go run check_testdata.go FuzzWithGoexit
+
+! go test -run=FuzzWithFail -fuzz=FuzzWithFail -fuzztime=100x -fuzzminimizetime=1000x
+stdout 'testdata[/\\]fuzz[/\\]FuzzWithFail[/\\]'
+go run check_testdata.go FuzzWithFail
+
+! go test -run=FuzzWithLogFail -fuzz=FuzzWithLogFail -fuzztime=100x -fuzzminimizetime=1000x
+stdout 'testdata[/\\]fuzz[/\\]FuzzWithLogFail[/\\]'
+stdout 'logged something'
+go run check_testdata.go FuzzWithLogFail
+
+! go test -run=FuzzWithErrorf -fuzz=FuzzWithErrorf -fuzztime=100x -fuzzminimizetime=1000x
+stdout 'testdata[/\\]fuzz[/\\]FuzzWithErrorf[/\\]'
+stdout 'errorf was called here'
+go run check_testdata.go FuzzWithErrorf
+
+! go test -run=FuzzWithFatalf -fuzz=FuzzWithFatalf -fuzztime=100x -fuzzminimizetime=1000x
+stdout 'testdata[/\\]fuzz[/\\]FuzzWithFatalf[/\\]'
+stdout 'fatalf was called here'
+go run check_testdata.go FuzzWithFatalf
+
+! go test -run=FuzzWithBadExit -fuzz=FuzzWithBadExit -fuzztime=100x -fuzzminimizetime=1000x
+stdout 'testdata[/\\]fuzz[/\\]FuzzWithBadExit[/\\]'
+stdout '^\s+fuzzing process hung or terminated unexpectedly: exit status'
+go run check_testdata.go FuzzWithBadExit
+
+! go test -run=FuzzDeadlock -fuzz=FuzzDeadlock -fuzztime=100x -fuzzminimizetime=0x
+stdout 'testdata[/\\]fuzz[/\\]FuzzDeadlock[/\\]'
+stdout '^\s+fuzzing process hung or terminated unexpectedly: exit status'
+go run check_testdata.go FuzzDeadlock
+
+# Running the fuzzer should find a crashing input quickly for fuzzing two types.
+! go test -run=FuzzWithTwoTypes -fuzz=FuzzWithTwoTypes -fuzztime=100x -fuzzminimizetime=1000x
+stdout 'testdata[/\\]fuzz[/\\]FuzzWithTwoTypes[/\\]'
+stdout 'these inputs caused a crash!'
+go run check_testdata.go FuzzWithTwoTypes
+
+# Running the fuzzer should find a crashing input quickly for an integer.
+! go test -run=FuzzInt -fuzz=FuzzInt -fuzztime=100x -fuzzminimizetime=1000x
+stdout 'testdata[/\\]fuzz[/\\]FuzzInt[/\\]'
+stdout 'this input caused a crash!'
+go run check_testdata.go FuzzInt
+
+! go test -run=FuzzUint -fuzz=FuzzUint -fuzztime=100x -fuzzminimizetime=1000x
+stdout 'testdata[/\\]fuzz[/\\]FuzzUint[/\\]'
+stdout 'this input caused a crash!'
+go run check_testdata.go FuzzUint
+
+# Running the fuzzer should find a crashing input quickly for a bool.
+! go test -run=FuzzBool -fuzz=FuzzBool -fuzztime=100x -fuzzminimizetime=1000x
+stdout 'testdata[/\\]fuzz[/\\]FuzzBool[/\\]'
+stdout 'this input caused a crash!'
+go run check_testdata.go FuzzBool
+
+# Running the fuzzer should find a crashing input quickly for a float.
+! go test -run=FuzzFloat -fuzz=FuzzFloat -fuzztime=100x -fuzzminimizetime=1000x
+stdout 'testdata[/\\]fuzz[/\\]FuzzFloat[/\\]'
+stdout 'this input caused a crash!'
+go run check_testdata.go FuzzFloat
+
+# Running the fuzzer should find a crashing input quickly for a byte.
+! go test -run=FuzzByte -fuzz=FuzzByte -fuzztime=100x -fuzzminimizetime=1000x
+stdout 'testdata[/\\]fuzz[/\\]FuzzByte[/\\]'
+stdout 'this input caused a crash!'
+go run check_testdata.go FuzzByte
+
+# Running the fuzzer should find a crashing input quickly for a rune.
+! go test -run=FuzzRune -fuzz=FuzzRune -fuzztime=100x -fuzzminimizetime=1000x
+stdout 'testdata[/\\]fuzz[/\\]FuzzRune[/\\]'
+stdout 'this input caused a crash!'
+go run check_testdata.go FuzzRune
+
+# Running the fuzzer should find a crashing input quickly for a string.
+! go test -run=FuzzString -fuzz=FuzzString -fuzztime=100x -fuzzminimizetime=1000x
+stdout 'testdata[/\\]fuzz[/\\]FuzzString[/\\]'
+stdout 'this input caused a crash!'
+go run check_testdata.go FuzzString
+
+-- go.mod --
+module m
+
+go 1.16
+-- fuzz_crash_test.go --
+package fuzz_crash
+
+import (
+ "os"
+ "runtime"
+ "testing"
+)
+
+func FuzzWithBug(f *testing.F) {
+ f.Add([]byte("aa"))
+ f.Fuzz(func(t *testing.T, b []byte) {
+ if string(b) != "aa" {
+ panic("this input caused a crash!")
+ }
+ })
+}
+
+func FuzzWithNilPanic(f *testing.F) {
+ f.Add([]byte("aa"))
+ f.Fuzz(func(t *testing.T, b []byte) {
+ if string(b) != "aa" {
+ panic(nil)
+ }
+ })
+}
+
+func FuzzWithGoexit(f *testing.F) {
+ f.Add([]byte("aa"))
+ f.Fuzz(func(t *testing.T, b []byte) {
+ if string(b) != "aa" {
+ runtime.Goexit()
+ }
+ })
+}
+
+func FuzzWithFail(f *testing.F) {
+ f.Add([]byte("aa"))
+ f.Fuzz(func(t *testing.T, b []byte) {
+ if string(b) != "aa" {
+ t.Fail()
+ }
+ })
+}
+
+func FuzzWithLogFail(f *testing.F) {
+ f.Add([]byte("aa"))
+ f.Fuzz(func(t *testing.T, b []byte) {
+ if string(b) != "aa" {
+ t.Log("logged something")
+ t.Fail()
+ }
+ })
+}
+
+func FuzzWithErrorf(f *testing.F) {
+ f.Add([]byte("aa"))
+ f.Fuzz(func(t *testing.T, b []byte) {
+ if string(b) != "aa" {
+ t.Errorf("errorf was called here")
+ }
+ })
+}
+
+func FuzzWithFatalf(f *testing.F) {
+ f.Add([]byte("aa"))
+ f.Fuzz(func(t *testing.T, b []byte) {
+ if string(b) != "aa" {
+ t.Fatalf("fatalf was called here")
+ }
+ })
+}
+
+func FuzzWithBadExit(f *testing.F) {
+ f.Add([]byte("aa"))
+ f.Fuzz(func(t *testing.T, b []byte) {
+ if string(b) != "aa" {
+ os.Exit(1)
+ }
+ })
+}
+
+func FuzzDeadlock(f *testing.F) {
+ f.Add(int(0))
+ f.Fuzz(func(t *testing.T, n int) {
+ if n != 0 {
+ select {}
+ }
+ })
+}
+
+func FuzzWithTwoTypes(f *testing.F) {
+ f.Fuzz(func(t *testing.T, a, b []byte) {
+ if len(a) > 0 && len(b) > 0 {
+ panic("these inputs caused a crash!")
+ }
+ })
+}
+
+func FuzzInt(f *testing.F) {
+ f.Add(0)
+ f.Fuzz(func(t *testing.T, a int) {
+ if a != 0 {
+ panic("this input caused a crash!")
+ }
+ })
+}
+
+func FuzzUint(f *testing.F) {
+ f.Add(uint(0))
+ f.Fuzz(func(t *testing.T, a uint) {
+ if a != 0 {
+ panic("this input caused a crash!")
+ }
+ })
+}
+
+func FuzzBool(f *testing.F) {
+ f.Add(false)
+ f.Fuzz(func(t *testing.T, a bool) {
+ if a {
+ panic("this input caused a crash!")
+ }
+ })
+}
+
+func FuzzFloat(f *testing.F) {
+ f.Fuzz(func(t *testing.T, a float64) {
+ if a != 0 {
+ panic("this input caused a crash!")
+ }
+ })
+}
+
+func FuzzByte(f *testing.F) {
+ f.Add(byte(0))
+ f.Fuzz(func(t *testing.T, a byte) {
+ if a != 0 {
+ panic("this input caused a crash!")
+ }
+ })
+}
+
+func FuzzRune(f *testing.F) {
+ f.Add(rune(0))
+ f.Fuzz(func(t *testing.T, a rune) {
+ if a != 0 {
+ panic("this input caused a crash!")
+ }
+ })
+}
+
+func FuzzString(f *testing.F) {
+ f.Add("")
+ f.Fuzz(func(t *testing.T, a string) {
+ if a != "" {
+ panic("this input caused a crash!")
+ }
+ })
+}
+
+-- check_testdata.go --
+// +build ignore
+
+package main
+
+import (
+ "bytes"
+ "crypto/sha256"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+)
+
+func main() {
+ target := os.Args[1]
+ dir := filepath.Join("testdata/fuzz", target)
+
+ files, err := ioutil.ReadDir(dir)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+
+ if len(files) == 0 {
+ fmt.Fprintf(os.Stderr, "expect at least one new mutation to be written to testdata\n")
+ os.Exit(1)
+ }
+
+ fname := files[0].Name()
+ contents, err := ioutil.ReadFile(filepath.Join(dir, fname))
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ if bytes.Equal(contents, []byte("aa")) {
+ fmt.Fprintf(os.Stderr, "newly written testdata entry was not mutated\n")
+ os.Exit(1)
+ }
+ // The hash of the bytes in the file should match the filename.
+ h := []byte(fmt.Sprintf("%x", sha256.Sum256(contents)))
+ if !bytes.HasPrefix(h, []byte(fname)) {
+ fmt.Fprintf(os.Stderr, "hash of bytes %q does not match filename %q\n", h, fname)
+ os.Exit(1)
+ }
+}
diff --git a/src/cmd/go/testdata/script/test_fuzz_mutate_fail.txt b/src/cmd/go/testdata/script/test_fuzz_mutate_fail.txt
new file mode 100644
index 0000000..213b73a
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fuzz_mutate_fail.txt
@@ -0,0 +1,103 @@
+[!fuzz] skip
+
+# Check that if a worker does not call F.Fuzz or calls F.Fail first,
+# 'go test' exits non-zero and no crasher is recorded.
+
+[short] skip
+env GOCACHE=$WORK/cache
+
+! go test -fuzz=FuzzReturn
+! exists testdata
+
+! go test -fuzz=FuzzSkip
+! exists testdata
+
+! go test -fuzz=FuzzFail
+! exists testdata
+
+! go test -fuzz=FuzzPanic
+! exists testdata
+
+! go test -fuzz=FuzzNilPanic
+! exists testdata
+
+! go test -fuzz=FuzzGoexit
+! exists testdata
+
+! go test -fuzz=FuzzExit
+! exists testdata
+
+-- go.mod --
+module m
+
+go 1.17
+-- fuzz_fail_test.go --
+package fuzz_fail
+
+import (
+ "flag"
+ "os"
+ "runtime"
+ "testing"
+)
+
+func isWorker() bool {
+ f := flag.Lookup("test.fuzzworker")
+ if f == nil {
+ return false
+ }
+ get, ok := f.Value.(flag.Getter)
+ if !ok {
+ return false
+ }
+ return get.Get() == interface{}(true)
+}
+
+func FuzzReturn(f *testing.F) {
+ if isWorker() {
+ return
+ }
+ f.Fuzz(func(*testing.T, []byte) {})
+}
+
+func FuzzSkip(f *testing.F) {
+ if isWorker() {
+ f.Skip()
+ }
+ f.Fuzz(func(*testing.T, []byte) {})
+}
+
+func FuzzFail(f *testing.F) {
+ if isWorker() {
+ f.Fail()
+ }
+ f.Fuzz(func(*testing.T, []byte) {})
+}
+
+func FuzzPanic(f *testing.F) {
+ if isWorker() {
+ panic("nope")
+ }
+ f.Fuzz(func(*testing.T, []byte) {})
+}
+
+func FuzzNilPanic(f *testing.F) {
+ if isWorker() {
+ panic(nil)
+ }
+ f.Fuzz(func(*testing.T, []byte) {})
+}
+
+func FuzzGoexit(f *testing.F) {
+ if isWorker() {
+ runtime.Goexit()
+ }
+ f.Fuzz(func(*testing.T, []byte) {})
+}
+
+func FuzzExit(f *testing.F) {
+ if isWorker() {
+ os.Exit(99)
+ }
+ f.Fuzz(func(*testing.T, []byte) {})
+}
diff --git a/src/cmd/go/testdata/script/test_fuzz_mutator.txt b/src/cmd/go/testdata/script/test_fuzz_mutator.txt
new file mode 100644
index 0000000..cc1f989
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fuzz_mutator.txt
@@ -0,0 +1,166 @@
+[!fuzz] skip
+
+# Test basic fuzzing mutator behavior.
+#
+# fuzz_test.go has two fuzz targets (FuzzA, FuzzB) which both add a seed value.
+# Each fuzz function writes the input to a log file. The coordinator and worker
+# use separate log files. check_logs.go verifies that the coordinator only
+# tests seed values and the worker tests mutated values on the fuzz target.
+
+[short] skip
+env GOCACHE=$WORK/cache
+
+go test -fuzz=FuzzA -fuzztime=100x -parallel=1 -log=fuzz
+go run check_logs.go fuzz fuzz.worker
+
+# TODO(b/181800488): remove -parallel=1, here and below. For now, when a
+# crash is found, all workers keep running, wasting resources and reducing
+# the number of executions available to the minimizer, increasing flakiness.
+
+# Test that the mutator is good enough to find several unique mutations.
+! go test -fuzz=FuzzMutator -parallel=1 -fuzztime=100x mutator_test.go
+! stdout '^ok'
+stdout FAIL
+stdout 'mutator found enough unique mutations'
+
+-- go.mod --
+module m
+
+go 1.16
+-- fuzz_test.go --
+package fuzz_test
+
+import (
+ "flag"
+ "fmt"
+ "os"
+ "testing"
+)
+
+var (
+ logPath = flag.String("log", "", "path to log file")
+ logFile *os.File
+)
+
+func TestMain(m *testing.M) {
+ flag.Parse()
+ var err error
+ logFile, err = os.OpenFile(*logPath, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666)
+ if os.IsExist(err) {
+ *logPath += ".worker"
+ logFile, err = os.OpenFile(*logPath, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666)
+ }
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ os.Exit(m.Run())
+}
+
+func FuzzA(f *testing.F) {
+ f.Add([]byte("seed"))
+ f.Fuzz(func(t *testing.T, b []byte) {
+ fmt.Fprintf(logFile, "FuzzA %q\n", b)
+ })
+}
+
+func FuzzB(f *testing.F) {
+ f.Add([]byte("seed"))
+ f.Fuzz(func(t *testing.T, b []byte) {
+ fmt.Fprintf(logFile, "FuzzB %q\n", b)
+ })
+}
+
+-- check_logs.go --
+// +build ignore
+
+package main
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "io"
+ "os"
+ "strings"
+)
+
+func main() {
+ coordPath, workerPath := os.Args[1], os.Args[2]
+
+ coordLog, err := os.Open(coordPath)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ defer coordLog.Close()
+ if err := checkCoordLog(coordLog); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+
+ workerLog, err := os.Open(workerPath)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ defer workerLog.Close()
+ if err := checkWorkerLog(workerLog); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+}
+
+func checkCoordLog(r io.Reader) error {
+ b, err := io.ReadAll(r)
+ if err != nil {
+ return err
+ }
+ if string(bytes.TrimSpace(b)) != `FuzzB "seed"` {
+ return fmt.Errorf("coordinator: did not test FuzzB seed")
+ }
+ return nil
+}
+
+func checkWorkerLog(r io.Reader) error {
+ scan := bufio.NewScanner(r)
+ var sawAMutant bool
+ for scan.Scan() {
+ line := scan.Text()
+ if !strings.HasPrefix(line, "FuzzA ") {
+ return fmt.Errorf("worker: tested something other than target: %s", line)
+ }
+ if strings.TrimPrefix(line, "FuzzA ") != `"seed"` {
+ sawAMutant = true
+ }
+ }
+ if err := scan.Err(); err != nil && err != bufio.ErrTooLong {
+ return err
+ }
+ if !sawAMutant {
+ return fmt.Errorf("worker: did not test any mutants")
+ }
+ return nil
+}
+-- mutator_test.go --
+package fuzz_test
+
+import (
+ "testing"
+)
+
+// TODO(katiehockman): re-work this test once we have a better fuzzing engine
+// (ie. more mutations, and compiler instrumentation)
+func FuzzMutator(f *testing.F) {
+ // TODO(katiehockman): simplify this once we can dedupe crashes (e.g.
+ // replace map with calls to panic, and simply count the number of crashes
+ // that were added to testdata)
+ crashes := make(map[string]bool)
+ // No seed corpus initiated
+ f.Fuzz(func(t *testing.T, b []byte) {
+ crashes[string(b)] = true
+ if len(crashes) >= 10 {
+ panic("mutator found enough unique mutations")
+ }
+ })
+}
diff --git a/src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt b/src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt
new file mode 100644
index 0000000..3b005c9
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt
@@ -0,0 +1,75 @@
+# TODO(jayconrod): support shared memory on more platforms.
+[!GOOS:darwin] [!GOOS:linux] [!GOOS:windows] skip
+
+# Verify that the fuzzing engine records the actual crashing input, even when
+# a worker process terminates without communicating the crashing input back
+# to the coordinator.
+
+[short] skip
+env GOCACHE=$WORK/cache
+
+# Start fuzzing. The worker crashes after 100 iterations.
+# The fuzz function writes the crashing input to "want" before exiting.
+# The fuzzing engine reconstructs the crashing input and saves it to testdata.
+! exists want
+! go test -fuzz=. -parallel=1 -fuzztime=110x -fuzzminimizetime=10x -v
+stdout '^\s+fuzzing process hung or terminated unexpectedly: exit status'
+stdout 'Failing input written to testdata'
+
+# Run the fuzz target without fuzzing. The fuzz function is called with the
+# crashing input in testdata. The test passes if that input is identical to
+# the one saved in "want".
+exists want
+go test -want=want
+
+-- go.mod --
+module fuzz
+
+go 1.17
+-- fuzz_test.go --
+package fuzz
+
+import (
+ "bytes"
+ "flag"
+ "os"
+ "testing"
+)
+
+var wantFlag = flag.String("want", "", "file containing previous crashing input")
+
+func FuzzRepeat(f *testing.F) {
+ i := 0
+ f.Fuzz(func(t *testing.T, b []byte) {
+ i++
+ if i == 100 {
+ f, err := os.OpenFile("want", os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0666)
+ if err != nil {
+ // Couldn't create the file. Return without crashing, and try
+ // again.
+ i--
+ t.Skip(err)
+ }
+ if _, err := f.Write(b); err != nil {
+ // We already created the file, so if we failed to write it
+ // there's not much we can do. The test will fail anyway, but
+ // at least make sure the error is logged to stdout.
+ t.Fatal(err)
+ }
+ if err := f.Close(); err != nil {
+ t.Fatal(err)
+ }
+ os.Exit(1) // crash without communicating
+ }
+
+ if *wantFlag != "" {
+ want, err := os.ReadFile(*wantFlag)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !bytes.Equal(want, b) {
+ t.Fatalf("inputs are not equal!\n got: %q\nwant:%q", b, want)
+ }
+ }
+ })
+}
diff --git a/src/cmd/go/testdata/script/test_fuzz_non_crash_signal.txt b/src/cmd/go/testdata/script/test_fuzz_non_crash_signal.txt
new file mode 100644
index 0000000..94a0421
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fuzz_non_crash_signal.txt
@@ -0,0 +1,76 @@
+# NOTE: this test is skipped on Windows, since there's no concept of signals.
+# When a process terminates another process, it provides an exit code.
+[GOOS:windows] skip
+[!fuzz] skip
+[short] skip
+env GOCACHE=$WORK/cache
+
+# FuzzNonCrash sends itself a signal that does not appear to be a crash.
+# We should not save a crasher.
+! go test -fuzz=FuzzNonCrash
+! exists testdata
+! stdout unreachable
+! stderr unreachable
+stdout 'fuzzing process terminated by unexpected signal; no crash will be recorded: signal: terminated'
+
+# FuzzKill sends itself a signal that cannot be caught by the worker process
+# and does not appear to be a crash.
+# We should not save a crasher.
+! go test -fuzz=FuzzKill
+! exists testdata
+! stdout unreachable
+! stderr unreachable
+stdout 'fuzzing process terminated by unexpected signal; no crash will be recorded: signal: killed'
+
+# FuzzCrash sends itself a signal that looks like a crash.
+# We should save a crasher.
+! go test -fuzz=FuzzCrash
+exists testdata/fuzz/FuzzCrash
+stdout '^\s+fuzzing process hung or terminated unexpectedly: exit status'
+
+-- go.mod --
+module test
+
+go 1.17
+-- fuzz_posix_test.go --
+// +build darwin freebsd linux
+
+package fuzz
+
+import (
+ "syscall"
+ "testing"
+)
+
+func FuzzNonCrash(f *testing.F) {
+ f.Fuzz(func(*testing.T, bool) {
+ pid := syscall.Getpid()
+ if err := syscall.Kill(pid, syscall.SIGTERM); err != nil {
+ panic(err)
+ }
+ // signal may not be received immediately. Wait for it.
+ select{}
+ })
+}
+
+func FuzzKill(f *testing.F) {
+ f.Fuzz(func(*testing.T, bool) {
+ pid := syscall.Getpid()
+ if err := syscall.Kill(pid, syscall.SIGKILL); err != nil {
+ panic(err)
+ }
+ // signal may not be received immediately. Wait for it.
+ select{}
+ })
+}
+
+func FuzzCrash(f *testing.F) {
+ f.Fuzz(func(*testing.T, bool) {
+ pid := syscall.Getpid()
+ if err := syscall.Kill(pid, syscall.SIGILL); err != nil {
+ panic(err)
+ }
+ // signal may not be received immediately. Wait for it.
+ select{}
+ })
+}
diff --git a/src/cmd/go/testdata/script/test_fuzz_parallel.txt b/src/cmd/go/testdata/script/test_fuzz_parallel.txt
new file mode 100644
index 0000000..8ff965a
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fuzz_parallel.txt
@@ -0,0 +1,67 @@
+[!fuzz] skip
+[short] skip
+env GOCACHE=$WORK/cache
+
+# When running seed inputs, T.Parallel should let multiple inputs run in
+# parallel.
+go test -run=FuzzSeed
+
+# When fuzzing, T.Parallel should be safe to call, but it should have no effect.
+# We just check that it doesn't hang, which would be the most obvious
+# failure mode.
+# TODO(jayconrod): check for the string "after T.Parallel". It's not printed
+# by 'go test', so we can't distinguish that crasher from some other panic.
+! go test -run=FuzzMutate -fuzz=FuzzMutate
+exists testdata/fuzz/FuzzMutate
+
+# Testdata should now contain a corpus entry which will fail FuzzMutate.
+# Run the test without fuzzing, setting -parallel to different values to make
+# sure it fails, and doesn't hang.
+! go test -run=FuzzMutate -parallel=1
+! go test -run=FuzzMutate -parallel=2
+! go test -run=FuzzMutate -parallel=4
+
+-- go.mod --
+module fuzz_parallel
+
+go 1.17
+-- fuzz_parallel_test.go --
+package fuzz_parallel
+
+import (
+ "sort"
+ "sync"
+ "testing"
+)
+
+func FuzzSeed(f *testing.F) {
+ for _, v := range [][]byte{{'a'}, {'b'}, {'c'}} {
+ f.Add(v)
+ }
+
+ var mu sync.Mutex
+ var before, after []byte
+ f.Cleanup(func() {
+ sort.Slice(after, func(i, j int) bool { return after[i] < after[j] })
+ got := string(before) + string(after)
+ want := "abcabc"
+ if got != want {
+ f.Fatalf("got %q; want %q", got, want)
+ }
+ })
+
+ f.Fuzz(func(t *testing.T, b []byte) {
+ before = append(before, b...)
+ t.Parallel()
+ mu.Lock()
+ after = append(after, b...)
+ mu.Unlock()
+ })
+}
+
+func FuzzMutate(f *testing.F) {
+ f.Fuzz(func(t *testing.T, _ []byte) {
+ t.Parallel()
+ t.Error("after T.Parallel")
+ })
+}
diff --git a/src/cmd/go/testdata/script/test_fuzz_profile_flags.txt b/src/cmd/go/testdata/script/test_fuzz_profile_flags.txt
new file mode 100644
index 0000000..5434c72
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fuzz_profile_flags.txt
@@ -0,0 +1,38 @@
+[!fuzz] skip
+
+! go test -fuzz=FuzzTrivial -coverprofile=prof
+! stdout .
+stderr '^cannot use -coverprofile flag with -fuzz flag$'
+
+! go test -fuzz=FuzzTrivial -blockprofile=prof
+! stdout .
+stderr '^cannot use -blockprofile flag with -fuzz flag$'
+
+! go test -fuzz=FuzzTrivial -cpuprofile=prof
+! stdout .
+stderr '^cannot use -cpuprofile flag with -fuzz flag$'
+
+! go test -fuzz=FuzzTrivial -memprofile=prof
+! stdout .
+stderr '^cannot use -memprofile flag with -fuzz flag$'
+
+! go test -fuzz=FuzzTrivial -mutexprofile=prof
+! stdout .
+stderr '^cannot use -mutexprofile flag with -fuzz flag$'
+
+! go test -fuzz=FuzzTrivial -trace=prof
+! stdout .
+stderr '^cannot use -trace flag with -fuzz flag$'
+
+-- go.mod --
+module example
+
+go 1.18
+-- fuzz_test.go --
+package example
+
+import "testing"
+
+func FuzzTrivial(f *testing.F) {
+ f.Fuzz(func(t *testing.T, _ []byte) {})
+}
diff --git a/src/cmd/go/testdata/script/test_fuzz_return.txt b/src/cmd/go/testdata/script/test_fuzz_return.txt
new file mode 100644
index 0000000..63275aa
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fuzz_return.txt
@@ -0,0 +1,19 @@
+[short] skip
+
+! go test .
+stdout '^panic: testing: fuzz target must not return a value \[recovered\]$'
+
+-- go.mod --
+module test
+go 1.18
+-- x_test.go --
+package test
+
+import "testing"
+
+func FuzzReturnErr(f *testing.F) {
+ f.Add("hello, validation!")
+ f.Fuzz(func(t *testing.T, in string) string {
+ return in
+ })
+}
diff --git a/src/cmd/go/testdata/script/test_fuzz_run.txt b/src/cmd/go/testdata/script/test_fuzz_run.txt
new file mode 100644
index 0000000..99a4413
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fuzz_run.txt
@@ -0,0 +1,143 @@
+[!fuzz] skip
+[short] skip
+env GOCACHE=$WORK/cache
+
+# Tests which verify the behavior and command line output when
+# running a fuzz target as a unit test.
+
+# Tests without -run.
+
+! go test
+stdout FAIL
+stdout 'error here'
+
+! go test -v
+stdout FAIL
+stdout 'error here'
+stdout '=== RUN FuzzFoo/thisfails'
+stdout '--- FAIL: FuzzFoo/thisfails'
+stdout '=== RUN FuzzFoo/thispasses'
+stdout '--- PASS: FuzzFoo/thispasses'
+
+# Tests where -run matches all seed corpora.
+
+! go test -run FuzzFoo/this
+stdout FAIL
+stdout 'error here'
+! stdout 'no tests to run'
+
+! go test -run /this
+stdout FAIL
+stdout 'error here'
+! stdout 'no tests to run'
+
+! go test -v -run FuzzFoo/this
+stdout FAIL
+stdout 'error here'
+stdout '=== RUN FuzzFoo/thisfails'
+stdout '--- FAIL: FuzzFoo/thisfails'
+stdout '=== RUN FuzzFoo/thispasses'
+stdout '--- PASS: FuzzFoo/thispasses'
+! stdout 'no tests to run'
+
+! go test -v -run /this
+stdout FAIL
+stdout 'error here'
+stdout '=== RUN FuzzFoo/thisfails'
+stdout '--- FAIL: FuzzFoo/thisfails'
+stdout '=== RUN FuzzFoo/thispasses'
+stdout '--- PASS: FuzzFoo/thispasses'
+! stdout 'no tests to run'
+
+# Tests where -run only matches one seed corpus which passes.
+
+go test -run FuzzFoo/thispasses
+stdout ok
+! stdout 'no tests to run'
+
+go test -run /thispasses
+stdout ok
+! stdout 'no tests to run'
+
+# Same tests in verbose mode
+go test -v -run FuzzFoo/thispasses
+stdout '=== RUN FuzzFoo/thispasses'
+stdout '--- PASS: FuzzFoo/thispasses'
+! stdout '=== RUN FuzzFoo/thisfails'
+! stdout 'no tests to run'
+
+go test -v -run /thispasses
+stdout '=== RUN FuzzFoo/thispasses'
+stdout '--- PASS: FuzzFoo/thispasses'
+! stdout '=== RUN FuzzFoo/thisfails'
+! stdout 'no tests to run'
+
+# Tests where -run only matches one seed corpus which fails.
+
+! go test -run FuzzFoo/thisfails
+stdout FAIL
+stdout 'error here'
+! stdout 'no tests to run'
+
+! go test -run /thisfails
+stdout FAIL
+stdout 'error here'
+! stdout 'no tests to run'
+
+! go test -v -run FuzzFoo/thisfails
+stdout 'error here'
+stdout '=== RUN FuzzFoo/thisfails'
+stdout '--- FAIL: FuzzFoo/thisfails'
+! stdout '=== RUN FuzzFoo/thispasses'
+! stdout 'no tests to run'
+
+! go test -v -run /thisfails
+stdout 'error here'
+stdout '=== RUN FuzzFoo/thisfails'
+stdout '--- FAIL: FuzzFoo/thisfails'
+! stdout '=== RUN FuzzFoo/thispasses'
+! stdout 'no tests to run'
+
+# Tests where -run doesn't match any seed corpora.
+
+go test -run FuzzFoo/nomatch
+stdout ok
+
+go test -run /nomatch
+stdout ok
+
+go test -v -run FuzzFoo/nomatch
+stdout '=== RUN FuzzFoo'
+stdout '--- PASS: FuzzFoo'
+stdout ok
+! stdout 'no tests to run'
+
+go test -v -run /nomatch
+stdout '=== RUN FuzzFoo'
+stdout '--- PASS: FuzzFoo'
+stdout ok
+! stdout 'no tests to run'
+
+-- go.mod --
+module example.com/x
+
+go 1.16
+-- x_test.go --
+package x
+
+import "testing"
+
+func FuzzFoo(f *testing.F) {
+ f.Add("this is fine")
+ f.Fuzz(func(t *testing.T, s string) {
+ if s == "fails" {
+ t.Error("error here")
+ }
+ })
+}
+-- testdata/fuzz/FuzzFoo/thisfails --
+go test fuzz v1
+string("fails")
+-- testdata/fuzz/FuzzFoo/thispasses --
+go test fuzz v1
+string("passes")
diff --git a/src/cmd/go/testdata/script/test_fuzz_seed_corpus.txt b/src/cmd/go/testdata/script/test_fuzz_seed_corpus.txt
new file mode 100644
index 0000000..3e3fbad
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fuzz_seed_corpus.txt
@@ -0,0 +1,203 @@
+[!fuzz-instrumented] skip
+[short] skip
+env GOCACHE=$WORK/cache
+
+# Test that fuzzing a target with a failure in f.Add prints the crash
+# and doesn't write anything to testdata/fuzz
+! go test -fuzz=FuzzWithAdd -run=FuzzWithAdd -fuzztime=1x
+! stdout ^ok
+! stdout 'Failing input written to testdata[/\\]fuzz[/\\]FuzzWithAdd[/\\]'
+stdout FAIL
+
+# Test that fuzzing a target with a success in f.Add and a fuzztime of only
+# 1 does not produce a crash.
+go test -fuzz=FuzzWithGoodAdd -run=FuzzWithGoodAdd -fuzztime=1x
+stdout ok
+! stdout FAIL
+
+# Test that fuzzing a target with a failure in testdata/fuzz prints the crash
+# and doesn't write anything to testdata/fuzz
+! go test -fuzz=FuzzWithTestdata -run=FuzzWithTestdata -fuzztime=1x
+! stdout ^ok
+! stdout 'Failing input written to testdata[/\\]fuzz[/\\]FuzzWithTestdata[/\\]'
+stdout 'failure while testing seed corpus entry: FuzzWithTestdata/1'
+stdout FAIL
+
+# Test that fuzzing a target with no seed corpus or cache finds a crash, prints
+# it, and write it to testdata
+! go test -fuzz=FuzzWithNoCache -run=FuzzWithNoCache -fuzztime=1x
+! stdout ^ok
+stdout 'Failing input written to testdata[/\\]fuzz[/\\]FuzzWithNoCache[/\\]'
+stdout FAIL
+
+# Write a crashing input to the cache
+mkdir $GOCACHE/fuzz/example.com/x/FuzzWithCache
+cp cache-file $GOCACHE/fuzz/example.com/x/FuzzWithCache/1
+
+# Test that fuzzing a target with a failure in the cache prints the crash
+# and writes this as a "new" crash to testdata/fuzz
+! go test -fuzz=FuzzWithCache -run=FuzzWithCache -fuzztime=1x
+! stdout ^ok
+stdout 'Failing input written to testdata[/\\]fuzz[/\\]FuzzWithCache[/\\]'
+stdout FAIL
+
+# Write a crashing input to the cache
+mkdir $GOCACHE/fuzz/example.com/x/FuzzWithMinimizableCache
+cp cache-file-bytes $GOCACHE/fuzz/example.com/x/FuzzWithMinimizableCache/1
+
+# Test that fuzzing a target with a failure in the cache minimizes it and writes
+# the new crash to testdata/fuzz
+! go test -fuzz=FuzzWithMinimizableCache -run=FuzzWithMinimizableCache -fuzztime=10000x
+! stdout ^ok
+stdout 'gathering baseline coverage'
+stdout 'got the minimum size!'
+stdout 'contains a non-zero byte of length 10'
+stdout 'Failing input written to testdata[/\\]fuzz[/\\]FuzzWithMinimizableCache[/\\]'
+stdout FAIL
+# Make sure this crash didn't come from fuzzing
+# (the log line that states fuzzing began shouldn't have printed)
+! stdout 'execs'
+
+# Clear the fuzz cache and make sure it's gone
+go clean -fuzzcache
+! exists $GOCACHE/fuzz
+
+# The tests below should operate the exact same as the previous tests. If -fuzz
+# is enabled, then whatever target is going to be fuzzed shouldn't be run by
+# anything other than the workers.
+
+# Test that fuzzing a target (with -run=None set) with a failure in f.Add prints
+# the crash and doesn't write anything to testdata/fuzz -fuzztime=1x
+! go test -fuzz=FuzzWithAdd -run=None
+! stdout ^ok
+! stdout 'Failing input written to testdata[/\\]fuzz[/\\]FuzzWithAdd[/\\]'
+stdout FAIL
+
+# Test that fuzzing a target (with -run=None set) with a success in f.Add and a
+# fuzztime of only 1 does not produce a crash.
+go test -fuzz=FuzzWithGoodAdd -run=None -fuzztime=1x
+stdout ok
+! stdout FAIL
+
+# Test that fuzzing a target (with -run=None set) with a failure in
+# testdata/fuzz prints the crash and doesn't write anything to testdata/fuzz
+! go test -fuzz=FuzzWithTestdata -run=None -fuzztime=1x
+! stdout ^ok
+! stdout 'Failing input written to testdata[/\\]fuzz[/\\]FuzzWithTestdata[/\\]'
+stdout FAIL
+
+# Write a crashing input to the cache
+mkdir $GOCACHE/fuzz/example.com/x/FuzzRunNoneWithCache
+cp cache-file $GOCACHE/fuzz/example.com/x/FuzzRunNoneWithCache/1
+
+# Test that fuzzing a target (with -run=None set) with a failure in the cache
+# prints the crash and writes this as a "new" crash to testdata/fuzz
+! go test -fuzz=FuzzRunNoneWithCache -run=None -fuzztime=1x
+! stdout ^ok
+stdout 'Failing input written to testdata[/\\]fuzz[/\\]FuzzRunNoneWithCache[/\\]'
+stdout FAIL
+
+# Clear the fuzz cache and make sure it's gone
+go clean -fuzzcache
+! exists $GOCACHE/fuzz
+
+# The tests below should operate the exact same way for the previous tests with
+# a seed corpus (namely, they should still fail). However, the binary is built
+# without instrumentation, so this should be a "testing only" run which executes
+# the seed corpus before attempting to fuzz.
+
+go test -c
+! exec ./x.test$GOEXE -test.fuzz=FuzzWithAdd -test.run=FuzzWithAdd -test.fuzztime=1x -test.fuzzcachedir=$WORK/cache
+! stdout ^ok
+! stdout 'Failing input written to testdata[/\\]fuzz[/\\]FuzzWithAdd[/\\]'
+stdout FAIL
+stderr warning
+
+go test -c
+! exec ./x.test$GOEXE -test.fuzz=FuzzWithTestdata -test.run=FuzzWithTestdata -test.fuzztime=1x -test.fuzzcachedir=$WORK/cache
+! stdout ^ok
+! stdout 'Failing input written to testdata[/\\]fuzz[/\\]FuzzWithTestdata[/\\]'
+stdout FAIL
+stderr warning
+
+-- go.mod --
+module example.com/x
+
+go 1.16
+-- x_test.go --
+package x
+
+import "testing"
+
+func FuzzWithAdd(f *testing.F) {
+ f.Add(10)
+ f.Fuzz(func(t *testing.T, i int) {
+ if i == 10 {
+ t.Error("bad thing here")
+ }
+ })
+}
+
+func FuzzWithGoodAdd(f *testing.F) {
+ f.Add(10)
+ f.Fuzz(func(t *testing.T, i int) {
+ if i != 10 {
+ t.Error("bad thing here")
+ }
+ })
+}
+
+func FuzzWithTestdata(f *testing.F) {
+ f.Fuzz(func(t *testing.T, i int) {
+ if i == 10 {
+ t.Error("bad thing here")
+ }
+ })
+}
+
+func FuzzWithNoCache(f *testing.F) {
+ f.Fuzz(func(t *testing.T, i int) {
+ t.Error("bad thing here")
+ })
+}
+
+func FuzzWithCache(f *testing.F) {
+ f.Fuzz(func(t *testing.T, i int) {
+ if i == 10 {
+ t.Error("bad thing here")
+ }
+ })
+}
+
+func FuzzWithMinimizableCache(f *testing.F) {
+ f.Fuzz(func(t *testing.T, b []byte) {
+ if len(b) < 10 {
+ return
+ }
+ for _, n := range b {
+ if n != 0 {
+ if len(b) == 10 {
+ t.Log("got the minimum size!")
+ }
+ t.Fatalf("contains a non-zero byte of length %d", len(b))
+ }
+ }
+ })
+}
+
+func FuzzRunNoneWithCache(f *testing.F) {
+ f.Fuzz(func(t *testing.T, i int) {
+ if i == 10 {
+ t.Error("bad thing here")
+ }
+ })
+}
+-- testdata/fuzz/FuzzWithTestdata/1 --
+go test fuzz v1
+int(10)
+-- cache-file --
+go test fuzz v1
+int(10)
+-- cache-file-bytes --
+go test fuzz v1
+[]byte("11111111111111111111")
diff --git a/src/cmd/go/testdata/script/test_fuzz_setenv.txt b/src/cmd/go/testdata/script/test_fuzz_setenv.txt
new file mode 100644
index 0000000..1370cd8
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fuzz_setenv.txt
@@ -0,0 +1,46 @@
+[!fuzz] skip
+[short] skip
+env GOCACHE=$WORK/cache
+
+go test -fuzz=FuzzA -fuzztime=100x fuzz_setenv_test.go
+
+-- fuzz_setenv_test.go --
+package fuzz
+
+import (
+ "flag"
+ "os"
+ "testing"
+)
+
+func FuzzA(f *testing.F) {
+ if s := os.Getenv("TEST_FUZZ_SETENV_A"); isWorker() && s == "" {
+ f.Fatal("environment variable not set")
+ } else if !isWorker() && s != "" {
+ f.Fatal("environment variable already set")
+ }
+ f.Setenv("TEST_FUZZ_SETENV_A", "A")
+ if os.Getenv("TEST_FUZZ_SETENV_A") == "" {
+ f.Fatal("Setenv did not set environment variable")
+ }
+ f.Fuzz(func(*testing.T, []byte) {})
+}
+
+func FuzzB(f *testing.F) {
+ if os.Getenv("TEST_FUZZ_SETENV_A") != "" {
+ f.Fatal("environment variable not cleared after FuzzA")
+ }
+ f.Skip()
+}
+
+func isWorker() bool {
+ f := flag.Lookup("test.fuzzworker")
+ if f == nil {
+ return false
+ }
+ get, ok := f.Value.(flag.Getter)
+ if !ok {
+ return false
+ }
+ return get.Get() == interface{}(true)
+}
diff --git a/src/cmd/go/testdata/script/test_fuzz_test_race.txt b/src/cmd/go/testdata/script/test_fuzz_test_race.txt
new file mode 100644
index 0000000..1bed47d
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fuzz_test_race.txt
@@ -0,0 +1,40 @@
+# Test that when both race detection and coverage instrumentation are enabled,
+# and seed values are being executed, the race detector isn't mistakenly
+# triggered.
+
+[short] skip
+[!fuzz] skip
+[!race] skip
+env GOCACHE=$WORK/cache
+
+# Test with coverage instrumentation enabled (-fuzz) and race instrumentation
+# but without actually fuzzing the target (by using a non-matching pattern)
+go test -fuzz=xxx -race -v
+! stderr 'race detected during execution of test'
+
+# Test with just race instrumentation enabled
+go test -race -v
+! stderr 'race detected during execution of test'
+
+# Test with coverage and race instrumentation enabled, and a matching fuzz
+# pattern
+go test -fuzz=FuzzRace -race -v -fuzztime=200x
+! stderr 'race detected during execution of test'
+
+-- go.mod --
+module test
+
+-- race_test.go --
+package race
+
+import "testing"
+
+func FuzzRace(f *testing.F) {
+ for i := 0; i < 100; i++ {
+ f.Add(i)
+ }
+
+ f.Fuzz(func(t *testing.T, i int) {
+ t.Parallel()
+ })
+}
diff --git a/src/cmd/go/testdata/script/test_fuzz_unsupported.txt b/src/cmd/go/testdata/script/test_fuzz_unsupported.txt
new file mode 100644
index 0000000..1ed0b8a
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fuzz_unsupported.txt
@@ -0,0 +1,18 @@
+[fuzz] skip
+
+! go test -fuzz=. -fuzztime=1x
+! stdout .
+stderr '^-fuzz flag is not supported on '$GOOS'/'$GOARCH'$'
+
+-- go.mod --
+module example
+
+go 1.18
+-- fuzz_test.go --
+package example
+
+import "testing"
+
+func FuzzTrivial(f *testing.F) {
+ f.Fuzz(func(t *testing.T, _ []byte) {})
+}
diff --git a/src/cmd/go/testdata/script/test_generated_main.txt b/src/cmd/go/testdata/script/test_generated_main.txt
new file mode 100644
index 0000000..2e991a5
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_generated_main.txt
@@ -0,0 +1,34 @@
+# Tests that the generated test main file has a generated code comment.
+# This is needed by analyzers that access source files through 'go list'.
+# Verifies golang.org/issue/31971.
+# TODO(jayconrod): This test is brittle. We should write _testmain.go as
+# a build action instead of with an ad-hoc WriteFile call
+# in internal/test/test.go. Then we could just grep 'go get -n'.
+go test x_test.go
+
+-- x_test.go --
+package x
+
+import (
+ "os"
+ "path/filepath"
+ "regexp"
+ "testing"
+)
+
+func Test(t *testing.T) {
+ exePath, err := os.Executable()
+ if err != nil {
+ t.Fatal(err)
+ }
+ testmainPath := filepath.Join(filepath.Dir(exePath), "_testmain.go")
+ source, err := os.ReadFile(testmainPath)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if matched, err := regexp.Match(`(?m)^// Code generated .* DO NOT EDIT\.$`, source); err != nil {
+ t.Fatal(err)
+ } else if !matched {
+ t.Error("_testmain.go does not have generated code comment")
+ }
+}
diff --git a/src/cmd/go/testdata/script/test_go111module_cache.txt b/src/cmd/go/testdata/script/test_go111module_cache.txt
new file mode 100644
index 0000000..ca1de43
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_go111module_cache.txt
@@ -0,0 +1,15 @@
+env GO111MODULE=on
+go mod init foo
+go test
+stdout ^ok\s+foo
+env GO111MODULE=off
+go test
+stdout ^ok\s+
+! stdout ^ok\s+(cache)$
+
+-- main_test.go --
+package main
+
+import "testing"
+
+func TestF(t *testing.T) {}
diff --git a/src/cmd/go/testdata/script/test_goroot_PATH.txt b/src/cmd/go/testdata/script/test_goroot_PATH.txt
new file mode 100644
index 0000000..a6278ca
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_goroot_PATH.txt
@@ -0,0 +1,41 @@
+# https://go.dev/issue/51473: to avoid the need for tests to rely on
+# runtime.GOROOT, 'go test' should run the test with its own GOROOT/bin
+# at the beginning of $PATH.
+
+[short] skip
+
+[!GOOS:plan9] env PATH=
+[GOOS:plan9] env path=
+go test .
+
+[!GOOS:plan9] env PATH=$WORK${/}bin
+[GOOS:plan9] env path=$WORK${/}bin
+go test .
+
+-- go.mod --
+module example
+
+go 1.19
+-- example_test.go --
+package example
+
+import (
+ "os"
+ "os/exec"
+ "path/filepath"
+ "testing"
+)
+
+func TestGoCommandExists(t *testing.T) {
+ got, err := exec.LookPath("go")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ want := filepath.Join(os.Getenv("GOROOT"), "bin", "go" + os.Getenv("GOEXE"))
+ if got != want {
+ t.Fatalf(`exec.LookPath("go") = %q; want %q`, got, want)
+ }
+}
+-- $WORK/bin/README.txt --
+This directory contains no executables.
diff --git a/src/cmd/go/testdata/script/test_import_error_stack.txt b/src/cmd/go/testdata/script/test_import_error_stack.txt
new file mode 100644
index 0000000..6c60f3d
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_import_error_stack.txt
@@ -0,0 +1,31 @@
+env GO111MODULE=off
+! go test testdep/p1
+stderr 'package testdep/p1 \(test\)\n\timports testdep/p2\n\timports testdep/p3: build constraints exclude all Go files ' # check for full import stack
+! go vet testdep/p1
+stderr 'package testdep/p1 \(test\)\n\timports testdep/p2\n\timports testdep/p3: build constraints exclude all Go files ' # check for full import stack
+
+env GO111MODULE=on
+cd testdep
+! go test testdep/p1
+stderr 'package testdep/p1 \(test\)\n\timports testdep/p2\n\timports testdep/p3: build constraints exclude all Go files ' # check for full import stack
+! go vet testdep/p1
+stderr 'package testdep/p1 \(test\)\n\timports testdep/p2\n\timports testdep/p3: build constraints exclude all Go files ' # check for full import stack
+
+-- testdep/go.mod --
+module testdep
+
+go 1.16
+-- testdep/p1/p1.go --
+package p1
+-- testdep/p1/p1_test.go --
+package p1
+
+import _ "testdep/p2"
+-- testdep/p2/p2.go --
+package p2
+
+import _ "testdep/p3"
+-- testdep/p3/p3.go --
+// +build ignore
+
+package ignored
diff --git a/src/cmd/go/testdata/script/test_issue45477.txt b/src/cmd/go/testdata/script/test_issue45477.txt
new file mode 100644
index 0000000..f435b6a
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_issue45477.txt
@@ -0,0 +1,12 @@
+[short] skip # links and runs a test binary
+
+go test -v .
+
+-- go.mod --
+module example.com/pkg_test
+
+-- pkg.go --
+package pkg_test
+
+-- pkg_test.go --
+package pkg_test
diff --git a/src/cmd/go/testdata/script/test_json.txt b/src/cmd/go/testdata/script/test_json.txt
new file mode 100644
index 0000000..6207c2e
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_json.txt
@@ -0,0 +1,80 @@
+[compiler:gccgo] skip # gccgo does not have standard packages
+[short] skip
+
+env GOCACHE=$WORK/tmp
+
+# Run go test -json on errors m/empty/pkg and m/skipper
+# It would be nice to test that the output is interlaced
+# but it seems to be impossible to do that in a short test
+# that isn't also flaky. Just check that we get JSON output.
+go test -json -short -v errors m/empty/pkg m/skipper
+
+# Check errors for run action
+stdout '"Package":"errors"'
+stdout '"Action":"start","Package":"errors"'
+stdout '"Action":"run","Package":"errors"'
+
+# Check m/empty/pkg for output and skip actions
+stdout '"Action":"start","Package":"m/empty/pkg"'
+stdout '"Action":"output","Package":"m/empty/pkg","Output":".*no test files'
+stdout '"Action":"skip","Package":"m/empty/pkg"'
+
+# Check skipper for output and skip actions
+stdout '"Action":"start","Package":"m/skipper"'
+stdout '"Action":"output","Package":"m/skipper","Test":"Test","Output":"--- SKIP:'
+stdout '"Action":"skip","Package":"m/skipper","Test":"Test"'
+
+# Check that starts were ordered properly.
+stdout '(?s)"Action":"start","Package":"errors".*"Action":"start","Package":"m/empty/pkg".*"Action":"start","Package":"m/skipper"'
+
+# Run go test -json on errors and check it's cached
+go test -json -short -v errors
+stdout '"Action":"output","Package":"errors","Output":".*\(cached\)'
+
+go test -json -bench=NONE -short -v errors
+stdout '"Package":"errors"'
+stdout '"Action":"run"'
+
+# Test running test2json
+go test -o $WORK/tmp/errors.test$GOEXE -c errors
+go tool test2json -p errors $WORK/tmp/errors.test$GOEXE -test.v -test.short
+stdout '"Package":"errors"'
+stdout '"Action":"run"'
+stdout '\{"Action":"pass","Package":"errors"\}'
+
+-- go.mod --
+module m
+
+go 1.16
+-- skipper/skip_test.go --
+package skipper
+
+import "testing"
+
+func Test(t *testing.T) {
+ t.Skip("skipping")
+}
+-- empty/pkg/pkg.go --
+package p
+-- empty/pkgtest/pkg.go --
+package p
+-- empty/pkgtest/test_test.go --
+package p
+-- empty/pkgtestxtest/pkg.go --
+package p
+-- empty/pkgtestxtest/test_test.go --
+package p
+-- empty/pkgtestxtest/xtest_test.go --
+package p_test
+-- empty/pkgxtest/pkg.go --
+package p
+-- empty/pkgxtest/xtest_test.go --
+package p_test
+-- empty/test/test_test.go --
+package p
+-- empty/testxtest/test_test.go --
+package p
+-- empty/testxtest/xtest_test.go --
+package p_test
+-- empty/xtest/xtest_test.go --
+package p_test
diff --git a/src/cmd/go/testdata/script/test_json_exit.txt b/src/cmd/go/testdata/script/test_json_exit.txt
new file mode 100644
index 0000000..dc7ffb0
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_json_exit.txt
@@ -0,0 +1,102 @@
+[short] skip
+
+go test -c -o mainpanic.exe ./mainpanic &
+go test -c -o mainexit0.exe ./mainexit0 &
+go test -c -o testpanic.exe ./testpanic &
+go test -c -o testbgpanic.exe ./testbgpanic &
+wait
+
+# Test binaries that panic in TestMain should be marked as failing.
+
+! go test -json ./mainpanic
+stdout '"Action":"fail"'
+! stdout '"Action":"pass"'
+
+! go tool test2json ./mainpanic.exe
+stdout '"Action":"fail"'
+! stdout '"Action":"pass"'
+
+# Test binaries that exit with status 0 should be marked as passing.
+
+go test -json ./mainexit0
+stdout '"Action":"pass"'
+! stdout '"Action":"fail"'
+
+go tool test2json ./mainexit0.exe
+stdout '"Action":"pass"'
+! stdout '"Action":"fail"'
+
+# Test functions that panic should never be marked as passing
+# (https://golang.org/issue/40132).
+
+! go test -json ./testpanic
+stdout '"Action":"fail"'
+! stdout '"Action":"pass"'
+
+! go tool test2json ./testpanic.exe -test.v
+stdout '"Action":"fail"'
+! stdout '"Action":"pass"'
+
+! go tool test2json ./testpanic.exe
+stdout '"Action":"fail"'
+! stdout '"Action":"pass"'
+
+# Tests that panic in a background goroutine should be marked as failing.
+
+! go test -json ./testbgpanic
+stdout '"Action":"fail"'
+! stdout '"Action":"pass"'
+
+! go tool test2json ./testbgpanic.exe -test.v
+stdout '"Action":"fail"'
+! stdout '"Action":"pass"'
+
+! go tool test2json ./testbgpanic.exe
+stdout '"Action":"fail"'
+! stdout '"Action":"pass"'
+
+-- go.mod --
+module m
+go 1.14
+-- mainpanic/mainpanic_test.go --
+package mainpanic_test
+
+import "testing"
+
+func TestMain(m *testing.M) {
+ panic("haha no")
+}
+-- mainexit0/mainexit0_test.go --
+package mainexit0_test
+
+import (
+ "fmt"
+ "os"
+ "testing"
+)
+
+func TestMain(m *testing.M) {
+ fmt.Println("nothing to do")
+ os.Exit(0)
+}
+-- testpanic/testpanic_test.go --
+package testpanic_test
+
+import "testing"
+
+func TestPanic(*testing.T) {
+ panic("haha no")
+}
+-- testbgpanic/testbgpanic_test.go --
+package testbgpanic_test
+
+import "testing"
+
+func TestPanicInBackground(*testing.T) {
+ c := make(chan struct{})
+ go func() {
+ panic("haha no")
+ close(c)
+ }()
+ <-c
+}
diff --git a/src/cmd/go/testdata/script/test_json_interleaved.txt b/src/cmd/go/testdata/script/test_json_interleaved.txt
new file mode 100644
index 0000000..e2d349e
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_json_interleaved.txt
@@ -0,0 +1,27 @@
+# Regression test for https://golang.org/issue/40657: output from the main test
+# function should be attributed correctly even if interleaved with the PAUSE
+# line for a new parallel subtest.
+
+[short] skip
+
+go test -json
+stdout '"Test":"TestWeirdTiming","Output":"[^"]* logging to outer again\\n"'
+
+-- go.mod --
+module example.com
+go 1.15
+-- main_test.go --
+package main
+
+import (
+ "testing"
+)
+
+func TestWeirdTiming(outer *testing.T) {
+ outer.Run("pauser", func(pauser *testing.T) {
+ outer.Logf("logging to outer")
+ pauser.Parallel()
+ })
+
+ outer.Logf("logging to outer again")
+}
diff --git a/src/cmd/go/testdata/script/test_json_issue35169.txt b/src/cmd/go/testdata/script/test_json_issue35169.txt
new file mode 100644
index 0000000..fdb5755
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_json_issue35169.txt
@@ -0,0 +1,28 @@
+! go test -json .
+
+ # We should see only JSON output on stdout, no non-JSON.
+ # To simplify the check, we just look for non-curly-braces, since
+ # every JSON entry has them and they're unlikely to occur
+ # in other error messages.
+! stdout '^[^{]'
+! stdout '[^}]\n$'
+
+ # Since the only test we requested failed to build, we should
+ # not see any "pass" actions in the JSON stream.
+! stdout '\{.*"Action":"pass".*\}'
+
+ # TODO(#62067): emit this as a build event instead of a test event.
+stdout '\{.*"Action":"output","Package":"example","Output":"FAIL\\texample \[build failed\]\\n"\}'
+stdout '\{.*"Action":"fail","Package":"example",.*\}'
+
+-- go.mod --
+module example
+go 1.19
+-- example.go --
+package example
+
+This is not valid Go source.
+-- example_test.go --
+package example
+
+func Test(*testing.T) {}
diff --git a/src/cmd/go/testdata/script/test_json_panic_exit.txt b/src/cmd/go/testdata/script/test_json_panic_exit.txt
new file mode 100644
index 0000000..5f1d033
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_json_panic_exit.txt
@@ -0,0 +1,69 @@
+# Verifies golang.org/issue/37555.
+
+[short] skip
+
+# 'go test -json' should say a test passes if it says it passes.
+go test -json ./pass
+stdout '"Action":"pass","Package":"[^"]*","Elapsed":[^"]*}\n\z'
+! stdout '"Test":.*\n\z'
+
+# 'go test -json' should say a test passes if it exits 0 and prints nothing.
+# TODO(golang.org/issue/29062): this should fail in the future.
+go test -json ./exit0main
+stdout '"Action":"pass".*\n\z'
+! stdout '"Test":.*\n\z'
+
+# 'go test -json' should say a test fails if it exits 1 and prints nothing.
+! go test -json ./exit1main
+stdout '"Action":"fail".*\n\z'
+! stdout '"Test":.*\n\z'
+
+# 'go test -json' should say a test fails if it panics.
+! go test -json ./panic
+stdout '"Action":"fail".*\n\z'
+! stdout '"Test":.*\n\z'
+
+-- go.mod --
+module example.com/test
+
+go 1.14
+
+-- pass/pass_test.go --
+package pass_test
+
+import "testing"
+
+func TestPass(t *testing.T) {}
+
+-- exit0main/exit0main_test.go --
+package exit0_test
+
+import (
+ "os"
+ "testing"
+)
+
+func TestMain(m *testing.M) {
+ os.Exit(0)
+}
+
+-- exit1main/exit1main_test.go --
+package exit1_test
+
+import (
+ "os"
+ "testing"
+)
+
+func TestMain(m *testing.M) {
+ os.Exit(1)
+}
+
+-- panic/panic_test.go --
+package panic_test
+
+import "testing"
+
+func TestPanic(t *testing.T) {
+ panic("oh no")
+}
diff --git a/src/cmd/go/testdata/script/test_json_prints.txt b/src/cmd/go/testdata/script/test_json_prints.txt
new file mode 100644
index 0000000..f979998
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_json_prints.txt
@@ -0,0 +1,48 @@
+go test -json
+
+stdout '"Action":"output","Package":"p","Output":"M1"}'
+stdout '"Action":"output","Package":"p","Test":"Test","Output":"=== RUN Test\\n"}'
+stdout '"Action":"output","Package":"p","Test":"Test","Output":"T1"}'
+stdout '"Action":"output","Package":"p","Test":"Test/Sub1","Output":"=== RUN Test/Sub1\\n"}'
+stdout '"Action":"output","Package":"p","Test":"Test/Sub1","Output":"Sub1 x_test.go:19: SubLog1\\n"}'
+stdout '"Action":"output","Package":"p","Test":"Test/Sub1","Output":"Sub2"}'
+stdout '"Action":"output","Package":"p","Test":"Test/Sub1","Output":"--- PASS: Test/Sub1 \([\d.]+s\)\\n"}'
+stdout '"Action":"pass","Package":"p","Test":"Test/Sub1","Elapsed"'
+stdout '"Action":"output","Package":"p","Test":"Test/Sub3","Output":"foo bar"}'
+stdout '"Action":"output","Package":"p","Test":"Test/Sub3","Output":"baz\\n"}'
+stdout '"Action":"output","Package":"p","Test":"Test","Output":"T2"}'
+stdout '"Action":"output","Package":"p","Test":"Test","Output":"--- PASS: Test \([\d.]+s\)\\n"}'
+stdout '"Action":"pass","Package":"p","Test":"Test","Elapsed"'
+stdout '"Action":"output","Package":"p","Output":"M2ok \\tp\\t[\d.]+s\\n"}'
+stdout '"Action":"pass","Package":"p","Elapsed"'
+
+-- go.mod --
+module p
+
+-- x_test.go --
+package p
+
+import (
+ "os"
+ "testing"
+)
+
+func TestMain(m *testing.M) {
+ print("M1")
+ code := m.Run()
+ print("M2")
+ os.Exit(code)
+}
+
+func Test(t *testing.T) {
+ print("T1")
+ t.Run("Sub1", func(t *testing.T) {
+ print("Sub1")
+ t.Log("SubLog1")
+ print("Sub2")
+ })
+ t.Run("Sub3", func(t *testing.T) {
+ print("\x16foo bar\x16baz\n")
+ })
+ print("T2")
+}
diff --git a/src/cmd/go/testdata/script/test_json_timeout.txt b/src/cmd/go/testdata/script/test_json_timeout.txt
new file mode 100644
index 0000000..0a2329b
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_json_timeout.txt
@@ -0,0 +1,19 @@
+! go test -json -timeout=1ms
+
+stdout '"Action":"output","Package":"p","Output":"FAIL\\tp\\t'
+stdout '"Action":"fail","Package":"p","Elapsed":'
+
+-- go.mod --
+module p
+
+-- x_test.go --
+package p
+
+import (
+ "testing"
+ "time"
+)
+
+func Test(t *testing.T) {
+ time.Sleep(1*time.Hour)
+}
diff --git a/src/cmd/go/testdata/script/test_main.txt b/src/cmd/go/testdata/script/test_main.txt
new file mode 100644
index 0000000..25d02e4
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_main.txt
@@ -0,0 +1,92 @@
+# Test TestMain
+go test standalone_main_normal_test.go
+! stdout '^ok.*\[no tests to run\]'
+! stderr '^ok.*\[no tests to run\]'
+stdout '^ok'
+
+# Test TestMain sees testing flags
+go test standalone_testmain_flag_test.go
+stdout '^ok.*\[no tests to run\]'
+
+# Test TestMain with wrong signature (Issue #22388)
+! go test standalone_main_wrong_test.go
+stderr 'wrong signature for TestMain, must be: func TestMain\(m \*testing.M\)'
+
+# Test TestMain does not call os.Exit (Issue #34129)
+! go test standalone_testmain_not_call_os_exit_test.go
+! stdout '^ok'
+
+-- standalone_main_normal_test.go --
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package standalone_main_normal_test
+
+import "testing"
+
+func TestMain(t *testing.T) {
+}
+-- standalone_main_wrong_test.go --
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package standalone_main_wrong_test
+
+import "testing"
+
+func TestMain(m *testing.Main) {
+}
+-- standalone_testmain_flag_test.go --
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package standalone_testmain_flag_test
+
+import (
+ "flag"
+ "fmt"
+ "os"
+ "testing"
+)
+
+func TestMain(m *testing.M) {
+ // A TestMain should be able to access testing flags if it calls
+ // flag.Parse without needing to use testing.Init.
+ flag.Parse()
+ found := false
+ flag.VisitAll(func(f *flag.Flag) {
+ if f.Name == "test.count" {
+ found = true
+ }
+ })
+ if !found {
+ fmt.Println("testing flags not registered")
+ os.Exit(1)
+ }
+ os.Exit(m.Run())
+}
+-- standalone_testmain_not_call_os_exit_test.go --
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package standalone_testmain_not_call_os_exit_test
+
+import (
+ "testing"
+)
+
+func TestWillFail(t *testing.T) {
+ t.Error("this test will fail.")
+}
+
+func TestMain(m *testing.M) {
+ defer func() {
+ recover()
+ }()
+ exit := m.Run()
+ panic(exit)
+}
diff --git a/src/cmd/go/testdata/script/test_main_archive.txt b/src/cmd/go/testdata/script/test_main_archive.txt
new file mode 100644
index 0000000..410d923
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_main_archive.txt
@@ -0,0 +1,32 @@
+env GO111MODULE=off
+
+# Test that a main_test of 'package main' imports the package,
+# not the installed binary.
+
+[short] skip
+
+env GOBIN=$WORK/bin
+go test main_test
+go install main_test
+
+go list -f '{{.Stale}}' main_test
+stdout false
+
+go test main_test
+
+-- main_test/m.go --
+package main
+
+func F() {}
+func main() {}
+-- main_test/m_test.go --
+package main_test
+
+import (
+ . "main_test"
+ "testing"
+)
+
+func Test1(t *testing.T) {
+ F()
+}
diff --git a/src/cmd/go/testdata/script/test_main_panic.txt b/src/cmd/go/testdata/script/test_main_panic.txt
new file mode 100644
index 0000000..45887c5
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_main_panic.txt
@@ -0,0 +1,30 @@
+[short] skip
+[!race] skip
+
+! go test -v -race main_panic/testmain_parallel_sub_panic_test.go
+! stdout 'DATA RACE'
+-- main_panic/testmain_parallel_sub_panic_test.go --
+package testmain_parallel_sub_panic_test
+
+import "testing"
+
+func setup() { println("setup()") }
+func teardown() { println("teardown()") }
+func TestA(t *testing.T) {
+ t.Run("1", func(t *testing.T) {
+ t.Run("1", func(t *testing.T) {
+ t.Parallel()
+ panic("A/1/1 panics")
+ })
+ t.Run("2", func(t *testing.T) {
+ t.Parallel()
+ println("A/1/2 is ok")
+ })
+ })
+}
+
+func TestMain(m *testing.M) {
+ setup()
+ defer teardown()
+ m.Run()
+} \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/test_main_twice.txt b/src/cmd/go/testdata/script/test_main_twice.txt
new file mode 100644
index 0000000..f32d4fc
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_main_twice.txt
@@ -0,0 +1,27 @@
+[short] skip
+
+env GOCACHE=$WORK/tmp
+go test -v multimain
+stdout -count=2 notwithstanding # check tests ran twice
+
+-- go.mod --
+module multimain
+
+go 1.16
+-- multimain_test.go --
+package multimain_test
+
+import "testing"
+
+func TestMain(m *testing.M) {
+ // Some users run m.Run multiple times, changing
+ // some kind of global state between runs.
+ // This used to work so I guess now it has to keep working.
+ // See golang.org/issue/23129.
+ m.Run()
+ m.Run()
+}
+
+func Test(t *testing.T) {
+ t.Log("notwithstanding")
+}
diff --git a/src/cmd/go/testdata/script/test_match_benchmark_labels.txt b/src/cmd/go/testdata/script/test_match_benchmark_labels.txt
new file mode 100644
index 0000000..13c4007
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_match_benchmark_labels.txt
@@ -0,0 +1,18 @@
+# Benchmark labels, file outside gopath
+# TODO(matloob): This test was called TestBenchmarkLabelsOutsideGOPATH
+# why "OutsideGOPATH"? Does the go command need to be run outside GOPATH?
+# Do the files need to exist outside GOPATH?
+cp $GOPATH/src/standalone_benchmark_test.go $WORK/tmp/standalone_benchmark_test.go
+go test -run '^$' -bench . $WORK/tmp/standalone_benchmark_test.go
+stdout '^goos: '$GOOS
+stdout '^goarch: '$GOARCH
+! stdout '^pkg:'
+! stderr '^pkg:'
+
+-- standalone_benchmark_test.go --
+package standalone_benchmark
+
+import "testing"
+
+func Benchmark(b *testing.B) {
+} \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/test_match_no_benchmarks.txt b/src/cmd/go/testdata/script/test_match_no_benchmarks.txt
new file mode 100644
index 0000000..30f4be8
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_match_no_benchmarks.txt
@@ -0,0 +1,13 @@
+# Matches no benchmarks
+go test -run '^$' -bench ThisWillNotMatch standalone_benchmark_test.go
+! stdout '^ok.*\[no tests to run\]'
+! stderr '^ok.*\[no tests to run\]'
+stdout '^ok'
+
+-- standalone_benchmark_test.go --
+package standalone_benchmark
+
+import "testing"
+
+func Benchmark(b *testing.B) {
+} \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/test_match_no_subtests.txt b/src/cmd/go/testdata/script/test_match_no_subtests.txt
new file mode 100644
index 0000000..7abb1eb
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_match_no_subtests.txt
@@ -0,0 +1,12 @@
+# The subtests don't match
+go test -run Test/ThisWillNotMatch standalone_sub_test.go
+stdout '^ok.*\[no tests to run\]'
+
+-- standalone_sub_test.go --
+package standalone_sub_test
+
+import "testing"
+
+func Test(t *testing.T) {
+ t.Run("Sub", func(t *testing.T) {})
+} \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/test_match_no_subtests_failure.txt b/src/cmd/go/testdata/script/test_match_no_subtests_failure.txt
new file mode 100644
index 0000000..b3c5b92
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_match_no_subtests_failure.txt
@@ -0,0 +1,15 @@
+# Matches no subtests, but parent test still fails
+! go test -run TestThatFails/ThisWillNotMatch standalone_fail_sub_test.go
+! stdout '^ok.*\[no tests to run\]'
+! stderr '^ok.*\[no tests to run\]'
+stdout 'FAIL'
+
+-- standalone_fail_sub_test.go --
+package standalone_fail_sub_test
+
+import "testing"
+
+func TestThatFails(t *testing.T) {
+ t.Run("Sub", func(t *testing.T) {})
+ t.Fail()
+} \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/test_match_no_subtests_parallel.txt b/src/cmd/go/testdata/script/test_match_no_subtests_parallel.txt
new file mode 100644
index 0000000..11c734c
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_match_no_subtests_parallel.txt
@@ -0,0 +1,19 @@
+# Matches no subtests, parallel
+go test -run Test/Sub/ThisWillNotMatch standalone_parallel_sub_test.go
+stdout '^ok.*\[no tests to run\]'
+
+-- standalone_parallel_sub_test.go --
+package standalone_parallel_sub_test
+
+import "testing"
+
+func Test(t *testing.T) {
+ ch := make(chan bool, 1)
+ t.Run("Sub", func(t *testing.T) {
+ t.Parallel()
+ <-ch
+ t.Run("Nested", func(t *testing.T) {})
+ })
+ // Ensures that Sub will finish after its t.Run call already returned.
+ ch <- true
+}
diff --git a/src/cmd/go/testdata/script/test_match_no_tests.txt b/src/cmd/go/testdata/script/test_match_no_tests.txt
new file mode 100644
index 0000000..1ad2097
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_match_no_tests.txt
@@ -0,0 +1,11 @@
+# Matches no tests
+go test -run ThisWillNotMatch standalone_test.go
+stdout '^ok.*\[no tests to run\]'
+
+-- standalone_test.go --
+package standalone_test
+
+import "testing"
+
+func Test(t *testing.T) {
+} \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/test_match_no_tests_build_failure.txt b/src/cmd/go/testdata/script/test_match_no_tests_build_failure.txt
new file mode 100644
index 0000000..e1c9643
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_match_no_tests_build_failure.txt
@@ -0,0 +1,19 @@
+# Test that when there's a build failure and a -run flag that doesn't match,
+# that the error for not matching tests does not override the error for
+# the build failure.
+
+! go test -run ThisWillNotMatch syntaxerror
+! stderr '(?m)^ok.*\[no tests to run\]'
+stdout 'FAIL'
+
+-- go.mod --
+module syntaxerror
+
+go 1.16
+-- x.go --
+package p
+-- x_test.go --
+package p
+
+func f() (x.y, z int) {
+}
diff --git a/src/cmd/go/testdata/script/test_match_no_tests_with_subtests.txt b/src/cmd/go/testdata/script/test_match_no_tests_with_subtests.txt
new file mode 100644
index 0000000..0d94918
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_match_no_tests_with_subtests.txt
@@ -0,0 +1,12 @@
+# Matches no tests with subtests
+go test -run ThisWillNotMatch standalone_sub_test.go
+stdout '^ok.*\[no tests to run\]'
+
+-- standalone_sub_test.go --
+package standalone_sub_test
+
+import "testing"
+
+func Test(t *testing.T) {
+ t.Run("Sub", func(t *testing.T) {})
+} \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/test_match_only_benchmarks.txt b/src/cmd/go/testdata/script/test_match_only_benchmarks.txt
new file mode 100644
index 0000000..5dfb96e
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_match_only_benchmarks.txt
@@ -0,0 +1,13 @@
+# Matches only benchmarks
+go test -run '^$' -bench . standalone_benchmark_test.go
+! stdout '^ok.*\[no tests to run\]'
+! stderr '^ok.*\[no tests to run\]'
+stdout '^ok'
+
+-- standalone_benchmark_test.go --
+package standalone_benchmark
+
+import "testing"
+
+func Benchmark(b *testing.B) {
+} \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/test_match_only_example.txt b/src/cmd/go/testdata/script/test_match_only_example.txt
new file mode 100644
index 0000000..515ccb3
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_match_only_example.txt
@@ -0,0 +1,31 @@
+[short] skip
+
+# Check that it's okay for test pattern to match only examples.
+go test -run Example example1_test.go
+! stderr '^ok.*\[no tests to run\]'
+stdout '^ok'
+
+-- example1_test.go --
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure that go test runs Example_Z before Example_A, preserving source order.
+
+package p
+
+import "fmt"
+
+var n int
+
+func Example_Z() {
+ n++
+ fmt.Println(n)
+ // Output: 1
+}
+
+func Example_A() {
+ n++
+ fmt.Println(n)
+ // Output: 2
+}
diff --git a/src/cmd/go/testdata/script/test_match_only_subtests.txt b/src/cmd/go/testdata/script/test_match_only_subtests.txt
new file mode 100644
index 0000000..beea895
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_match_only_subtests.txt
@@ -0,0 +1,14 @@
+# Matches only subtests
+go test -run Test/Sub standalone_sub_test.go
+! stdout '^ok.*\[no tests to run\]'
+! stderr '^ok.*\[no tests to run\]'
+stdout '^ok'
+
+-- standalone_sub_test.go --
+package standalone_sub_test
+
+import "testing"
+
+func Test(t *testing.T) {
+ t.Run("Sub", func(t *testing.T) {})
+} \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/test_match_only_subtests_parallel.txt b/src/cmd/go/testdata/script/test_match_only_subtests_parallel.txt
new file mode 100644
index 0000000..11872c2
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_match_only_subtests_parallel.txt
@@ -0,0 +1,21 @@
+# Matches only subtests, parallel
+go test -run Test/Sub/Nested standalone_parallel_sub_test.go
+! stdout '^ok.*\[no tests to run\]'
+! stderr '^ok.*\[no tests to run\]'
+stdout '^ok'
+
+-- standalone_parallel_sub_test.go --
+package standalone_parallel_sub_test
+
+import "testing"
+
+func Test(t *testing.T) {
+ ch := make(chan bool, 1)
+ t.Run("Sub", func(t *testing.T) {
+ t.Parallel()
+ <-ch
+ t.Run("Nested", func(t *testing.T) {})
+ })
+ // Ensures that Sub will finish after its t.Run call already returned.
+ ch <- true
+}
diff --git a/src/cmd/go/testdata/script/test_match_only_tests.txt b/src/cmd/go/testdata/script/test_match_only_tests.txt
new file mode 100644
index 0000000..9185793
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_match_only_tests.txt
@@ -0,0 +1,13 @@
+# Matches only tests
+go test -run Test standalone_test.go
+! stdout '^ok.*\[no tests to run\]'
+! stderr '^ok.*\[no tests to run\]'
+stdout '^ok'
+
+-- standalone_test.go --
+package standalone_test
+
+import "testing"
+
+func Test(t *testing.T) {
+} \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/test_minus_n.txt b/src/cmd/go/testdata/script/test_minus_n.txt
new file mode 100644
index 0000000..9900dbc
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_minus_n.txt
@@ -0,0 +1,14 @@
+# The intent here is to verify that 'go test -n' works without crashing.
+# Any test will do.
+
+go test -n x_test.go
+
+-- x_test.go --
+package x_test
+
+import (
+ "testing"
+)
+
+func TestEmpty(t *testing.T) {
+}
diff --git a/src/cmd/go/testdata/script/test_no_run_example.txt b/src/cmd/go/testdata/script/test_no_run_example.txt
new file mode 100644
index 0000000..53ac755
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_no_run_example.txt
@@ -0,0 +1,30 @@
+go test -v norunexample
+stdout 'File with non-runnable example was built.'
+
+-- go.mod --
+module norunexample
+
+go 1.16
+-- example_test.go --
+package pkg_test
+
+import "os"
+
+func init() {
+ os.Stdout.Write([]byte("File with non-runnable example was built.\n"))
+}
+
+func Example_test() {
+ // This test will not be run, it has no "Output:" comment.
+}
+-- test_test.go --
+package pkg
+
+import (
+ "os"
+ "testing"
+)
+
+func TestBuilt(t *testing.T) {
+ os.Stdout.Write([]byte("A normal test was executed.\n"))
+}
diff --git a/src/cmd/go/testdata/script/test_no_tests.txt b/src/cmd/go/testdata/script/test_no_tests.txt
new file mode 100644
index 0000000..2d624d1
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_no_tests.txt
@@ -0,0 +1,15 @@
+# Tests issue #26242
+
+go test testnorun
+stdout 'testnorun\t\[no test files\]'
+
+-- go.mod --
+module testnorun
+
+go 1.16
+-- p.go --
+package p
+
+func init() {
+ panic("go test must not link and run test binaries without tests")
+}
diff --git a/src/cmd/go/testdata/script/test_overlay.txt b/src/cmd/go/testdata/script/test_overlay.txt
new file mode 100644
index 0000000..b6bdc11
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_overlay.txt
@@ -0,0 +1,24 @@
+[short] skip
+
+cd $WORK/gopath/src/foo
+go test -list=. -overlay=overlay.json .
+stdout 'TestBar'
+
+-- go.mod --
+module test.pkg
+-- foo/foo_test.go --
+package foo
+
+import "testing"
+
+func TestFoo(t *testing.T) { }
+-- tmp/bar_test.go --
+package foo
+
+import "testing"
+
+func TestBar(t *testing.T) {
+ t.Fatal("dummy failure")
+}
+-- foo/overlay.json --
+{"Replace": {"foo_test.go": "../tmp/bar_test.go"}}
diff --git a/src/cmd/go/testdata/script/test_parallel_number.txt b/src/cmd/go/testdata/script/test_parallel_number.txt
new file mode 100644
index 0000000..4eb9794
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_parallel_number.txt
@@ -0,0 +1,25 @@
+[short] skip
+
+# go test -parallel -1 shouldn't work
+! go test -parallel -1 standalone_parallel_sub_test.go
+stdout '-parallel can only be given'
+
+# go test -parallel 0 shouldn't work
+! go test -parallel 0 standalone_parallel_sub_test.go
+stdout '-parallel can only be given'
+
+-- standalone_parallel_sub_test.go --
+package standalone_parallel_sub_test
+
+import "testing"
+
+func Test(t *testing.T) {
+ ch := make(chan bool, 1)
+ t.Run("Sub", func(t *testing.T) {
+ t.Parallel()
+ <-ch
+ t.Run("Nested", func(t *testing.T) {})
+ })
+ // Ensures that Sub will finish after its t.Run call already returned.
+ ch <- true
+}
diff --git a/src/cmd/go/testdata/script/test_ppc64_linker_funcs.txt b/src/cmd/go/testdata/script/test_ppc64_linker_funcs.txt
new file mode 100644
index 0000000..735b5dc
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_ppc64_linker_funcs.txt
@@ -0,0 +1,49 @@
+# Tests that the linker implements the PPC64 ELFv2 ABI
+# register save and restore functions as defined in
+# section 2.3.3.1 of the PPC64 ELFv2 ABI when linking
+# external objects most likely compiled with gcc's
+# -Os option.
+#
+# Verifies golang.org/issue/52366 for linux/ppc64le
+[!GOOS:linux] skip
+[!compiler:gc] skip
+[!cgo] skip
+[!GOARCH:ppc64le] skip
+
+go build -ldflags='-linkmode=internal'
+exec ./abitest
+stdout success
+
+-- go.mod --
+module abitest
+
+-- abitest.go --
+package main
+
+/*
+#cgo CFLAGS: -Os
+
+int foo_fpr() {
+ asm volatile("":::"fr31","fr30","fr29","fr28");
+}
+int foo_gpr0() {
+ asm volatile("":::"r30","r29","r28");
+}
+int foo_gpr1() {
+ asm volatile("":::"fr31", "fr30","fr29","fr28","r30","r29","r28");
+}
+int foo_vr() {
+ asm volatile("":::"v31","v30","v29","v28");
+}
+*/
+import "C"
+
+import "fmt"
+
+func main() {
+ C.foo_fpr()
+ C.foo_gpr0()
+ C.foo_gpr1()
+ C.foo_vr()
+ fmt.Println("success")
+}
diff --git a/src/cmd/go/testdata/script/test_ppc64le_cgo_inline_plt.txt b/src/cmd/go/testdata/script/test_ppc64le_cgo_inline_plt.txt
new file mode 100644
index 0000000..ef9ff03
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_ppc64le_cgo_inline_plt.txt
@@ -0,0 +1,38 @@
+# Verify the linker will correctly resolve
+# ppc64le objects compiled with gcc's -fno-plt
+# option. This inlines PLT calls, and generates
+# additional reloc types which the internal linker
+# should handle.
+#
+# Verifies golang.org/issue/53345
+#
+# Note, older gcc/clang may accept this option, but
+# ignore it if binutils does not support the relocs.
+[!compiler:gc] skip
+[!cgo] skip
+[!GOARCH:ppc64le] skip
+
+env CGO_CFLAGS='-fno-plt -O2 -g'
+
+go build -ldflags='-linkmode=internal'
+exec ./noplttest
+stdout helloworld
+
+-- go.mod --
+module noplttest
+
+-- noplttest.go --
+package main
+
+/*
+#include <stdio.h>
+void helloworld(void) {
+ printf("helloworld\n");
+ fflush(stdout);
+}
+*/
+import "C"
+
+func main() {
+ C.helloworld()
+}
diff --git a/src/cmd/go/testdata/script/test_profile.txt b/src/cmd/go/testdata/script/test_profile.txt
new file mode 100644
index 0000000..9110706
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_profile.txt
@@ -0,0 +1,19 @@
+[compiler:gccgo] skip 'gccgo has no standard packages'
+[short] skip
+
+# Check go test -cpuprofile creates errors.test
+go test -cpuprofile errors.prof errors
+exists -exec errors.test$GOEXE
+
+# Check go test -cpuprofile -o myerrors.test creates errors.test
+go test -cpuprofile errors.prof -o myerrors.test$GOEXE errors
+exists -exec myerrors.test$GOEXE
+
+# Check go test -mutexprofile creates errors.test
+go test -mutexprofile errors.prof errors
+exists -exec errors.test$GOEXE
+
+# Check go test -mutexprofile -o myerrors.test creates errors.test
+go test -mutexprofile errors.prof -o myerrors.test$GOEXE errors
+exists -exec myerrors.test$GOEXE
+
diff --git a/src/cmd/go/testdata/script/test_race.txt b/src/cmd/go/testdata/script/test_race.txt
new file mode 100644
index 0000000..2ffea46
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_race.txt
@@ -0,0 +1,51 @@
+[short] skip
+[!race] skip
+
+go test testrace
+
+! go test -race testrace
+stdout 'FAIL: TestRace'
+! stdout 'PASS'
+! stderr 'PASS'
+
+! go test -race testrace -run XXX -bench .
+stdout 'FAIL: BenchmarkRace'
+! stdout 'PASS'
+! stderr 'PASS'
+
+-- go.mod --
+module testrace
+
+go 1.16
+-- race_test.go --
+package testrace
+
+import "testing"
+
+func TestRace(t *testing.T) {
+ for i := 0; i < 10; i++ {
+ c := make(chan int)
+ x := 1
+ go func() {
+ x = 2
+ c <- 1
+ }()
+ x = 3
+ <-c
+ _ = x
+ }
+}
+
+func BenchmarkRace(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ c := make(chan int)
+ x := 1
+ go func() {
+ x = 2
+ c <- 1
+ }()
+ x = 3
+ <-c
+ _ = x
+ }
+}
diff --git a/src/cmd/go/testdata/script/test_race_cover_mode_issue20435.txt b/src/cmd/go/testdata/script/test_race_cover_mode_issue20435.txt
new file mode 100644
index 0000000..eacc882
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_race_cover_mode_issue20435.txt
@@ -0,0 +1,48 @@
+[short] skip
+[!race] skip
+
+# Make sure test is functional.
+go test testrace
+
+# Now, check that -race -covermode=set is not allowed.
+! go test -race -covermode=set testrace
+stderr '-covermode must be "atomic", not "set", when -race is enabled'
+! stdout PASS
+! stderr PASS
+
+-- go.mod --
+module testrace
+
+go 1.16
+-- race_test.go --
+package testrace
+
+import "testing"
+
+func TestRace(t *testing.T) {
+ for i := 0; i < 10; i++ {
+ c := make(chan int)
+ x := 1
+ go func() {
+ x = 2
+ c <- 1
+ }()
+ x = 3
+ <-c
+ _ = x
+ }
+}
+
+func BenchmarkRace(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ c := make(chan int)
+ x := 1
+ go func() {
+ x = 2
+ c <- 1
+ }()
+ x = 3
+ <-c
+ _ = x
+ }
+}
diff --git a/src/cmd/go/testdata/script/test_race_install.txt b/src/cmd/go/testdata/script/test_race_install.txt
new file mode 100644
index 0000000..918d7e9
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_race_install.txt
@@ -0,0 +1,12 @@
+[!race] skip
+[short] skip
+
+mkdir $WORKDIR/tmp/pkg
+go install -race -pkgdir=$WORKDIR/tmp/pkg std
+
+-- go.mod --
+module empty
+
+go 1.16
+-- pkg/pkg.go --
+package p
diff --git a/src/cmd/go/testdata/script/test_race_install_cgo.txt b/src/cmd/go/testdata/script/test_race_install_cgo.txt
new file mode 100644
index 0000000..e1fe4f2
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_race_install_cgo.txt
@@ -0,0 +1,91 @@
+# Tests Issue #10500
+
+[!race] skip
+
+env GOBIN=$WORK/bin
+go install m/mtime m/sametime
+
+go tool -n cgo
+cp stdout cgopath.txt
+exec $GOBIN/mtime cgopath.txt # get the mtime of the file whose name is in cgopath.txt
+cp stdout cgotime_before.txt
+
+ # For this test, we don't actually care whether 'go test -race -i' succeeds.
+ # It may fail if GOROOT is read-only (perhaps it was installed as root).
+ # We only care that it does not overwrite cmd/cgo regardless.
+? go test -race -i runtime/race
+
+exec $GOBIN/mtime cgopath.txt # get the mtime of the file whose name is in cgopath.txt
+cp stdout cgotime_after.txt
+exec $GOBIN/sametime cgotime_before.txt cgotime_after.txt
+
+-- go.mod --
+module m
+
+go 1.16
+-- mtime/mtime.go --
+package main
+
+import (
+ "encoding/json"
+ "fmt"
+ "os"
+ "strings"
+)
+
+func main() {
+ b, err := os.ReadFile(os.Args[1])
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ filename := strings.TrimSpace(string(b))
+ info, err := os.Stat(filename)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ if err := json.NewEncoder(os.Stdout).Encode(info.ModTime()); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+}
+-- sametime/sametime.go --
+package main
+
+import (
+ "encoding/json"
+ "fmt"
+ "os"
+ "time"
+)
+
+
+func main() {
+ var t1 time.Time
+ b1, err := os.ReadFile(os.Args[1])
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ if err := json.Unmarshal(b1, &t1); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+
+ var t2 time.Time
+ b2, err := os.ReadFile(os.Args[2])
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ if err := json.Unmarshal(b2, &t2); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+
+ if !t1.Equal(t2) {
+ fmt.Fprintf(os.Stderr, "time in %v (%v) is not the same as time in %v (%v)", os.Args[1], t1, os.Args[2], t2)
+ os.Exit(1)
+ }
+}
diff --git a/src/cmd/go/testdata/script/test_race_tag.txt b/src/cmd/go/testdata/script/test_race_tag.txt
new file mode 100644
index 0000000..4b18ebc
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_race_tag.txt
@@ -0,0 +1,29 @@
+# Tests Issue #54468
+
+[short] skip 'links a test binary'
+[!race] skip
+
+go mod tidy
+go test -c -o=$devnull -race .
+
+! stderr 'cannot find package'
+
+-- go.mod --
+module testrace
+
+go 1.18
+
+require rsc.io/sampler v1.0.0
+-- race_test.go --
+//go:build race
+
+package testrace
+
+import (
+ "testing"
+
+ _ "rsc.io/sampler"
+)
+
+func TestRaceTag(t *testing.T) {
+}
diff --git a/src/cmd/go/testdata/script/test_rebuildall.txt b/src/cmd/go/testdata/script/test_rebuildall.txt
new file mode 100644
index 0000000..38233c1
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_rebuildall.txt
@@ -0,0 +1,14 @@
+env GO111MODULE=off
+
+# Regression test for golang.org/issue/6844:
+# 'go test -a' should force dependencies in the standard library to be rebuilt.
+
+[short] skip
+
+go test -x -a -c testdata/dep_test.go
+stderr '^.*[/\\]compile'$GOEXE'["]? (.* )?regexp .*[/\\]regexp\.go'
+
+-- testdata/dep_test.go --
+package deps
+
+import _ "testing"
diff --git a/src/cmd/go/testdata/script/test_regexps.txt b/src/cmd/go/testdata/script/test_regexps.txt
new file mode 100644
index 0000000..2f33080
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_regexps.txt
@@ -0,0 +1,79 @@
+go test -cpu=1 -run=X/Y -bench=X/Y -count=2 -v testregexp
+
+# Test the following:
+
+# TestX is run, twice
+stdout -count=2 '^=== RUN TestX$'
+stdout -count=2 '^ x_test.go:6: LOG: X running$'
+
+# TestX/Y is run, twice
+stdout -count=2 '^=== RUN TestX/Y$'
+stdout -count=2 '^ x_test.go:8: LOG: Y running$'
+
+# TestXX is run, twice
+stdout -count=2 '^=== RUN TestXX$'
+stdout -count=2 '^ z_test.go:10: LOG: XX running'
+
+# TestZ is not run
+! stdout '^=== RUN TestZ$'
+
+# BenchmarkX is run with N=1 once, only to discover what sub-benchmarks it has,
+# and should not print a final summary line.
+stdout -count=1 '^ x_test.go:13: LOG: X running N=1$'
+! stdout '^\s+BenchmarkX: x_test.go:13: LOG: X running N=\d\d+'
+! stdout 'BenchmarkX\s+\d+'
+
+# Same for BenchmarkXX.
+stdout -count=1 '^ z_test.go:18: LOG: XX running N=1$'
+! stdout '^ z_test.go:18: LOG: XX running N=\d\d+'
+! stdout 'BenchmarkXX\s+\d+'
+
+# BenchmarkX/Y is run in full twice due to -count=2.
+# "Run in full" means that it runs for approximately the default benchtime,
+# but may cap out at N=1e9.
+# We don't actually care what the final iteration count is, but it should be
+# a large number, and the last iteration count prints right before the results.
+stdout -count=2 '^ x_test.go:15: LOG: Y running N=[1-9]\d{4,}\nBenchmarkX/Y\s+\d+'
+
+-- go.mod --
+module testregexp
+
+go 1.16
+-- x_test.go --
+package x
+
+import "testing"
+
+func TestX(t *testing.T) {
+ t.Logf("LOG: X running")
+ t.Run("Y", func(t *testing.T) {
+ t.Logf("LOG: Y running")
+ })
+}
+
+func BenchmarkX(b *testing.B) {
+ b.Logf("LOG: X running N=%d", b.N)
+ b.Run("Y", func(b *testing.B) {
+ b.Logf("LOG: Y running N=%d", b.N)
+ })
+}
+-- z_test.go --
+package x
+
+import "testing"
+
+func TestZ(t *testing.T) {
+ t.Logf("LOG: Z running")
+}
+
+func TestXX(t *testing.T) {
+ t.Logf("LOG: XX running")
+}
+
+func BenchmarkZ(b *testing.B) {
+ b.Logf("LOG: Z running N=%d", b.N)
+}
+
+func BenchmarkXX(b *testing.B) {
+ b.Logf("LOG: XX running N=%d", b.N)
+}
diff --git a/src/cmd/go/testdata/script/test_relative_cmdline.txt b/src/cmd/go/testdata/script/test_relative_cmdline.txt
new file mode 100644
index 0000000..96f7b87
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_relative_cmdline.txt
@@ -0,0 +1,52 @@
+# Relative imports in command line package
+
+env GO111MODULE=off
+
+# Run tests outside GOPATH.
+env GOPATH=$WORK/tmp
+
+go test ./testimport/p.go ./testimport/p_test.go ./testimport/x_test.go
+stdout '^ok'
+
+-- testimport/p.go --
+package p
+
+func F() int { return 1 }
+-- testimport/p1/p1.go --
+package p1
+
+func F() int { return 1 }
+-- testimport/p2/p2.go --
+package p2
+
+func F() int { return 1 }
+-- testimport/p_test.go --
+package p
+
+import (
+ "./p1"
+
+ "testing"
+)
+
+func TestF(t *testing.T) {
+ if F() != p1.F() {
+ t.Fatal(F())
+ }
+}
+-- testimport/x_test.go --
+package p_test
+
+import (
+ . "../testimport"
+
+ "./p2"
+
+ "testing"
+)
+
+func TestF1(t *testing.T) {
+ if F() != p2.F() {
+ t.Fatal(F())
+ }
+}
diff --git a/src/cmd/go/testdata/script/test_relative_import.txt b/src/cmd/go/testdata/script/test_relative_import.txt
new file mode 100644
index 0000000..938a875
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_relative_import.txt
@@ -0,0 +1,31 @@
+# Relative imports in go test
+env GO111MODULE=off # relative import not supported in module mode
+
+# Run tests outside GOPATH.
+env GOPATH=$WORK/tmp
+
+go test ./testimport
+stdout '^ok'
+
+-- testimport/p.go --
+package p
+
+func F() int { return 1 }
+-- testimport/p1/p1.go --
+package p1
+
+func F() int { return 1 }
+-- testimport/p_test.go --
+package p
+
+import (
+ "./p1"
+
+ "testing"
+)
+
+func TestF(t *testing.T) {
+ if F() != p1.F() {
+ t.Fatal(F())
+ }
+}
diff --git a/src/cmd/go/testdata/script/test_script_cmdcd.txt b/src/cmd/go/testdata/script/test_script_cmdcd.txt
new file mode 100644
index 0000000..6e6f67e
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_script_cmdcd.txt
@@ -0,0 +1,13 @@
+# Tests that after a cd command, where usually the UNIX path separator is used,
+# a match against $PWD does not fail on Windows.
+
+cd $WORK/a/b/c/pkg
+
+go list -find -f {{.Root}}
+stdout $PWD
+
+-- $WORK/a/b/c/pkg/go.mod --
+module pkg
+
+-- $WORK/a/b/c/pkg/pkg.go --
+package pkg
diff --git a/src/cmd/go/testdata/script/test_shuffle.txt b/src/cmd/go/testdata/script/test_shuffle.txt
new file mode 100644
index 0000000..98029f5
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_shuffle.txt
@@ -0,0 +1,134 @@
+# Shuffle order of tests and benchmarks
+
+[short] skip 'builds and repeatedly runs a test binary'
+
+# Run tests
+go test -v foo_test.go
+! stdout '-test.shuffle '
+stdout '(?s)TestOne(.*)TestTwo(.*)TestThree'
+
+go test -v -shuffle=off foo_test.go
+! stdout '-test.shuffle '
+stdout '(?s)TestOne(.*)TestTwo(.*)TestThree'
+
+go test -v -shuffle=42 foo_test.go
+stdout '^-test.shuffle 42'
+stdout '(?s)TestThree(.*)TestOne(.*)TestTwo'
+
+go test -v -shuffle=0 foo_test.go
+stdout '^-test.shuffle 0'
+stdout '(?s)TestTwo(.*)TestOne(.*)TestThree'
+
+go test -v -shuffle -1 foo_test.go
+stdout '^-test.shuffle -1'
+stdout '(?s)TestThree(.*)TestOne(.*)TestTwo'
+
+go test -v -shuffle=on foo_test.go
+stdout '^-test.shuffle '
+stdout '(?s)=== RUN TestOne(.*)--- PASS: TestOne'
+stdout '(?s)=== RUN TestTwo(.*)--- PASS: TestTwo'
+stdout '(?s)=== RUN TestThree(.*)--- PASS: TestThree'
+
+
+# Run tests and benchmarks
+go test -v -bench=. foo_test.go
+! stdout '-test.shuffle '
+stdout '(?s)TestOne(.*)TestTwo(.*)TestThree(.*)BenchmarkOne(.*)BenchmarkTwo(.*)BenchmarkThree'
+
+go test -v -bench=. -shuffle=off foo_test.go
+! stdout '-test.shuffle '
+stdout '(?s)TestOne(.*)TestTwo(.*)TestThree(.*)BenchmarkOne(.*)BenchmarkTwo(.*)BenchmarkThree'
+
+go test -v -bench=. -shuffle=42 foo_test.go
+stdout '^-test.shuffle 42'
+stdout '(?s)TestThree(.*)TestOne(.*)TestTwo(.*)BenchmarkThree(.*)BenchmarkOne(.*)BenchmarkTwo'
+
+go test -v -bench=. -shuffle=0 foo_test.go
+stdout '^-test.shuffle 0'
+stdout '(?s)TestTwo(.*)TestOne(.*)TestThree(.*)BenchmarkThree(.*)BenchmarkOne(.*)BenchmarkTwo'
+
+go test -v -bench=. -shuffle -1 foo_test.go
+stdout '^-test.shuffle -1'
+stdout '(?s)TestThree(.*)TestOne(.*)TestTwo(.*)BenchmarkOne(.*)BenchmarkThree(.*)BenchmarkTwo'
+
+go test -v -bench=. -shuffle=on foo_test.go
+stdout '^-test.shuffle '
+stdout '(?s)=== RUN TestOne(.*)--- PASS: TestOne'
+stdout '(?s)=== RUN TestTwo(.*)--- PASS: TestTwo'
+stdout '(?s)=== RUN TestThree(.*)--- PASS: TestThree'
+stdout -count=2 'BenchmarkOne'
+stdout -count=2 'BenchmarkTwo'
+stdout -count=2 'BenchmarkThree'
+
+
+# When running go test -count=N, each of the N runs distinct runs should maintain the same
+# shuffled order of these tests.
+go test -v -shuffle=43 -count=4 foo_test.go
+stdout '^-test.shuffle 43'
+stdout '(?s)TestThree(.*)TestTwo(.*)TestOne(.*)TestThree(.*)TestTwo(.*)TestOne(.*)TestThree(.*)TestTwo(.*)TestOne(.*)TestThree(.*)TestTwo(.*)TestOne'
+
+go test -v -bench=. -shuffle=44 -count=2 foo_test.go
+stdout '^-test.shuffle 44'
+stdout '(?s)TestOne(.*)TestThree(.*)TestTwo(.*)TestOne(.*)TestThree(.*)TestTwo(.*)BenchmarkTwo(.*)BenchmarkOne(.*)BenchmarkThree(.*)'
+
+
+# The feature should work with test binaries as well
+go test -c
+exec ./m.test -test.shuffle=off
+! stdout '^-test.shuffle '
+
+exec ./m.test -test.shuffle=on
+stdout '^-test.shuffle '
+
+exec ./m.test -test.v -test.bench=. -test.shuffle=0 foo_test.go
+stdout '^-test.shuffle 0'
+stdout '(?s)TestTwo(.*)TestOne(.*)TestThree(.*)BenchmarkThree(.*)BenchmarkOne(.*)BenchmarkTwo'
+
+exec ./m.test -test.v -test.bench=. -test.shuffle=123 foo_test.go
+stdout '^-test.shuffle 123'
+stdout '(?s)TestThree(.*)TestOne(.*)TestTwo(.*)BenchmarkThree(.*)BenchmarkTwo(.*)BenchmarkOne'
+
+exec ./m.test -test.v -test.bench=. -test.shuffle=-1 foo_test.go
+stdout '^-test.shuffle -1'
+stdout '(?s)TestThree(.*)TestOne(.*)TestTwo(.*)BenchmarkOne(.*)BenchmarkThree(.*)BenchmarkTwo'
+
+exec ./m.test -test.v -test.bench=. -test.shuffle=44 -test.count=2 foo_test.go
+stdout '^-test.shuffle 44'
+stdout '(?s)TestOne(.*)TestThree(.*)TestTwo(.*)TestOne(.*)TestThree(.*)TestTwo(.*)BenchmarkTwo(.*)BenchmarkOne(.*)BenchmarkThree(.*)'
+
+
+# Negative testcases for invalid input
+! go test -shuffle -count=2
+stderr 'invalid value "-count=2" for flag -shuffle: -shuffle argument must be "on", "off", or an int64: strconv.ParseInt: parsing "-count=2": invalid syntax'
+
+! go test -shuffle=
+stderr '(?s)invalid value "" for flag -shuffle: -shuffle argument must be "on", "off", or an int64: strconv.ParseInt: parsing "": invalid syntax'
+
+! go test -shuffle=' '
+stderr '(?s)invalid value " " for flag -shuffle: -shuffle argument must be "on", "off", or an int64: strconv.ParseInt: parsing " ": invalid syntax'
+
+! go test -shuffle=true
+stderr 'invalid value "true" for flag -shuffle: -shuffle argument must be "on", "off", or an int64: strconv.ParseInt: parsing "true": invalid syntax'
+
+! go test -shuffle='abc'
+stderr 'invalid value "abc" for flag -shuffle: -shuffle argument must be "on", "off", or an int64: strconv.ParseInt: parsing "abc": invalid syntax'
+
+-- go.mod --
+module m
+
+go 1.16
+-- foo_test.go --
+package foo
+
+import "testing"
+
+func TestOne(t *testing.T) {}
+func TestTwo(t *testing.T) {}
+func TestThree(t *testing.T) {}
+
+func BenchmarkOne(b *testing.B) {}
+func BenchmarkTwo(b *testing.B) {}
+func BenchmarkThree(b *testing.B) {}
+
+-- foo.go --
+package foo
diff --git a/src/cmd/go/testdata/script/test_skip.txt b/src/cmd/go/testdata/script/test_skip.txt
new file mode 100644
index 0000000..2e5f4d6
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_skip.txt
@@ -0,0 +1,45 @@
+go test -v -run Test -skip T skip_test.go
+! stdout RUN
+stdout '^ok.*\[no tests to run\]'
+
+go test -v -skip T skip_test.go
+! stdout RUN
+
+go test -v -skip 1 skip_test.go
+! stdout Test1
+stdout RUN.*Test2
+stdout RUN.*Test2/3
+
+go test -v -skip 2/3 skip_test.go
+stdout RUN.*Test1
+stdout RUN.*Test2
+stdout RUN.*ExampleTest1
+! stdout Test2/3
+
+go test -v -skip 2/4 skip_test.go
+stdout RUN.*Test1
+stdout RUN.*Test2
+stdout RUN.*Test2/3
+stdout RUN.*ExampleTest1
+
+go test -v -skip Example skip_test.go
+stdout RUN.*Test1
+stdout RUN.*Test2
+stdout RUN.*Test2/3
+! stdout ExampleTest1
+
+-- skip_test.go --
+package skip_test
+
+import "testing"
+
+func Test1(t *testing.T) {
+}
+
+func Test2(t *testing.T) {
+ t.Run("3", func(t *testing.T) {})
+}
+
+func ExampleTest1() {
+ // Output:
+}
diff --git a/src/cmd/go/testdata/script/test_source_order.txt b/src/cmd/go/testdata/script/test_source_order.txt
new file mode 100644
index 0000000..2865276
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_source_order.txt
@@ -0,0 +1,54 @@
+[short] skip
+
+# Control
+! go test example2_test.go example1_test.go
+
+# This test only passes if the source order is preserved
+go test example1_test.go example2_test.go
+
+-- example1_test.go --
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure that go test runs Example_Z before Example_A, preserving source order.
+
+package p
+
+import "fmt"
+
+var n int
+
+func Example_Z() {
+ n++
+ fmt.Println(n)
+ // Output: 1
+}
+
+func Example_A() {
+ n++
+ fmt.Println(n)
+ // Output: 2
+}
+-- example2_test.go --
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure that go test runs Example_Y before Example_B, preserving source order.
+
+package p
+
+import "fmt"
+
+func Example_Y() {
+ n++
+ fmt.Println(n)
+ // Output: 3
+}
+
+func Example_B() {
+ n++
+ fmt.Println(n)
+ // Output: 4
+}
diff --git a/src/cmd/go/testdata/script/test_status.txt b/src/cmd/go/testdata/script/test_status.txt
new file mode 100644
index 0000000..aa6ad3c
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_status.txt
@@ -0,0 +1,18 @@
+env GO111MODULE=off
+
+! go test x y
+stdout ^FAIL\s+x
+stdout ^ok\s+y
+stdout (?-m)FAIL\n$
+
+-- x/x_test.go --
+package x
+
+import "testing"
+
+func TestNothingJustFail(t *testing.T) {
+ t.Fail()
+}
+
+-- y/y_test.go --
+package y
diff --git a/src/cmd/go/testdata/script/test_syntax_error_says_fail.txt b/src/cmd/go/testdata/script/test_syntax_error_says_fail.txt
new file mode 100644
index 0000000..44ff6e2
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_syntax_error_says_fail.txt
@@ -0,0 +1,25 @@
+# Test that the error message for a syntax error in a test go file
+# says FAIL.
+
+env GO111MODULE=off
+! go test syntaxerror
+stderr 'x_test.go:' # check that the error is diagnosed
+stdout 'FAIL' # check that go test says FAIL
+
+env GO111MODULE=on
+cd syntaxerror
+! go test syntaxerror
+stderr 'x_test.go:' # check that the error is diagnosed
+stdout 'FAIL' # check that go test says FAIL
+
+-- syntaxerror/go.mod --
+module syntaxerror
+
+go 1.16
+-- syntaxerror/x.go --
+package p
+-- syntaxerror/x_test.go --
+package p
+
+func f() (x.y, z int) {
+}
diff --git a/src/cmd/go/testdata/script/test_timeout.txt b/src/cmd/go/testdata/script/test_timeout.txt
new file mode 100644
index 0000000..4de4df4
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_timeout.txt
@@ -0,0 +1,23 @@
+[short] skip
+env GO111MODULE=off
+cd a
+
+# If no timeout is set explicitly, 'go test' should set
+# -test.timeout to its internal deadline.
+go test -v . --
+stdout '10m0s'
+
+# An explicit -timeout argument should be propagated to -test.timeout.
+go test -v -timeout 30m . --
+stdout '30m0s'
+
+-- a/timeout_test.go --
+package t
+import (
+ "flag"
+ "fmt"
+ "testing"
+)
+func TestTimeout(t *testing.T) {
+ fmt.Println(flag.Lookup("test.timeout").Value.String())
+}
diff --git a/src/cmd/go/testdata/script/test_timeout_stdin.txt b/src/cmd/go/testdata/script/test_timeout_stdin.txt
new file mode 100644
index 0000000..f2de0a6
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_timeout_stdin.txt
@@ -0,0 +1,88 @@
+# Regression test for https://go.dev/issue/24050:
+# a test that exits with an I/O stream held open
+# should fail after a reasonable delay, not wait forever.
+# (As of the time of writing, that delay is 10% of the timeout,
+# but this test does not depend on its specific value.)
+
+[short] skip 'runs a test that hangs until its WaitDelay expires'
+
+! go test -v -timeout=1m .
+
+ # After the test process itself prints PASS and exits,
+ # the kernel closes its stdin pipe to to the orphaned subprocess.
+ # At that point, we expect the subprocess to print 'stdin closed'
+ # and periodically log to stderr until the WaitDelay expires.
+ #
+ # Once the WaitDelay expires, the copying goroutine for 'go test' stops and
+ # closes the read side of the stderr pipe, and the subprocess will eventually
+ # exit due to a failed write to that pipe.
+
+stdout '^--- PASS: TestOrphanCmd .*\nPASS\nstdin closed'
+stdout '^\*\*\* Test I/O incomplete \d+.* after exiting\.\nexec: WaitDelay expired before I/O complete\nFAIL\s+example\s+\d+(\.\d+)?s'
+
+-- go.mod --
+module example
+
+go 1.20
+-- main_test.go --
+package main
+
+import (
+ "fmt"
+ "io"
+ "os"
+ "os/exec"
+ "testing"
+ "time"
+)
+
+func TestMain(m *testing.M) {
+ if os.Getenv("TEST_TIMEOUT_HANG") == "1" {
+ io.Copy(io.Discard, os.Stdin)
+ if _, err := os.Stderr.WriteString("stdin closed\n"); err != nil {
+ os.Exit(1)
+ }
+
+ ticker := time.NewTicker(100 * time.Millisecond)
+ for t := range ticker.C {
+ _, err := fmt.Fprintf(os.Stderr, "still alive at %v\n", t)
+ if err != nil {
+ os.Exit(1)
+ }
+ }
+ }
+
+ m.Run()
+}
+
+func TestOrphanCmd(t *testing.T) {
+ exe, err := os.Executable()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ cmd := exec.Command(exe)
+ cmd.Env = append(cmd.Environ(), "TEST_TIMEOUT_HANG=1")
+
+ // Hold stdin open until this (parent) process exits.
+ if _, err := cmd.StdinPipe(); err != nil {
+ t.Fatal(err)
+ }
+
+ // Forward stderr to the subprocess so that it can hold the stream open.
+ cmd.Stderr = os.Stderr
+
+ if err := cmd.Start(); err != nil {
+ t.Fatal(err)
+ }
+ t.Logf("started %v", cmd)
+
+ // Intentionally leak cmd when the test completes.
+ // This will allow the test process itself to exit, but (at least on Unix
+ // platforms) will keep the parent process's stderr stream open.
+ go func() {
+ if err := cmd.Wait(); err != nil {
+ os.Exit(3)
+ }
+ }()
+}
diff --git a/src/cmd/go/testdata/script/test_trimpath.txt b/src/cmd/go/testdata/script/test_trimpath.txt
new file mode 100644
index 0000000..065f9ce
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_trimpath.txt
@@ -0,0 +1,51 @@
+[short] skip
+
+go test -trimpath -v .
+! stdout '[/\\]pkg_test[/\\]'
+stdout -count=3 '[/\\]pkg[/\\]'
+
+-- go.mod --
+module example.com/pkg
+
+go 1.17
+
+-- pkg.go --
+package pkg
+
+import "runtime"
+
+func PrintFile() {
+ _, file, _, _ := runtime.Caller(0)
+ println(file)
+}
+
+-- pkg_test.go --
+package pkg
+
+import "runtime"
+
+func PrintFileForTest() {
+ _, file, _, _ := runtime.Caller(0)
+ println(file)
+}
+
+-- pkg_x_test.go --
+package pkg_test
+
+import (
+ "runtime"
+ "testing"
+
+ "example.com/pkg"
+)
+
+func TestMain(m *testing.M) {
+ pkg.PrintFile()
+ pkg.PrintFileForTest()
+ PrintFileInXTest()
+}
+
+func PrintFileInXTest() {
+ _, file, _, _ := runtime.Caller(0)
+ println(file)
+}
diff --git a/src/cmd/go/testdata/script/test_trimpath_main.txt b/src/cmd/go/testdata/script/test_trimpath_main.txt
new file mode 100644
index 0000000..c076212
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_trimpath_main.txt
@@ -0,0 +1,38 @@
+[short] skip
+
+go test -trimpath -v .
+! stdout '[/\\]pkg_test[/\\]'
+stdout -count=2 '[/\\]pkg[/\\]'
+
+-- go.mod --
+module example.com/pkg
+
+go 1.17
+
+-- main.go --
+package main
+
+import "runtime"
+
+func PrintFile() {
+ _, file, _, _ := runtime.Caller(0)
+ println(file)
+}
+
+-- main_test.go --
+package main
+
+import (
+ "runtime"
+ "testing"
+)
+
+func PrintFileForTest() {
+ _, file, _, _ := runtime.Caller(0)
+ println(file)
+}
+
+func TestMain(m *testing.M) {
+ PrintFile()
+ PrintFileForTest()
+}
diff --git a/src/cmd/go/testdata/script/test_trimpath_test_suffix.txt b/src/cmd/go/testdata/script/test_trimpath_test_suffix.txt
new file mode 100644
index 0000000..6cbad83
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_trimpath_test_suffix.txt
@@ -0,0 +1,40 @@
+[short] skip
+
+go test -trimpath -v .
+! stdout '[/\\]pkg_test_test[/\\]'
+stdout -count=2 '[/\\]pkg_test[/\\]'
+
+-- go.mod --
+module example.com/pkg_test
+
+go 1.17
+
+-- pkg.go --
+package pkg_test
+
+import "runtime"
+
+func PrintFile() {
+ _, file, _, _ := runtime.Caller(0)
+ println(file)
+}
+
+-- pkg_x_test.go --
+package pkg_test_test
+
+import (
+ "runtime"
+ "testing"
+
+ "example.com/pkg_test"
+)
+
+func PrintFileForTest() {
+ _, file, _, _ := runtime.Caller(0)
+ println(file)
+}
+
+func TestMain(m *testing.M) {
+ pkg_test.PrintFile()
+ PrintFileForTest()
+}
diff --git a/src/cmd/go/testdata/script/test_vendor.txt b/src/cmd/go/testdata/script/test_vendor.txt
new file mode 100644
index 0000000..c6a88b6
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_vendor.txt
@@ -0,0 +1,57 @@
+# In GOPATH mode, vendored packages can replace std packages.
+env GO111MODULE=off
+cd vend/hello
+go test -v
+stdout TestMsgInternal
+stdout TestMsgExternal
+
+# In module mode, they cannot.
+env GO111MODULE=on
+! go test -mod=vendor
+stderr 'undefined: strings.Msg'
+
+-- vend/hello/go.mod --
+module vend/hello
+
+go 1.16
+-- vend/hello/hello.go --
+package main
+
+import (
+ "fmt"
+ "strings" // really ../vendor/strings
+)
+
+func main() {
+ fmt.Printf("%s\n", strings.Msg)
+}
+-- vend/hello/hello_test.go --
+package main
+
+import (
+ "strings" // really ../vendor/strings
+ "testing"
+)
+
+func TestMsgInternal(t *testing.T) {
+ if strings.Msg != "hello, world" {
+ t.Fatalf("unexpected msg: %v", strings.Msg)
+ }
+}
+-- vend/hello/hellox_test.go --
+package main_test
+
+import (
+ "strings" // really ../vendor/strings
+ "testing"
+)
+
+func TestMsgExternal(t *testing.T) {
+ if strings.Msg != "hello, world" {
+ t.Fatalf("unexpected msg: %v", strings.Msg)
+ }
+}
+-- vend/vendor/strings/msg.go --
+package strings
+
+var Msg = "hello, world"
diff --git a/src/cmd/go/testdata/script/test_vet.txt b/src/cmd/go/testdata/script/test_vet.txt
new file mode 100644
index 0000000..6151f91
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_vet.txt
@@ -0,0 +1,123 @@
+[short] skip
+
+# Test file
+! go test p1_test.go
+stderr 'Logf format %d'
+go test -vet=off
+stdout '^ok'
+
+# Non-test file
+! go test p1.go
+stderr 'Printf format %d'
+go test -x -vet=shift p1.go
+stderr '[\\/]vet.*-shift'
+stdout '\[no test files\]'
+go test -vet=off p1.go
+! stderr '[\\/]vet.*-shift'
+stdout '\[no test files\]'
+
+# ensure all runs non-default vet
+! go test -vet=all ./vetall/...
+stderr 'using resp before checking for errors'
+
+# Test issue #47309
+! go test -vet=bools,xyz ./vetall/...
+stderr '-vet argument must be a supported analyzer'
+
+# Test with a single analyzer
+! go test -vet=httpresponse ./vetall/...
+stderr 'using resp before checking for errors'
+
+# Test with a list of analyzers
+go test -vet=atomic,bools,nilfunc ./vetall/...
+stdout 'm/vetall.*\[no tests to run\]'
+
+# Test issue #22890
+go test m/vetcycle
+stdout 'm/vetcycle.*\[no test files\]'
+
+# Test with ...
+! go test ./vetfail/...
+stderr 'Printf format %d'
+stdout 'ok\s+m/vetfail/p2'
+
+# Check there's no diagnosis of a bad build constraint in vetxonly mode.
+# Use -a so that we need to recompute the vet-specific export data for
+# vetfail/p1.
+go test -a m/vetfail/p2
+! stderr 'invalid.*constraint'
+
+-- go.mod --
+module m
+
+go 1.16
+-- p1_test.go --
+package p
+
+import "testing"
+
+func Test(t *testing.T) {
+ t.Logf("%d") // oops
+}
+-- p1.go --
+package p
+
+import "fmt"
+
+func F() {
+ fmt.Printf("%d") // oops
+}
+-- vetall/p.go --
+package p
+
+import "net/http"
+
+func F() {
+ resp, err := http.Head("example.com")
+ defer resp.Body.Close()
+ if err != nil {
+ panic(err)
+ }
+ // (defer statement belongs here)
+}
+-- vetall/p_test.go --
+package p
+-- vetcycle/p.go --
+package p
+
+type (
+ _ interface{ m(B1) }
+ A1 interface{ a(D1) }
+ B1 interface{ A1 }
+ C1 interface {
+ B1 /* ERROR issue #18395 */
+ }
+ D1 interface{ C1 }
+)
+
+var _ A1 = C1 /* ERROR cannot use C1 */ (nil)
+-- vetfail/p1/p1.go --
+// +build !foo-bar
+
+package p1
+
+import "fmt"
+
+func F() {
+ fmt.Printf("%d", "hello") // causes vet error
+}
+-- vetfail/p2/p2.go --
+package p2
+
+import _ "m/vetfail/p1"
+
+func F() {
+}
+-- vetfail/p2/p2_test.go --
+package p2
+
+import "testing"
+
+func TestF(t *testing.T) {
+ F()
+}
diff --git a/src/cmd/go/testdata/script/test_write_profiles_on_timeout.txt b/src/cmd/go/testdata/script/test_write_profiles_on_timeout.txt
new file mode 100644
index 0000000..0db183f
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_write_profiles_on_timeout.txt
@@ -0,0 +1,26 @@
+# Tests issue 19394
+
+[short] skip
+
+! go test -cpuprofile cpu.pprof -memprofile mem.pprof -timeout 1ms
+stdout '^panic: test timed out'
+grep . cpu.pprof
+grep . mem.pprof
+
+-- go.mod --
+module profiling
+
+go 1.16
+-- timeout_test.go --
+package timeouttest_test
+
+import (
+ "testing"
+ "time"
+)
+
+func TestSleep(t *testing.T) {
+ for {
+ time.Sleep(1 * time.Second)
+ }
+}
diff --git a/src/cmd/go/testdata/script/test_xtestonly_works.txt b/src/cmd/go/testdata/script/test_xtestonly_works.txt
new file mode 100644
index 0000000..8e150db
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_xtestonly_works.txt
@@ -0,0 +1,27 @@
+[short] skip
+
+go test xtestonly
+! stdout '^ok.*\[no tests to run\]'
+stdout '^ok'
+
+-- go.mod --
+module xtestonly
+
+go 1.16
+-- f.go --
+package xtestonly
+
+func F() int { return 42 }
+-- f_test.go --
+package xtestonly_test
+
+import (
+ "testing"
+ "xtestonly"
+)
+
+func TestF(t *testing.T) {
+ if x := xtestonly.F(); x != 42 {
+ t.Errorf("f.F() = %d, want 42", x)
+ }
+}
diff --git a/src/cmd/go/testdata/script/testing_coverage.txt b/src/cmd/go/testdata/script/testing_coverage.txt
new file mode 100644
index 0000000..6cf6adb
--- /dev/null
+++ b/src/cmd/go/testdata/script/testing_coverage.txt
@@ -0,0 +1,57 @@
+
+# Rudimentary test of testing.Coverage().
+
+[short] skip
+[!GOEXPERIMENT:coverageredesign] skip
+
+# Simple test.
+go test -v -cover -count=1
+
+# Make sure test still passes when test executable is built and
+# run outside the go command.
+go test -c -o t.exe -cover
+exec ./t.exe
+
+-- go.mod --
+module hello
+
+go 1.20
+-- hello.go --
+package hello
+
+func Hello() {
+ println("hello")
+}
+
+// contents not especially interesting, just need some code
+func foo(n int) int {
+ t := 0
+ for i := 0; i < n; i++ {
+ for j := 0; j < i; j++ {
+ t += i ^ j
+ if t == 1010101 {
+ break
+ }
+ }
+ }
+ return t
+}
+
+-- hello_test.go --
+package hello
+
+import "testing"
+
+func TestTestCoverage(t *testing.T) {
+ Hello()
+ C1 := testing.Coverage()
+ foo(29)
+ C2 := testing.Coverage()
+ if C1 == 0.0 || C2 == 0.0 {
+ t.Errorf("unexpected zero values C1=%f C2=%f", C1, C2)
+ }
+ if C1 >= C2 {
+ t.Errorf("testing.Coverage() not monotonically increasing C1=%f C2=%f", C1, C2)
+ }
+}
+
diff --git a/src/cmd/go/testdata/script/testing_issue40908.txt b/src/cmd/go/testdata/script/testing_issue40908.txt
new file mode 100644
index 0000000..839320e
--- /dev/null
+++ b/src/cmd/go/testdata/script/testing_issue40908.txt
@@ -0,0 +1,25 @@
+[short] skip
+[!race] skip
+
+go test -race testrace
+
+-- go.mod --
+module testrace
+
+go 1.16
+-- race_test.go --
+package testrace
+
+import "testing"
+
+func TestRace(t *testing.T) {
+ helperDone := make(chan struct{})
+ go func() {
+ t.Logf("Something happened before cleanup.")
+ close(helperDone)
+ }()
+
+ t.Cleanup(func() {
+ <-helperDone
+ })
+}
diff --git a/src/cmd/go/testdata/script/toolexec.txt b/src/cmd/go/testdata/script/toolexec.txt
new file mode 100644
index 0000000..20a5968
--- /dev/null
+++ b/src/cmd/go/testdata/script/toolexec.txt
@@ -0,0 +1,128 @@
+[short] skip
+
+# Build our simple toolexec program.
+go build ./cmd/mytool
+
+# Use an ephemeral build cache so that our toolexec output is not cached
+# for any stale standard-library dependencies.
+#
+# TODO(#27628): This should not be necessary.
+env GOCACHE=$WORK/gocache
+
+# Build the main package with our toolexec program. For each action, it will
+# print the tool's name and the TOOLEXEC_IMPORTPATH value. We expect to compile
+# each package once, and link the main package once.
+# Don't check the entire output at once, because the order in which the tools
+# are run is irrelevant here.
+# Finally, note that asm and cgo are run twice.
+
+go build -toolexec=$PWD/mytool
+[GOARCH:amd64] stderr -count=2 '^asm'${GOEXE}' TOOLEXEC_IMPORTPATH="test/main/withasm"$'
+stderr -count=1 '^compile'${GOEXE}' TOOLEXEC_IMPORTPATH="test/main/withasm"$'
+[cgo] stderr -count=2 '^cgo'${GOEXE}' TOOLEXEC_IMPORTPATH="test/main/withcgo"$'
+[cgo] stderr -count=1 '^compile'${GOEXE}' TOOLEXEC_IMPORTPATH="test/main/withcgo"$'
+stderr -count=1 '^compile'${GOEXE}' TOOLEXEC_IMPORTPATH="test/main"$'
+stderr -count=1 '^link'${GOEXE}' TOOLEXEC_IMPORTPATH="test/main"$'
+
+# Test packages are a little bit trickier.
+# We have four variants of test/main, as reported by 'go list -test':
+#
+# test/main - the regular non-test package
+# test/main.test - the generated test program
+# test/main [test/main.test] - the test package for foo_test.go
+# test/main_test [test/main.test] - the test package for foo_separate_test.go
+#
+# As such, TOOLEXEC_IMPORTPATH must see the same strings, to be able to uniquely
+# identify each package being built as reported by 'go list -f {{.ImportPath}}'.
+# Note that these are not really "import paths" anymore, but that naming is
+# consistent with 'go list -json' at least.
+
+go test -toolexec=$PWD/mytool
+
+stderr -count=2 '^# test/main\.test$'
+stderr -count=1 '^compile'${GOEXE}' TOOLEXEC_IMPORTPATH="test/main\.test"$'
+stderr -count=1 '^link'${GOEXE}' TOOLEXEC_IMPORTPATH="test/main\.test"$'
+
+stderr -count=1 '^# test/main \[test/main\.test\]$'
+stderr -count=1 '^compile'${GOEXE}' TOOLEXEC_IMPORTPATH="test/main \[test/main\.test\]"$'
+
+stderr -count=1 '^# test/main_test \[test/main\.test\]$'
+stderr -count=1 '^compile'${GOEXE}' TOOLEXEC_IMPORTPATH="test/main_test \[test/main\.test\]"$'
+
+-- go.mod --
+module test/main
+-- foo.go --
+// Simple package so we can test a program build with -toolexec.
+// With a dummy import, to test different TOOLEXEC_IMPORTPATH values.
+// Includes dummy uses of cgo and asm, to cover those tools as well.
+package main
+
+import (
+ _ "test/main/withasm"
+ _ "test/main/withcgo"
+)
+
+func main() {}
+-- foo_test.go --
+package main
+
+import "testing"
+
+func TestFoo(t *testing.T) {}
+-- foo_separate_test.go --
+package main_test
+
+import "testing"
+
+func TestSeparateFoo(t *testing.T) {}
+-- withcgo/withcgo.go --
+package withcgo
+
+// int fortytwo()
+// {
+// return 42;
+// }
+import "C"
+-- withcgo/stub.go --
+package withcgo
+
+// Stub file to ensure we build without cgo too.
+-- withasm/withasm.go --
+package withasm
+
+// Note that we don't need to declare the Add func at all.
+-- withasm/withasm_amd64.s --
+TEXT ·Add(SB),$0-24
+ MOVQ a+0(FP), AX
+ ADDQ b+8(FP), AX
+ MOVQ AX, ret+16(FP)
+ RET
+-- cmd/mytool/main.go --
+package main
+
+import (
+ "fmt"
+ "os"
+ "os/exec"
+ "path/filepath"
+)
+
+func main() {
+ tool, args := os.Args[1], os.Args[2:]
+ toolName := filepath.Base(tool)
+ if len(args) > 0 && args[0] == "-V=full" {
+ // We can't alter the version output.
+ } else {
+ // Print which tool we're running, and on what package.
+ fmt.Fprintf(os.Stdout, "%s TOOLEXEC_IMPORTPATH=%q\n", toolName, os.Getenv("TOOLEXEC_IMPORTPATH"))
+ }
+
+ // Simply run the tool.
+ cmd := exec.Command(tool, args...)
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ if err := cmd.Run(); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+}
diff --git a/src/cmd/go/testdata/script/tooltags.txt b/src/cmd/go/testdata/script/tooltags.txt
new file mode 100644
index 0000000..27068ee
--- /dev/null
+++ b/src/cmd/go/testdata/script/tooltags.txt
@@ -0,0 +1,57 @@
+env GOOS=linux
+
+env GOARCH=amd64
+env GOAMD64=v3
+go list -f '{{context.ToolTags}}'
+stdout 'amd64.v1 amd64.v2 amd64.v3'
+
+env GOARCH=arm
+env GOARM=6
+go list -f '{{context.ToolTags}}'
+stdout 'arm.5 arm.6'
+
+env GOARCH=mips
+env GOMIPS=hardfloat
+go list -f '{{context.ToolTags}}'
+stdout 'mips.hardfloat'
+
+env GOARCH=mips64
+env GOMIPS=hardfloat
+go list -f '{{context.ToolTags}}'
+stdout 'mips64.hardfloat'
+
+env GOARCH=ppc64
+env GOPPC64=power9
+go list -f '{{context.ToolTags}}'
+stdout 'ppc64.power8 ppc64.power9'
+
+env GOARCH=ppc64
+env GOPPC64=power10
+go list -f '{{context.ToolTags}}'
+stdout 'ppc64.power8 ppc64.power9 ppc64.power10'
+
+env GOARCH=ppc64le
+env GOPPC64=power9
+go list -f '{{context.ToolTags}}'
+stdout 'ppc64le.power8 ppc64le.power9'
+
+env GOARCH=ppc64le
+env GOPPC64=power10
+go list -f '{{context.ToolTags}}'
+stdout 'ppc64le.power8 ppc64le.power9 ppc64le.power10'
+
+env GOARCH=386
+env GO386=sse2
+go list -f '{{context.ToolTags}}'
+stdout '386.sse2'
+
+env GOARCH=wasm
+env GOWASM=satconv
+go list -f '{{context.ToolTags}}'
+stdout 'wasm.satconv'
+
+-- go.mod --
+module m
+
+-- p.go --
+package p
diff --git a/src/cmd/go/testdata/script/trampoline_reuse_test.txt b/src/cmd/go/testdata/script/trampoline_reuse_test.txt
new file mode 100644
index 0000000..41e86e4
--- /dev/null
+++ b/src/cmd/go/testdata/script/trampoline_reuse_test.txt
@@ -0,0 +1,100 @@
+# Verify PPC64 does not reuse a trampoline which is too far away.
+# This tests an edge case where the direct call relocation addend should
+# be ignored when computing the distance from the direct call to the
+# already placed trampoline
+[short] skip
+[!GOARCH:ppc64] [!GOARCH:ppc64le] skip
+[GOOS:aix] skip
+
+# Note, this program does not run. Presumably, 'DWORD $0' is simpler to
+# assembly 2^26 or so times.
+#
+# We build something which should be laid out as such:
+#
+# bar.Bar
+# main.Func1
+# bar.Bar+400-tramp0
+# main.BigAsm
+# main.Func2
+# bar.Bar+400-tramp1
+#
+# bar.Bar needs to be placed far enough away to generate relocations
+# from main package calls. and main.Func1 and main.Func2 are placed
+# a bit more than the direct call limit apart, but not more than 0x400
+# bytes beyond it (to verify the reloc calc).
+
+go build
+
+-- go.mod --
+
+module foo
+
+go 1.19
+
+-- main.go --
+
+package main
+
+import "foo/bar"
+
+func Func1()
+
+func main() {
+ Func1()
+ bar.Bar2()
+}
+
+-- foo.s --
+
+TEXT main·Func1(SB),0,$0-0
+ CALL bar·Bar+0x400(SB)
+ CALL main·BigAsm(SB)
+// A trampoline will be placed here to bar.Bar
+
+// This creates a gap sufficiently large to prevent trampoline reuse
+#define NOP64 DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0;
+#define NOP256 NOP64 NOP64 NOP64 NOP64
+#define NOP2S10 NOP256 NOP256 NOP256 NOP256
+#define NOP2S12 NOP2S10 NOP2S10 NOP2S10 NOP2S10
+#define NOP2S14 NOP2S12 NOP2S12 NOP2S12 NOP2S12
+#define NOP2S16 NOP2S14 NOP2S14 NOP2S14 NOP2S14
+#define NOP2S18 NOP2S16 NOP2S16 NOP2S16 NOP2S16
+#define NOP2S20 NOP2S18 NOP2S18 NOP2S18 NOP2S18
+#define NOP2S22 NOP2S20 NOP2S20 NOP2S20 NOP2S20
+#define NOP2S24 NOP2S22 NOP2S22 NOP2S22 NOP2S22
+#define BIGNOP NOP2S24 NOP2S24
+TEXT main·BigAsm(SB),0,$0-0
+ // Fill to the direct call limit so Func2 must generate a new trampoline.
+ // As the implicit trampoline above is just barely unreachable.
+ BIGNOP
+ MOVD $main·Func2(SB), R3
+
+TEXT main·Func2(SB),0,$0-0
+ CALL bar·Bar+0x400(SB)
+// Another trampoline should be placed here.
+
+-- bar/bar.s --
+
+#define NOP64 DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0;
+#define NOP256 NOP64 NOP64 NOP64 NOP64
+#define NOP2S10 NOP256 NOP256 NOP256 NOP256
+#define NOP2S12 NOP2S10 NOP2S10 NOP2S10 NOP2S10
+#define NOP2S14 NOP2S12 NOP2S12 NOP2S12 NOP2S12
+#define NOP2S16 NOP2S14 NOP2S14 NOP2S14 NOP2S14
+#define NOP2S18 NOP2S16 NOP2S16 NOP2S16 NOP2S16
+#define NOP2S20 NOP2S18 NOP2S18 NOP2S18 NOP2S18
+#define NOP2S22 NOP2S20 NOP2S20 NOP2S20 NOP2S20
+#define NOP2S24 NOP2S22 NOP2S22 NOP2S22 NOP2S22
+#define BIGNOP NOP2S24 NOP2S24 NOP2S10
+// A very big not very interesting function.
+TEXT bar·Bar(SB),0,$0-0
+ BIGNOP
+
+-- bar/bar.go --
+
+package bar
+
+func Bar()
+
+func Bar2() {
+}
diff --git a/src/cmd/go/testdata/script/vendor_complex.txt b/src/cmd/go/testdata/script/vendor_complex.txt
new file mode 100644
index 0000000..290efdb
--- /dev/null
+++ b/src/cmd/go/testdata/script/vendor_complex.txt
@@ -0,0 +1,75 @@
+env GO111MODULE=off
+
+# smoke test for complex build configuration
+go build -o complex.exe complex
+[!cross] [exec:gccgo] go build -compiler=gccgo -o complex.exe complex
+
+-- complex/main.go --
+package main
+
+import (
+ _ "complex/nest/sub/test12"
+ _ "complex/nest/sub/test23"
+ "complex/w"
+ "v"
+)
+
+func main() {
+ println(v.Hello + " " + w.World)
+}
+
+-- complex/nest/sub/test12/p.go --
+package test12
+
+// Check that vendor/v1 is used but vendor/v2 is NOT used (sub/vendor/v2 wins).
+
+import (
+ "v1"
+ "v2"
+)
+
+const x = v1.ComplexNestVendorV1
+const y = v2.ComplexNestSubVendorV2
+
+-- complex/nest/sub/test23/p.go --
+package test23
+
+// Check that vendor/v3 is used but vendor/v2 is NOT used (sub/vendor/v2 wins).
+
+import (
+ "v2"
+ "v3"
+)
+
+const x = v3.ComplexNestVendorV3
+const y = v2.ComplexNestSubVendorV2
+
+-- complex/nest/sub/vendor/v2/v2.go --
+package v2
+
+const ComplexNestSubVendorV2 = true
+
+-- complex/nest/vendor/v1/v1.go --
+package v1
+
+const ComplexNestVendorV1 = true
+
+-- complex/nest/vendor/v2/v2.go --
+package v2
+
+const ComplexNestVendorV2 = true
+
+-- complex/nest/vendor/v3/v3.go --
+package v3
+
+const ComplexNestVendorV3 = true
+
+-- complex/vendor/v/v.go --
+package v
+
+const Hello = "hello"
+
+-- complex/w/w.go --
+package w
+
+const World = "world"
diff --git a/src/cmd/go/testdata/script/vendor_gopath_issue11409.txt b/src/cmd/go/testdata/script/vendor_gopath_issue11409.txt
new file mode 100644
index 0000000..c85f674
--- /dev/null
+++ b/src/cmd/go/testdata/script/vendor_gopath_issue11409.txt
@@ -0,0 +1,52 @@
+[!GOOS:windows] [short] stop 'this test only applies to Windows'
+env GO111MODULE=off
+
+go build run_go.go
+exec ./run_go$GOEXE $GOPATH $GOPATH/src/vend/hello
+stdout 'hello, world'
+
+-- run_go.go --
+package main
+
+import (
+ "fmt"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+)
+
+func changeVolume(s string, f func(s string) string) string {
+ vol := filepath.VolumeName(s)
+ return f(vol) + s[len(vol):]
+}
+
+func main() {
+ gopath := changeVolume(os.Args[1], strings.ToLower)
+ dir := changeVolume(os.Args[2], strings.ToUpper)
+ cmd := exec.Command("go", "run", "hello.go")
+ cmd.Dir = dir
+ cmd.Env = append(os.Environ(), "GOPATH="+gopath)
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ if err := cmd.Run(); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+}
+
+-- vend/hello/hello.go --
+package main
+
+import (
+ "fmt"
+ "strings" // really ../vendor/strings
+)
+
+func main() {
+ fmt.Printf("%s\n", strings.Msg)
+}
+-- vend/vendor/strings/msg.go --
+package strings
+
+var Msg = "hello, world"
diff --git a/src/cmd/go/testdata/script/vendor_import.txt b/src/cmd/go/testdata/script/vendor_import.txt
new file mode 100644
index 0000000..c64af2c
--- /dev/null
+++ b/src/cmd/go/testdata/script/vendor_import.txt
@@ -0,0 +1,106 @@
+# Imports
+env GO111MODULE=off
+
+# Pass -e to permit errors (e.g. bad.go, invalid.go)
+go list -f '{{.ImportPath}} {{.Imports}}' -e 'vend/...' 'vend/vendor/...' 'vend/x/vendor/...'
+cmp stdout want_vendor_imports.txt
+
+-- want_vendor_imports.txt --
+vend [vend/vendor/p r]
+vend/dir1 []
+vend/hello [fmt vend/vendor/strings]
+vend/subdir [vend/vendor/p r]
+vend/x [vend/x/vendor/p vend/vendor/q vend/x/vendor/r vend/dir1 vend/vendor/vend/dir1/dir2]
+vend/x/invalid [vend/x/invalid/vendor/foo]
+vend/vendor/p []
+vend/vendor/q []
+vend/vendor/strings []
+vend/vendor/vend/dir1/dir2 []
+vend/x/vendor/p []
+vend/x/vendor/p/p [notfound]
+vend/x/vendor/r []
+-- vend/bad.go --
+package vend
+
+import _ "r"
+-- vend/dir1/dir1.go --
+package dir1
+-- vend/good.go --
+package vend
+
+import _ "p"
+-- vend/hello/hello.go --
+package main
+
+import (
+ "fmt"
+ "strings" // really ../vendor/strings
+)
+
+func main() {
+ fmt.Printf("%s\n", strings.Msg)
+}
+-- vend/hello/hello_test.go --
+package main
+
+import (
+ "strings" // really ../vendor/strings
+ "testing"
+)
+
+func TestMsgInternal(t *testing.T) {
+ if strings.Msg != "hello, world" {
+ t.Fatalf("unexpected msg: %v", strings.Msg)
+ }
+}
+-- vend/hello/hellox_test.go --
+package main_test
+
+import (
+ "strings" // really ../vendor/strings
+ "testing"
+)
+
+func TestMsgExternal(t *testing.T) {
+ if strings.Msg != "hello, world" {
+ t.Fatalf("unexpected msg: %v", strings.Msg)
+ }
+}
+-- vend/subdir/bad.go --
+package subdir
+
+import _ "r"
+-- vend/subdir/good.go --
+package subdir
+
+import _ "p"
+-- vend/vendor/p/p.go --
+package p
+-- vend/vendor/q/q.go --
+package q
+-- vend/vendor/strings/msg.go --
+package strings
+
+var Msg = "hello, world"
+-- vend/vendor/vend/dir1/dir2/dir2.go --
+package dir2
+-- vend/x/invalid/invalid.go --
+package invalid
+
+import "vend/x/invalid/vendor/foo"
+-- vend/x/vendor/p/p/p.go --
+package p
+
+import _ "notfound"
+-- vend/x/vendor/p/p.go --
+package p
+-- vend/x/vendor/r/r.go --
+package r
+-- vend/x/x.go --
+package x
+
+import _ "p"
+import _ "q"
+import _ "r"
+import _ "vend/dir1" // not vendored
+import _ "vend/dir1/dir2" // vendored
diff --git a/src/cmd/go/testdata/script/vendor_import_missing.txt b/src/cmd/go/testdata/script/vendor_import_missing.txt
new file mode 100644
index 0000000..8e50dfe
--- /dev/null
+++ b/src/cmd/go/testdata/script/vendor_import_missing.txt
@@ -0,0 +1,7 @@
+# Missing package error message
+! go build vend/x/vendor/p/p
+
+-- vend/x/vendor/p/p/p.go --
+package p
+
+import _ "notfound"
diff --git a/src/cmd/go/testdata/script/vendor_import_wrong.txt b/src/cmd/go/testdata/script/vendor_import_wrong.txt
new file mode 100644
index 0000000..73bf595
--- /dev/null
+++ b/src/cmd/go/testdata/script/vendor_import_wrong.txt
@@ -0,0 +1,20 @@
+# Wrong import path
+env GO111MODULE=off
+! go build vend/x/invalid
+stderr 'must be imported as foo'
+
+env GO111MODULE=
+cd vend/x/invalid
+! go build vend/x/invalid
+stderr 'must be imported as foo'
+
+-- vend/x/invalid/go.mod --
+module vend/x/invalid
+
+go 1.16
+
+-- vend/x/invalid/invalid.go --
+package invalid
+
+import "vend/x/invalid/vendor/foo"
+
diff --git a/src/cmd/go/testdata/script/vendor_internal.txt b/src/cmd/go/testdata/script/vendor_internal.txt
new file mode 100644
index 0000000..4c0f1fa
--- /dev/null
+++ b/src/cmd/go/testdata/script/vendor_internal.txt
@@ -0,0 +1,16 @@
+go build ./vendor/foo.com/internal/bar/a
+
+-- go.mod --
+module example.com/x
+go 1.19
+
+require "foo.com/internal/bar" v1.0.0
+-- vendor/modules.txt --
+# foo.com/internal/bar v1.0.0
+## explicit
+foo.com/internal/bar/a
+-- vendor/foo.com/internal/bar/a/a.go --
+package a
+import _ "foo.com/internal/bar/b"
+-- vendor/foo.com/internal/bar/b/b.go --
+package b \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/vendor_issue12156.txt b/src/cmd/go/testdata/script/vendor_issue12156.txt
new file mode 100644
index 0000000..ac95c6d
--- /dev/null
+++ b/src/cmd/go/testdata/script/vendor_issue12156.txt
@@ -0,0 +1,16 @@
+# Tests issue #12156, a former index out of range panic.
+
+env GO111MODULE=off
+env GOPATH=$WORK/gopath/src/testvendor2 # vendor/x is directly in $GOPATH, not in $GOPATH/src
+cd $WORK/gopath/src/testvendor2/src/p
+
+! go build p.go
+! stderr panic # Make sure it doesn't panic
+stderr 'cannot find package "x"'
+
+-- testvendor2/src/p/p.go --
+package p
+
+import "x"
+-- testvendor2/vendor/x/x.go --
+package x
diff --git a/src/cmd/go/testdata/script/vendor_list_issue11977.txt b/src/cmd/go/testdata/script/vendor_list_issue11977.txt
new file mode 100644
index 0000000..f1ed613
--- /dev/null
+++ b/src/cmd/go/testdata/script/vendor_list_issue11977.txt
@@ -0,0 +1,87 @@
+env GO111MODULE=off
+
+go list -f '{{join .TestImports "\n"}}' github.com/rsc/go-get-issue-11864/t
+stdout 'go-get-issue-11864/vendor/vendor.org/p'
+
+go list -f '{{join .XTestImports "\n"}}' github.com/rsc/go-get-issue-11864/tx
+stdout 'go-get-issue-11864/vendor/vendor.org/p'
+
+go list -f '{{join .XTestImports "\n"}}' github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx2
+stdout 'go-get-issue-11864/vendor/vendor.org/tx2'
+
+go list -f '{{join .XTestImports "\n"}}' github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx3
+stdout 'go-get-issue-11864/vendor/vendor.org/tx3'
+
+-- $GOPATH/src/github.com/rsc/go-get-issue-11864/m.go --
+package g
+
+import _ "vendor.org/p"
+import _ "vendor.org/p1"
+
+func main() {}
+
+-- $GOPATH/src/github.com/rsc/go-get-issue-11864/t/t_test.go --
+package t
+
+import _ "vendor.org/p"
+import _ "vendor.org/p1"
+import "testing"
+
+func TestNop(t *testing.T) {}
+
+-- $GOPATH/src/github.com/rsc/go-get-issue-11864/t/t.go --
+package t
+
+-- $GOPATH/src/github.com/rsc/go-get-issue-11864/tx/tx_test.go --
+package tx_test
+
+import _ "vendor.org/p"
+import _ "vendor.org/p1"
+import "testing"
+
+func TestNop(t *testing.T) {}
+
+-- $GOPATH/src/github.com/rsc/go-get-issue-11864/tx/tx.go --
+package tx
+
+-- $GOPATH/src/github.com/rsc/go-get-issue-11864/vendor/vendor.org/p1/p1.go --
+package p1 // import "vendor.org/p1"
+
+-- $GOPATH/src/github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx3/tx3_test.go --
+package tx3_test
+
+import "vendor.org/tx3"
+import "testing"
+
+var Found = tx3.Exported
+
+func TestNop(t *testing.T) {}
+
+-- $GOPATH/src/github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx3/export_test.go --
+package tx3
+
+var Exported = true
+
+-- $GOPATH/src/github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx3/tx3.go --
+package tx3
+
+-- $GOPATH/src/github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx2/tx2_test.go --
+package tx2_test
+
+import . "vendor.org/tx2"
+import "testing"
+
+var Found = Exported
+
+func TestNop(t *testing.T) {}
+
+-- $GOPATH/src/github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx2/export_test.go --
+package tx2
+
+var Exported = true
+
+-- $GOPATH/src/github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx2/tx2.go --
+package tx2
+
+-- $GOPATH/src/github.com/rsc/go-get-issue-11864/vendor/vendor.org/p/p.go --
+package p
diff --git a/src/cmd/go/testdata/script/vendor_outside_module.txt b/src/cmd/go/testdata/script/vendor_outside_module.txt
new file mode 100644
index 0000000..3ad4579
--- /dev/null
+++ b/src/cmd/go/testdata/script/vendor_outside_module.txt
@@ -0,0 +1,36 @@
+# baz.go (importing just fmt) works with -mod=mod, -mod=vendor.
+go build -x -mod=mod my-module/vendor/example.com/another-module/foo/bar/baz.go
+go build -x -mod=readonly my-module/vendor/example.com/another-module/foo/bar/baz.go
+go build -x -mod=vendor my-module/vendor/example.com/another-module/foo/bar/baz.go
+
+# baz_with_outside_dep.go (with a non-std dependency) works with -mod=mod
+# but not with -mod=readonly and -mod=vendor.
+go build -x -mod=mod my-module/vendor/example.com/another-module/foo/bar/baz_with_outside_dep.go
+! go build -x -mod=readonly my-module/vendor/example.com/another-module/foo/bar/baz_with_outside_dep.go
+stderr 'no required module provides package rsc.io/quote'
+! go build -x -mod=vendor my-module/vendor/example.com/another-module/foo/bar/baz_with_outside_dep.go
+stderr 'no required module provides package rsc.io/quote'
+
+-- my-module/go.mod --
+module example.com/my-module
+
+go 1.20
+-- my-module/vendor/example.com/another-module/foo/bar/baz.go --
+package main
+
+import "fmt"
+
+func main() {
+ fmt.Println("hello, world.")
+}
+-- my-module/vendor/example.com/another-module/foo/bar/baz_with_outside_dep.go --
+package main
+
+import (
+ "fmt"
+ "rsc.io/quote"
+)
+
+func main() {
+ fmt.Println(quote.Hello())
+}
diff --git a/src/cmd/go/testdata/script/vendor_resolve.txt b/src/cmd/go/testdata/script/vendor_resolve.txt
new file mode 100644
index 0000000..bc8cf0a
--- /dev/null
+++ b/src/cmd/go/testdata/script/vendor_resolve.txt
@@ -0,0 +1,21 @@
+env GO111MODULE=off
+! go build p
+stderr 'must be imported as x'
+
+-- p/p.go --
+package p
+
+import (
+ _ "q/y"
+ _ "q/z"
+)
+-- q/vendor/x/x.go --
+package x
+-- q/y/y.go --
+package y
+
+import _ "x"
+-- q/z/z.go --
+package z
+
+import _ "q/vendor/x"
diff --git a/src/cmd/go/testdata/script/vendor_test_issue11864.txt b/src/cmd/go/testdata/script/vendor_test_issue11864.txt
new file mode 100644
index 0000000..90c9c59
--- /dev/null
+++ b/src/cmd/go/testdata/script/vendor_test_issue11864.txt
@@ -0,0 +1,83 @@
+[short] skip
+env GO111MODULE=off
+
+# test should work too
+go test github.com/rsc/go-get-issue-11864
+go test github.com/rsc/go-get-issue-11864/t
+
+# external tests should observe internal test exports (golang.org/issue/11977)
+go test github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx2
+
+-- $GOPATH/src/github.com/rsc/go-get-issue-11864/m.go --
+package g
+
+import _ "vendor.org/p"
+import _ "vendor.org/p1"
+
+func main() {}
+
+-- $GOPATH/src/github.com/rsc/go-get-issue-11864/t/t_test.go --
+package t
+
+import _ "vendor.org/p"
+import _ "vendor.org/p1"
+import "testing"
+
+func TestNop(t *testing.T) {}
+
+-- $GOPATH/src/github.com/rsc/go-get-issue-11864/t/t.go --
+package t
+
+-- $GOPATH/src/github.com/rsc/go-get-issue-11864/tx/tx_test.go --
+package tx_test
+
+import _ "vendor.org/p"
+import _ "vendor.org/p1"
+import "testing"
+
+func TestNop(t *testing.T) {}
+
+-- $GOPATH/src/github.com/rsc/go-get-issue-11864/tx/tx.go --
+package tx
+
+-- $GOPATH/src/github.com/rsc/go-get-issue-11864/vendor/vendor.org/p1/p1.go --
+package p1 // import "vendor.org/p1"
+
+-- $GOPATH/src/github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx3/tx3_test.go --
+package tx3_test
+
+import "vendor.org/tx3"
+import "testing"
+
+var Found = tx3.Exported
+
+func TestNop(t *testing.T) {}
+
+-- $GOPATH/src/github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx3/export_test.go --
+package tx3
+
+var Exported = true
+
+-- $GOPATH/src/github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx3/tx3.go --
+package tx3
+
+-- $GOPATH/src/github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx2/tx2_test.go --
+package tx2_test
+
+import . "vendor.org/tx2"
+import "testing"
+
+var Found = Exported
+
+func TestNop(t *testing.T) {}
+
+-- $GOPATH/src/github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx2/export_test.go --
+package tx2
+
+var Exported = true
+
+-- $GOPATH/src/github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx2/tx2.go --
+package tx2
+
+-- $GOPATH/src/github.com/rsc/go-get-issue-11864/vendor/vendor.org/p/p.go --
+package p
diff --git a/src/cmd/go/testdata/script/vendor_test_issue14613.txt b/src/cmd/go/testdata/script/vendor_test_issue14613.txt
new file mode 100644
index 0000000..d2f05c9
--- /dev/null
+++ b/src/cmd/go/testdata/script/vendor_test_issue14613.txt
@@ -0,0 +1,52 @@
+[short] skip
+env GO111MODULE=off
+
+# test folder should work
+go test github.com/clsung/go-vendor-issue-14613
+
+# test with specified _test.go should work too
+cd $GOPATH/src
+go test github.com/clsung/go-vendor-issue-14613/vendor_test.go
+
+# test with imported and not used
+! go test github.com/clsung/go-vendor-issue-14613/vendor/mylibtesttest/myapp/myapp_test.go
+stderr 'imported and not used'
+
+-- $GOPATH/src/github.com/clsung/go-vendor-issue-14613/./vendor_test.go --
+package main
+
+import (
+ "testing"
+
+ "github.com/clsung/fake"
+)
+
+func TestVendor(t *testing.T) {
+ ret := fake.DoNothing()
+ expected := "Ok"
+ if expected != ret {
+ t.Errorf("fake returned %q, expected %q", ret, expected)
+ }
+}
+
+-- $GOPATH/src/github.com/clsung/go-vendor-issue-14613/./vendor/mylibtesttest/myapp/myapp_test.go --
+package myapp
+import (
+ "mylibtesttest/rds"
+)
+
+-- $GOPATH/src/github.com/clsung/go-vendor-issue-14613/./vendor/mylibtesttest/rds/rds.go --
+package rds
+
+-- $GOPATH/src/github.com/clsung/go-vendor-issue-14613/./vendor/github.com/clsung/fake/fake.go --
+package fake
+
+func DoNothing() string {
+ return "Ok"
+}
+
+-- $GOPATH/src/github.com/clsung/go-vendor-issue-14613/./m.go --
+package main
+
+func main() {}
+
diff --git a/src/cmd/go/testdata/script/version.txt b/src/cmd/go/testdata/script/version.txt
new file mode 100644
index 0000000..0a2ac1e
--- /dev/null
+++ b/src/cmd/go/testdata/script/version.txt
@@ -0,0 +1,92 @@
+# Without arguments, we just print Go's own version.
+go version
+stdout '^go version'
+
+# Flags without files, or paths to missing files, should error.
+! go version missing.exe
+! go version -m
+stderr 'with arguments'
+! go version -v
+stderr 'with arguments'
+
+# Check that 'go version' succeed even when it does not contain Go build info.
+# It should print an error if the file has a known Go binary extension.
+#
+go version empty.txt
+! stdout .
+! stderr .
+go version empty.exe
+stderr 'could not read Go build info'
+go version empty.so
+stderr 'could not read Go build info'
+go version empty.dll
+stderr 'could not read Go build info'
+
+# Neither of the two flags above should be an issue via GOFLAGS.
+env GOFLAGS='-m -v'
+go version
+stdout '^go version'
+env GOFLAGS=
+
+env GO111MODULE=on
+
+# Check that very basic version lookup succeeds.
+go build empty.go
+go version empty$GOEXE
+[cgo] go build -ldflags=-linkmode=external empty.go
+[cgo] go version empty$GOEXE
+
+# Skip the remaining builds if we are running in short mode.
+[short] skip
+
+# Check that 'go version' and 'go version -m' work on a binary built in module mode.
+go get rsc.io/fortune
+go build -o fortune.exe rsc.io/fortune
+go version fortune.exe
+stdout '^fortune.exe: .+'
+go version -m fortune.exe
+stdout -buildmode=exe
+stdout '^\tpath\trsc.io/fortune'
+stdout '^\tmod\trsc.io/fortune\tv1.0.0'
+
+# Check the build info of a binary built from $GOROOT/src/cmd
+go build -o test2json.exe cmd/test2json
+go version -m test2json.exe
+stdout -buildmode=exe
+stdout '^test2json.exe: .+'
+stdout '^\tpath\tcmd/test2json$'
+! stdout 'mod[^e]'
+
+# Repeat the test with -buildmode=pie.
+[!buildmode:pie] stop
+go build -buildmode=pie -o external.exe rsc.io/fortune
+go version external.exe
+stdout '^external.exe: .+'
+go version -m external.exe
+stdout -buildmode=pie
+stdout '^\tpath\trsc.io/fortune'
+stdout '^\tmod\trsc.io/fortune\tv1.0.0'
+
+# Also test PIE with internal linking.
+# currently only supported on linux/amd64, linux/arm64 and windows/amd64.
+[!GOOS:linux] [!GOOS:windows] stop
+[!GOARCH:amd64] [!GOARCH:arm64] stop
+go build -buildmode=pie -ldflags=-linkmode=internal -o internal.exe rsc.io/fortune
+go version internal.exe
+stdout '^internal.exe: .+'
+go version -m internal.exe
+stdout -buildmode=pie
+stdout '^\tpath\trsc.io/fortune'
+stdout '^\tmod\trsc.io/fortune\tv1.0.0'
+
+-- go.mod --
+module m
+
+-- empty.go --
+package main
+func main(){}
+
+-- empty.txt --
+-- empty.exe --
+-- empty.so --
+-- empty.dll --
diff --git a/src/cmd/go/testdata/script/version_build_settings.txt b/src/cmd/go/testdata/script/version_build_settings.txt
new file mode 100644
index 0000000..cd3f5cf
--- /dev/null
+++ b/src/cmd/go/testdata/script/version_build_settings.txt
@@ -0,0 +1,89 @@
+[short] skip
+
+# Compiler name is always added.
+go build
+go version -m m$GOEXE
+stdout '^\tbuild\t-compiler=gc$'
+stdout '^\tbuild\tGOOS='
+stdout '^\tbuild\tGOARCH='
+[GOARCH:amd64] stdout '^\tbuild\tGOAMD64='
+! stdout asmflags|gcflags|ldflags|gccgoflags
+
+# Toolchain flags are added if present.
+# The raw flags are included, with package patterns if specified.
+go build -asmflags=example.com/m=-D=FOO=bar
+go version -m m$GOEXE
+stdout '^\tbuild\t-asmflags=example\.com/m=-D=FOO=bar$'
+
+go build -gcflags=example.com/m=-N
+go version -m m$GOEXE
+stdout '^\tbuild\t-gcflags=example\.com/m=-N$'
+
+go build -ldflags=example.com/m=-w
+go version -m m$GOEXE
+stdout '^\tbuild\t-ldflags=example\.com/m=-w$'
+
+go build -trimpath
+go version -m m$GOEXE
+stdout '\tbuild\t-trimpath=true$'
+
+# gccgoflags are not added when gc is used, and vice versa.
+# TODO: test gccgo.
+go build -gccgoflags=all=UNUSED
+go version -m m$GOEXE
+! stdout gccgoflags
+
+# Build and tool tags are added but not release tags.
+# "race" is included with build tags but not "cgo".
+go build -tags=a,b
+go version -m m$GOEXE
+stdout '^\tbuild\t-tags=a,b$'
+[race] go build -race
+[race] go version -m m$GOEXE
+[race] ! stdout '^\tbuild\t-tags='
+[race] stdout '^\tbuild\t-race=true$'
+
+# CGO flags are separate settings.
+# CGO_ENABLED is always present.
+# Other flags are added if CGO_ENABLED is true.
+env CGO_ENABLED=0
+go build
+go version -m m$GOEXE
+stdout '^\tbuild\tCGO_ENABLED=0$'
+! stdout CGO_CPPFLAGS|CGO_CFLAGS|CGO_CXXFLAGS|CGO_LDFLAGS
+
+[cgo] env CGO_ENABLED=1
+[cgo] env CGO_CPPFLAGS=-DFROM_CPPFLAGS=1
+[cgo] env CGO_CFLAGS=-DFROM_CFLAGS=1
+[cgo] env CGO_CXXFLAGS=-DFROM_CXXFLAGS=1
+[cgo] env CGO_LDFLAGS=-L/extra/dir/does/not/exist
+[cgo] go build '-ldflags=all=-linkmode=external -extldflags=-L/bonus/dir/does/not/exist'
+[cgo] go version -m m$GOEXE
+[cgo] stdout '^\tbuild\t-ldflags="all=-linkmode=external -extldflags=-L/bonus/dir/does/not/exist"$'
+[cgo] stdout '^\tbuild\tCGO_ENABLED=1$'
+[cgo] stdout '^\tbuild\tCGO_CPPFLAGS=-DFROM_CPPFLAGS=1$'
+[cgo] stdout '^\tbuild\tCGO_CFLAGS=-DFROM_CFLAGS=1$'
+[cgo] stdout '^\tbuild\tCGO_CXXFLAGS=-DFROM_CXXFLAGS=1$'
+[cgo] stdout '^\tbuild\tCGO_LDFLAGS=-L/extra/dir/does/not/exist$'
+
+# https://go.dev/issue/52372: a cgo-enabled binary should not be stamped with
+# CGO_ flags that contain paths.
+[cgo] env CGO_ENABLED=1
+[cgo] env CGO_CPPFLAGS=-DFROM_CPPFLAGS=1
+[cgo] env CGO_CFLAGS=-DFROM_CFLAGS=1
+[cgo] env CGO_CXXFLAGS=-DFROM_CXXFLAGS=1
+[cgo] env CGO_LDFLAGS=-L/extra/dir/does/not/exist
+[cgo] go build -trimpath '-ldflags=all=-linkmode=external -extldflags=-L/bonus/dir/does/not/exist'
+[cgo] go version -m m$GOEXE
+[cgo] ! stdout '/extra/dir/does/not/exist'
+[cgo] ! stdout '/bonus/dir/does/not/exist'
+[cgo] stdout '^\tbuild\tCGO_ENABLED=1$'
+
+-- go.mod --
+module example.com/m
+
+go 1.18
+-- m.go --
+package main
+
+func main() {}
diff --git a/src/cmd/go/testdata/script/version_buildvcs_bzr.txt b/src/cmd/go/testdata/script/version_buildvcs_bzr.txt
new file mode 100644
index 0000000..85db9ba
--- /dev/null
+++ b/src/cmd/go/testdata/script/version_buildvcs_bzr.txt
@@ -0,0 +1,107 @@
+# This test checks that VCS information is stamped into Go binaries by default,
+# controlled with -buildvcs. This test focuses on Bazaar specifics.
+# The Git test covers common functionality.
+
+[!exec:bzr] skip
+[short] skip
+env GOBIN=$WORK/gopath/bin
+env oldpath=$PATH
+env HOME=$WORK
+cd repo/a
+exec bzr whoami 'J.R. Gopher <gopher@golang.org>'
+
+# If there's no local repository, there's no VCS info.
+go install
+go version -m $GOBIN/a$GOEXE
+! stdout bzrrevision
+rm $GOBIN/a$GOEXE
+
+# If there is a repository, but it can't be used for some reason,
+# there should be an error. It should hint about -buildvcs=false.
+cd ..
+mkdir .bzr
+env PATH=$WORK${/}fakebin${:}$oldpath
+chmod 0755 $WORK/fakebin/bzr
+! exec bzr help
+cd a
+! go install
+stderr '^error obtaining VCS status: exit status 1\n\tUse -buildvcs=false to disable VCS stamping.$'
+rm $GOBIN/a$GOEXE
+cd ..
+env PATH=$oldpath
+rm .bzr
+
+# If there is an empty repository in a parent directory, only "modified" is tagged.
+exec bzr init
+cd a
+go install
+go version -m $GOBIN/a$GOEXE
+stdout '^\tbuild\tvcs=bzr$'
+! stdout vcs.revision
+! stdout vcs.time
+stdout '^\tbuild\tvcs.modified=true$'
+cd ..
+
+# Revision and commit time are tagged for repositories with commits.
+exec bzr add a README
+exec bzr commit -m 'initial commit'
+cd a
+go install
+go version -m $GOBIN/a$GOEXE
+stdout '^\tbuild\tvcs=bzr$'
+stdout '^\tbuild\tvcs.revision='
+stdout '^\tbuild\tvcs.time='
+stdout '^\tbuild\tvcs.modified=false$'
+rm $GOBIN/a$GOEXE
+
+# Building an earlier commit should still build clean.
+cp ../../outside/empty.txt ../NEWS
+exec bzr add ../NEWS
+exec bzr commit -m 'add NEWS'
+exec bzr update -r1
+go install
+go version -m $GOBIN/a$GOEXE
+stdout '^\tbuild\tvcs=bzr$'
+stdout '^\tbuild\tvcs.revision='
+stdout '^\tbuild\tvcs.time='
+stdout '^\tbuild\tvcs.modified=false$'
+
+# Building with -buildvcs=false suppresses the info.
+go install -buildvcs=false
+go version -m $GOBIN/a$GOEXE
+! stdout vcs.revision
+rm $GOBIN/a$GOEXE
+
+# An untracked file is shown as modified, even if it isn't part of the build.
+cp ../../outside/empty.txt .
+go install
+go version -m $GOBIN/a$GOEXE
+stdout '^\tbuild\tvcs.modified=true$'
+rm empty.txt
+rm $GOBIN/a$GOEXE
+
+# An edited file is shown as modified, even if it isn't part of the build.
+cp ../../outside/empty.txt ../README
+go install
+go version -m $GOBIN/a$GOEXE
+stdout '^\tbuild\tvcs.modified=true$'
+exec bzr revert ../README
+rm $GOBIN/a$GOEXE
+
+-- $WORK/fakebin/bzr --
+#!/bin/sh
+exit 1
+-- $WORK/fakebin/bzr.bat --
+exit 1
+-- repo/README --
+Far out in the uncharted backwaters of the unfashionable end of the western
+spiral arm of the Galaxy lies a small, unregarded yellow sun.
+-- repo/a/go.mod --
+module example.com/a
+
+go 1.18
+-- repo/a/a.go --
+package main
+
+func main() {}
+-- outside/empty.txt --
diff --git a/src/cmd/go/testdata/script/version_buildvcs_fossil.txt b/src/cmd/go/testdata/script/version_buildvcs_fossil.txt
new file mode 100644
index 0000000..bd6b89d
--- /dev/null
+++ b/src/cmd/go/testdata/script/version_buildvcs_fossil.txt
@@ -0,0 +1,94 @@
+# This test checks that VCS information is stamped into Go binaries by default,
+# controlled with -buildvcs. This test focuses on Fossil specifics.
+# The Git test covers common functionality.
+
+# "fossil" is the Fossil file server on Plan 9.
+[GOOS:plan9] skip
+[!exec:fossil] skip
+[short] skip
+env GOBIN=$WORK/gopath/bin
+env oldpath=$PATH
+env HOME=$WORK
+env USER=gopher
+[!GOOS:windows] env fslckout=.fslckout
+[GOOS:windows] env fslckout=_FOSSIL_
+exec pwd
+exec fossil init repo.fossil
+cd repo/a
+
+# If there's no local repository, there's no VCS info.
+go install
+go version -m $GOBIN/a$GOEXE
+! stdout vcs.revision
+rm $GOBIN/a$GOEXE
+
+# If there is a repository, but it can't be used for some reason,
+# there should be an error. It should hint about -buildvcs=false.
+cd ..
+mv fslckout $fslckout
+env PATH=$WORK${/}fakebin${:}$oldpath
+chmod 0755 $WORK/fakebin/fossil
+! exec fossil help
+cd a
+! go install
+stderr '^error obtaining VCS status: exit status 1\n\tUse -buildvcs=false to disable VCS stamping.$'
+rm $GOBIN/a$GOEXE
+cd ..
+env PATH=$oldpath
+rm $fslckout
+
+# Revision and commit time are tagged for repositories with commits.
+exec fossil open ../repo.fossil -f
+exec fossil add a README
+exec fossil commit -m 'initial commit'
+cd a
+go install
+go version -m $GOBIN/a$GOEXE
+stdout '^\tbuild\tvcs=fossil\n'
+stdout '^\tbuild\tvcs.revision='
+stdout '^\tbuild\tvcs.time='
+stdout '^\tbuild\tvcs.modified=false$'
+rm $GOBIN/a$GOEXE
+
+# Building with -buildvcs=false suppresses the info.
+go install -buildvcs=false
+go version -m $GOBIN/a$GOEXE
+! stdout vcs.revision
+rm $GOBIN/a$GOEXE
+
+# An untracked file is shown as modified, even if it isn't part of the build.
+cp ../../outside/empty.txt .
+go install
+go version -m $GOBIN/a$GOEXE
+stdout '^\tbuild\tvcs=fossil\n'
+stdout '^\tbuild\tvcs.modified=true$'
+rm empty.txt
+rm $GOBIN/a$GOEXE
+
+# An edited file is shown as modified, even if it isn't part of the build.
+cp ../../outside/empty.txt ../README
+go install
+go version -m $GOBIN/a$GOEXE
+stdout '^\tbuild\tvcs=fossil\n'
+stdout '^\tbuild\tvcs.modified=true$'
+exec fossil revert ../README
+rm $GOBIN/a$GOEXE
+
+-- $WORK/fakebin/fossil --
+#!/bin/sh
+exit 1
+-- $WORK/fakebin/fossil.bat --
+exit 1
+-- repo/README --
+Far out in the uncharted backwaters of the unfashionable end of the western
+spiral arm of the Galaxy lies a small, unregarded yellow sun.
+-- repo/fslckout --
+-- repo/a/go.mod --
+module example.com/a
+
+go 1.18
+-- repo/a/a.go --
+package main
+
+func main() {}
+-- outside/empty.txt --
diff --git a/src/cmd/go/testdata/script/version_buildvcs_git.txt b/src/cmd/go/testdata/script/version_buildvcs_git.txt
new file mode 100644
index 0000000..680e492
--- /dev/null
+++ b/src/cmd/go/testdata/script/version_buildvcs_git.txt
@@ -0,0 +1,182 @@
+# This test checks that VCS information is stamped into Go binaries by default,
+# controlled with -buildvcs. This test focuses on Git. Other tests focus on
+# other VCS tools but may not cover common functionality.
+
+[!git] skip
+[short] skip
+env GOBIN=$WORK/gopath/bin
+env oldpath=$PATH
+cd repo/a
+
+# If there's no local repository, there's no VCS info.
+go install
+go version -m $GOBIN/a$GOEXE
+! stdout vcs.revision
+rm $GOBIN/a$GOEXE
+
+# If there's an orphan .git file left by a git submodule, it's not a git
+# repository, and there's no VCS info.
+cd ../gitsubmodule
+go install
+go version -m $GOBIN/gitsubmodule$GOEXE
+! stdout vcs.revision
+rm $GOBIN/gitsubmodule$GOEXE
+
+# If there is a repository, but it can't be used for some reason,
+# there should be an error. It should hint about -buildvcs=false.
+# Also ensure that multiple errors are collected by "go list -e".
+cd ..
+mkdir .git
+env PATH=$WORK${/}fakebin${:}$oldpath
+chmod 0755 $WORK/fakebin/git
+! exec git help
+cd a
+! go install
+stderr '^error obtaining VCS status: exit status 1\n\tUse -buildvcs=false to disable VCS stamping.$'
+go list -e -f '{{.ImportPath}}: {{.Error}}' ./...
+stdout -count=1 '^example\.com/a: error obtaining VCS status'
+stdout -count=1 '^example\.com/a/library: <nil>'
+stdout -count=1 '^example\.com/a/othermain: error obtaining VCS status'
+cd ..
+env PATH=$oldpath
+rm .git
+
+# If there is an empty repository in a parent directory, only "uncommitted" is tagged.
+exec git init
+exec git config user.email gopher@golang.org
+exec git config user.name 'J.R. Gopher'
+cd a
+go install
+go version -m $GOBIN/a$GOEXE
+stdout '^\tbuild\tvcs=git$'
+stdout '^\tbuild\tvcs.modified=true$'
+! stdout vcs.revision
+! stdout vcs.time
+rm $GOBIN/a$GOEXE
+
+# Revision and commit time are tagged for repositories with commits.
+exec git add -A
+exec git commit -m 'initial commit'
+go install
+go version -m $GOBIN/a$GOEXE
+stdout '^\tbuild\tvcs.revision='
+stdout '^\tbuild\tvcs.time='
+stdout '^\tbuild\tvcs.modified=false$'
+rm $GOBIN/a$GOEXE
+
+# Building with -buildvcs=false suppresses the info.
+go install -buildvcs=false
+go version -m $GOBIN/a$GOEXE
+! stdout vcs.revision
+rm $GOBIN/a$GOEXE
+
+# An untracked file is shown as uncommitted, even if it isn't part of the build.
+cp ../../outside/empty.txt .
+go install
+go version -m $GOBIN/a$GOEXE
+stdout '^\tbuild\tvcs.modified=true$'
+rm empty.txt
+rm $GOBIN/a$GOEXE
+
+# An edited file is shown as uncommitted, even if it isn't part of the build.
+cp ../../outside/empty.txt ../README
+go install
+go version -m $GOBIN/a$GOEXE
+stdout '^\tbuild\tvcs.modified=true$'
+exec git checkout ../README
+rm $GOBIN/a$GOEXE
+
+# If the build doesn't include any packages from the repository,
+# there should be no VCS info.
+go install example.com/cmd/a@v1.0.0
+go version -m $GOBIN/a$GOEXE
+! stdout vcs.revision
+rm $GOBIN/a$GOEXE
+
+go mod edit -require=example.com/c@v0.0.0
+go mod edit -replace=example.com/c@v0.0.0=../../outside/c
+go install example.com/c
+go version -m $GOBIN/c$GOEXE
+! stdout vcs.revision
+rm $GOBIN/c$GOEXE
+exec git checkout go.mod
+
+# If the build depends on a package in the repository, but it's not in the
+# main module, there should be no VCS info.
+go mod edit -require=example.com/b@v0.0.0
+go mod edit -replace=example.com/b@v0.0.0=../b
+go mod edit -require=example.com/d@v0.0.0
+go mod edit -replace=example.com/d@v0.0.0=../../outside/d
+go install example.com/d
+go version -m $GOBIN/d$GOEXE
+! stdout vcs.revision
+exec git checkout go.mod
+rm $GOBIN/d$GOEXE
+
+# If we're loading multiple main packages,
+# but they share the same VCS repository,
+# we only need to execute VCS status commands once.
+go list -x ./...
+stdout -count=3 '^example.com'
+stderr -count=1 '^git status'
+stderr -count=1 '^git -c log.showsignature=false show'
+
+-- $WORK/fakebin/git --
+#!/bin/sh
+exit 1
+-- $WORK/fakebin/git.bat --
+exit 1
+-- repo/README --
+Far out in the uncharted backwaters of the unfashionable end of the western
+spiral arm of the Galaxy lies a small, unregarded yellow sun.
+-- repo/a/go.mod --
+module example.com/a
+
+go 1.18
+-- repo/a/a.go --
+package main
+
+func main() {}
+-- repo/a/library/f.go --
+package library
+-- repo/a/othermain/f.go --
+package main
+
+func main() {}
+-- repo/b/go.mod --
+module example.com/b
+
+go 1.18
+-- repo/b/b.go --
+package b
+-- repo/gitsubmodule/.git --
+gitdir: ../.git/modules/gitsubmodule
+-- repo/gitsubmodule/go.mod --
+module example.com/gitsubmodule
+
+go 1.18
+-- repo/gitsubmodule/main.go --
+package main
+
+func main() {}
+-- outside/empty.txt --
+-- outside/c/go.mod --
+module example.com/c
+
+go 1.18
+-- outside/c/main.go --
+package main
+
+func main() {}
+-- outside/d/go.mod --
+module example.com/d
+
+go 1.18
+
+require example.com/b v0.0.0
+-- outside/d/main.go --
+package main
+
+import _ "example.com/b"
+
+func main() {}
diff --git a/src/cmd/go/testdata/script/version_buildvcs_hg.txt b/src/cmd/go/testdata/script/version_buildvcs_hg.txt
new file mode 100644
index 0000000..fbbd886
--- /dev/null
+++ b/src/cmd/go/testdata/script/version_buildvcs_hg.txt
@@ -0,0 +1,91 @@
+# This test checks that VCS information is stamped into Go binaries by default,
+# controlled with -buildvcs. This test focuses on Mercurial specifics.
+# The Git test covers common functionality.
+
+[!exec:hg] skip
+[short] skip
+env GOBIN=$WORK/gopath/bin
+env oldpath=$PATH
+cd repo/a
+
+# If there's no local repository, there's no VCS info.
+go install
+go version -m $GOBIN/a$GOEXE
+! stdout hgrevision
+rm $GOBIN/a$GOEXE
+
+# If there is a repository, but it can't be used for some reason,
+# there should be an error. It should hint about -buildvcs=false.
+cd ..
+mkdir .hg
+env PATH=$WORK${/}fakebin${:}$oldpath
+chmod 0755 $WORK/fakebin/hg
+! exec hg help
+cd a
+! go install
+stderr '^error obtaining VCS status: exit status 1\n\tUse -buildvcs=false to disable VCS stamping.$'
+rm $GOBIN/a$GOEXE
+cd ..
+env PATH=$oldpath
+rm .hg
+
+# If there is an empty repository in a parent directory, only "uncommitted" is tagged.
+exec hg init
+cd a
+go install
+go version -m $GOBIN/a$GOEXE
+! stdout vcs.revision
+! stdout vcs.time
+stdout '^\tbuild\tvcs.modified=true$'
+cd ..
+
+# Revision and commit time are tagged for repositories with commits.
+exec hg add a README
+exec hg commit -m 'initial commit'
+cd a
+go install
+go version -m $GOBIN/a$GOEXE
+stdout '^\tbuild\tvcs.revision='
+stdout '^\tbuild\tvcs.time='
+stdout '^\tbuild\tvcs.modified=false$'
+rm $GOBIN/a$GOEXE
+
+# Building with -buildvcs=false suppresses the info.
+go install -buildvcs=false
+go version -m $GOBIN/a$GOEXE
+! stdout hgrevision
+rm $GOBIN/a$GOEXE
+
+# An untracked file is shown as uncommitted, even if it isn't part of the build.
+cp ../../outside/empty.txt .
+go install
+go version -m $GOBIN/a$GOEXE
+stdout '^\tbuild\tvcs.modified=true$'
+rm empty.txt
+rm $GOBIN/a$GOEXE
+
+# An edited file is shown as uncommitted, even if it isn't part of the build.
+cp ../../outside/empty.txt ../README
+go install
+go version -m $GOBIN/a$GOEXE
+stdout '^\tbuild\tvcs.modified=true$'
+exec hg revert ../README
+rm $GOBIN/a$GOEXE
+
+-- $WORK/fakebin/hg --
+#!/bin/sh
+exit 1
+-- $WORK/fakebin/hg.bat --
+exit 1
+-- repo/README --
+Far out in the uncharted backwaters of the unfashionable end of the western
+spiral arm of the Galaxy lies a small, unregarded yellow sun.
+-- repo/a/go.mod --
+module example.com/a
+
+go 1.18
+-- repo/a/a.go --
+package main
+
+func main() {}
+-- outside/empty.txt --
diff --git a/src/cmd/go/testdata/script/version_buildvcs_nested.txt b/src/cmd/go/testdata/script/version_buildvcs_nested.txt
new file mode 100644
index 0000000..6dab847
--- /dev/null
+++ b/src/cmd/go/testdata/script/version_buildvcs_nested.txt
@@ -0,0 +1,51 @@
+[!git] skip
+[!exec:hg] skip
+[short] skip
+env GOFLAGS='-n -buildvcs'
+
+# Create a root module in a root Git repository.
+mkdir root
+cd root
+go mod init example.com/root
+exec git init
+
+# Nesting repositories in parent directories are ignored, as the current
+# directory main package, and containing main module are in the same repository.
+# This is an error in GOPATH mode (to prevent VCS injection), but for modules,
+# we assume users have control over repositories they've checked out.
+mkdir hgsub
+cd hgsub
+exec hg init
+cp ../../main.go main.go
+! go build
+stderr '^error obtaining VCS status: main module is in repository ".*root" but current directory is in repository ".*hgsub"$'
+stderr '^\tUse -buildvcs=false to disable VCS stamping.$'
+go build -buildvcs=false
+go mod init example.com/root/hgsub
+go build
+cd ..
+
+# It's an error to build a package from a nested Git repository if the package
+# is in a separate repository from the current directory or from the module
+# root directory.
+mkdir gitsub
+cd gitsub
+exec git init
+exec git config user.name 'J.R.Gopher'
+exec git config user.email 'gopher@golang.org'
+cp ../../main.go main.go
+! go build
+stderr '^error obtaining VCS status: main module is in repository ".*root" but current directory is in repository ".*gitsub"$'
+go build -buildvcs=false
+go mod init example.com/root/gitsub
+exec git commit --allow-empty -m empty # status commands fail without this
+go build
+rm go.mod
+cd ..
+! go build ./gitsub
+stderr '^error obtaining VCS status: main package is in repository ".*gitsub" but current directory is in repository ".*root"$'
+go build -buildvcs=false -o=gitsub${/} ./gitsub
+
+-- main.go --
+package main
+func main() {}
diff --git a/src/cmd/go/testdata/script/version_cshared.txt b/src/cmd/go/testdata/script/version_cshared.txt
new file mode 100644
index 0000000..29e21fc
--- /dev/null
+++ b/src/cmd/go/testdata/script/version_cshared.txt
@@ -0,0 +1,19 @@
+[short] skip
+[!buildmode:c-shared] stop
+
+env GO111MODULE=on
+
+go get rsc.io/fortune
+go build -buildmode=c-shared -o external.so rsc.io/fortune
+go version external.so
+stdout '^external.so: .+'
+go version -m external.so
+stdout '^\tpath\trsc.io/fortune'
+stdout '^\tmod\trsc.io/fortune\tv1.0.0'
+
+-- go.mod --
+module m
+
+-- empty.go --
+package main
+func main(){}
diff --git a/src/cmd/go/testdata/script/version_gc_sections.txt b/src/cmd/go/testdata/script/version_gc_sections.txt
new file mode 100644
index 0000000..4bda23b
--- /dev/null
+++ b/src/cmd/go/testdata/script/version_gc_sections.txt
@@ -0,0 +1,24 @@
+# This test checks that external linking with --gc-sections does not strip version information.
+
+[short] skip
+[!cgo] skip
+[GOOS:aix] skip # no --gc-sections
+[GOOS:darwin] skip # no --gc-sections
+
+go build -ldflags='-linkmode=external -extldflags=-Wl,--gc-sections'
+go version hello$GOEXE
+! stdout 'not a Go executable'
+! stderr 'not a Go executable'
+
+-- go.mod --
+module hello
+-- hello.go --
+package main
+
+/*
+*/
+import "C"
+
+func main() {
+ println("hello")
+}
diff --git a/src/cmd/go/testdata/script/version_goexperiment.txt b/src/cmd/go/testdata/script/version_goexperiment.txt
new file mode 100644
index 0000000..4b165eb
--- /dev/null
+++ b/src/cmd/go/testdata/script/version_goexperiment.txt
@@ -0,0 +1,16 @@
+# Test that experiments appear in "go version <binary>"
+
+# This test requires rebuilding the runtime, which takes a while.
+[short] skip
+
+env GOEXPERIMENT=fieldtrack
+go build -o main$GOEXE version.go
+go version main$GOEXE
+stdout 'X:fieldtrack$'
+exec ./main$GOEXE
+stderr 'X:fieldtrack$'
+
+-- version.go --
+package main
+import "runtime"
+func main() { println(runtime.Version()) }
diff --git a/src/cmd/go/testdata/script/version_replace.txt b/src/cmd/go/testdata/script/version_replace.txt
new file mode 100644
index 0000000..82b8504
--- /dev/null
+++ b/src/cmd/go/testdata/script/version_replace.txt
@@ -0,0 +1,33 @@
+[short] skip
+
+go mod download example.com/printversion@v0.1.0 example.com/printversion@v1.0.0
+go get example.com/printversion@v0.1.0
+go install example.com/printversion
+
+go run example.com/printversion
+cmp stdout out.txt
+
+go version -m $GOPATH/bin/printversion$GOEXE
+stdout '^.*[/\\]bin[/\\]printversion'$GOEXE': .*$'
+stdout '^ path example.com/printversion$'
+stdout '^ mod example.com/printversion v0.1.0$'
+stdout '^ => example.com/printversion v1.0.0 h1:.*$'
+stdout '^ dep example.com/version v1.0.0$'
+stdout '^ => example.com/version v1.0.1 h1:.*$'
+
+-- go.mod --
+module golang.org/issue/37392
+go 1.14
+require (
+ example.com/printversion v0.1.0
+)
+replace (
+ example.com/printversion => example.com/printversion v1.0.0
+ example.com/version v1.0.0 => example.com/version v1.0.1
+)
+-- out.txt --
+path is example.com/printversion
+main is example.com/printversion v0.1.0
+ (replaced by example.com/printversion v1.0.0)
+using example.com/version v1.0.0
+ (replaced by example.com/version v1.0.1)
diff --git a/src/cmd/go/testdata/script/vet.txt b/src/cmd/go/testdata/script/vet.txt
new file mode 100644
index 0000000..6573ae3
--- /dev/null
+++ b/src/cmd/go/testdata/script/vet.txt
@@ -0,0 +1,62 @@
+# Package with external tests
+! go vet m/vetpkg
+stderr 'Printf'
+
+# With tags
+! go vet -tags tagtest m/vetpkg
+stderr 'c\.go.*Printf'
+
+# With flags on
+! go vet -printf m/vetpkg
+stderr 'Printf'
+
+# With flags off
+go vet -printf=false m/vetpkg
+! stderr .
+
+# With only test files (tests issue #23395)
+go vet m/onlytest
+! stderr .
+
+# With only cgo files (tests issue #24193)
+[!cgo] skip
+[short] skip
+go vet m/onlycgo
+! stderr .
+
+-- go.mod --
+module m
+
+go 1.16
+-- vetpkg/a_test.go --
+package p_test
+-- vetpkg/b.go --
+package p
+
+import "fmt"
+
+func f() {
+ fmt.Printf("%d")
+}
+-- vetpkg/c.go --
+// +build tagtest
+
+package p
+
+import "fmt"
+
+func g() {
+ fmt.Printf("%d", 3, 4)
+}
+-- onlytest/p_test.go --
+package p
+
+import "testing"
+
+func TestMe(*testing.T) {}
+-- onlycgo/p.go --
+package p
+
+import "C"
+
+func F() {}
diff --git a/src/cmd/go/testdata/script/vet_asm.txt b/src/cmd/go/testdata/script/vet_asm.txt
new file mode 100644
index 0000000..ae2db97
--- /dev/null
+++ b/src/cmd/go/testdata/script/vet_asm.txt
@@ -0,0 +1,32 @@
+env GO111MODULE=off
+
+# Issue 27665. Verify that "go vet" analyzes non-Go files.
+
+[!GOARCH:amd64] skip
+! go vet -asmdecl a
+stderr 'f: invalid MOVW of x'
+
+# -c flag shows context
+! go vet -c=2 -asmdecl a
+stderr '...invalid MOVW...'
+stderr '1 .*TEXT'
+stderr '2 MOVW'
+stderr '3 RET'
+stderr '4'
+
+# -json causes success, even with diagnostics and errors.
+go vet -json -asmdecl a
+stderr '"a": {'
+stderr '"asmdecl":'
+stderr '"posn": ".*asm.s:2:1",'
+stderr '"message": ".*invalid MOVW.*"'
+
+-- a/a.go --
+package a
+
+func f(x int8)
+
+-- a/asm.s --
+TEXT ·f(SB),0,$0-1
+ MOVW x+0(FP), AX
+ RET
diff --git a/src/cmd/go/testdata/script/vet_deps.txt b/src/cmd/go/testdata/script/vet_deps.txt
new file mode 100644
index 0000000..b2a8f16
--- /dev/null
+++ b/src/cmd/go/testdata/script/vet_deps.txt
@@ -0,0 +1,34 @@
+env GO111MODULE=off
+
+# Issue 30296. Verify that "go vet" uses only immediate dependencies.
+
+# First run fills the cache.
+go vet a
+
+go vet -x a
+! stderr 'transitive'
+
+-- a/a.go --
+package a
+
+import "b"
+
+func F() {
+ b.F()
+}
+
+-- b/b.go --
+package b
+
+import "transitive"
+
+func F() {
+ transitive.F()
+}
+
+-- transitive/c.go --
+package transitive
+
+func F() {
+}
+
diff --git a/src/cmd/go/testdata/script/vet_flags.txt b/src/cmd/go/testdata/script/vet_flags.txt
new file mode 100644
index 0000000..73f4e41
--- /dev/null
+++ b/src/cmd/go/testdata/script/vet_flags.txt
@@ -0,0 +1,91 @@
+env GO111MODULE=on
+
+# Issue 35837: "go vet -<analyzer> <std package>" should use the requested
+# analyzers, not the default analyzers for 'go test'.
+go vet -n -buildtags=false runtime
+stderr '-buildtags=false'
+! stderr '-unsafeptr=false'
+
+# Issue 37030: "go vet <std package>" without other flags should disable the
+# unsafeptr check by default.
+go vet -n runtime
+stderr '-unsafeptr=false'
+! stderr '-unreachable=false'
+
+# However, it should be enabled if requested explicitly.
+go vet -n -unsafeptr runtime
+stderr '-unsafeptr'
+! stderr '-unsafeptr=false'
+
+# -unreachable is disabled during test but on during plain vet.
+go test -n runtime
+stderr '-unreachable=false'
+
+# A flag terminator should be allowed before the package list.
+go vet -n -- .
+
+[short] stop
+
+# Analyzer flags should be included from GOFLAGS, and should override
+# the defaults.
+go vet .
+env GOFLAGS='-tags=buggy'
+! go vet .
+stderr 'possible Printf formatting directive'
+
+# Enabling one analyzer in GOFLAGS should disable the rest implicitly...
+env GOFLAGS='-tags=buggy -unsafeptr'
+go vet .
+
+# ...but enabling one on the command line should not disable the analyzers
+# enabled via GOFLAGS.
+env GOFLAGS='-tags=buggy -printf'
+! go vet -unsafeptr
+stderr 'possible Printf formatting directive'
+
+# Analyzer flags don't exist unless we're running 'go vet',
+# and we shouldn't run the vet tool to discover them otherwise.
+# (Maybe someday we'll hard-code the analyzer flags for the default vet
+# tool to make this work, but not right now.)
+env GOFLAGS='-unsafeptr'
+! go list .
+stderr 'go: parsing \$GOFLAGS: unknown flag -unsafeptr'
+env GOFLAGS=
+
+# "go test" on a user package should by default enable an explicit list of analyzers.
+go test -n -run=none .
+stderr '[/\\]vet'$GOEXE'["]? .* -errorsas .* ["]?\$WORK[/\\][^ ]*[/\\]vet\.cfg'
+
+# An explicitly-empty -vet argument should imply the default analyzers.
+go test -n -vet= -run=none .
+stderr '[/\\]vet'$GOEXE'["]? .* -errorsas .* ["]?\$WORK[/\\][^ ]*[/\\]vet\.cfg'
+
+# "go test" on a standard package should by default disable an explicit list.
+go test -n -run=none encoding/binary
+stderr '[/\\]vet'$GOEXE'["]? -unsafeptr=false -unreachable=false ["]?\$WORK[/\\][^ ]*[/\\]vet\.cfg'
+
+go test -n -vet= -run=none encoding/binary
+stderr '[/\\]vet'$GOEXE'["]? -unsafeptr=false -unreachable=false ["]?\$WORK[/\\][^ ]*[/\\]vet\.cfg'
+
+# Both should allow users to override via the -vet flag.
+go test -n -vet=unreachable -run=none .
+stderr '[/\\]vet'$GOEXE'["]? -unreachable ["]?\$WORK[/\\][^ ]*[/\\]vet\.cfg'
+go test -n -vet=unreachable -run=none encoding/binary
+stderr '[/\\]vet'$GOEXE'["]? -unreachable ["]?\$WORK[/\\][^ ]*[/\\]vet\.cfg'
+
+-- go.mod --
+module example.com/x
+-- x.go --
+package x
+-- x_test.go --
+package x
+-- x_tagged.go --
+// +build buggy
+
+package x
+
+import "fmt"
+
+func init() {
+ fmt.Sprint("%s") // oops!
+}
diff --git a/src/cmd/go/testdata/script/vet_internal.txt b/src/cmd/go/testdata/script/vet_internal.txt
new file mode 100644
index 0000000..85f7093
--- /dev/null
+++ b/src/cmd/go/testdata/script/vet_internal.txt
@@ -0,0 +1,71 @@
+env GO111MODULE=off
+
+# Issue 36173. Verify that "go vet" prints line numbers on load errors.
+
+! go vet a/a.go
+stderr '^package command-line-arguments\n\ta[/\\]a.go:5:3: use of internal package'
+
+! go vet a/a_test.go
+stderr '^package command-line-arguments \(test\)\n\ta[/\\]a_test.go:4:3: use of internal package'
+
+! go vet a
+stderr '^package a\n\ta[/\\]a.go:5:3: use of internal package'
+
+go vet b/b.go
+! stderr 'use of internal package'
+
+! go vet b/b_test.go
+stderr '^package command-line-arguments \(test\)\n\tb[/\\]b_test.go:4:3: use of internal package'
+
+! go vet depends-on-a/depends-on-a.go
+stderr '^package command-line-arguments\n\timports a\n\ta[/\\]a.go:5:3: use of internal package'
+
+! go vet depends-on-a/depends-on-a_test.go
+stderr '^package command-line-arguments \(test\)\n\timports a\n\ta[/\\]a.go:5:3: use of internal package a/x/internal/y not allowed'
+
+! go vet depends-on-a
+stderr '^package depends-on-a\n\timports a\n\ta[/\\]a.go:5:3: use of internal package'
+
+-- a/a.go --
+// A package with bad imports in both src and test
+package a
+
+import (
+ _ "a/x/internal/y"
+)
+
+-- a/a_test.go --
+package a
+
+import (
+ _ "a/x/internal/y"
+)
+
+-- b/b.go --
+// A package with a bad import in test only
+package b
+
+-- b/b_test.go --
+package b
+
+import (
+ _ "a/x/internal/y"
+)
+
+-- depends-on-a/depends-on-a.go --
+// A package that depends on a package with a bad import
+package depends
+
+import (
+ _ "a"
+)
+
+-- depends-on-a/depends-on-a_test.go --
+package depends
+
+import (
+ _ "a"
+)
+
+-- a/x/internal/y/y.go --
+package y
diff --git a/src/cmd/go/testdata/script/work.txt b/src/cmd/go/testdata/script/work.txt
new file mode 100644
index 0000000..69391ef
--- /dev/null
+++ b/src/cmd/go/testdata/script/work.txt
@@ -0,0 +1,154 @@
+! go work init doesnotexist
+stderr 'go: directory doesnotexist does not exist'
+go env GOWORK
+! stdout .
+
+go work init ./a ./b
+cmpenv go.work go.work.want
+go env GOWORK
+stdout '^'$WORK'(\\|/)gopath(\\|/)src(\\|/)go.work$'
+
+! go run example.com/b
+stderr 'a(\\|/)a.go:4:8: no required module provides package rsc.io/quote; to add it:\n\tcd '$WORK(\\|/)gopath(\\|/)src(\\|/)a'\n\tgo get rsc.io/quote'
+cd a
+go get rsc.io/quote
+cat go.mod
+go env GOMOD # go env GOMOD reports the module in a single module context
+stdout $GOPATH(\\|/)src(\\|/)a(\\|/)go.mod
+cd ..
+go run example.com/b
+stdout 'Hello, world.'
+
+# And try from a different directory
+cd c
+go run example.com/b
+stdout 'Hello, world.'
+cd $GOPATH/src
+
+go list all # all includes both modules
+stdout 'example.com/a'
+stdout 'example.com/b'
+
+# -mod can only be set to readonly in workspace mode
+go list -mod=readonly all
+! go list -mod=mod all
+stderr '^go: -mod may only be set to readonly or vendor when in workspace mode'
+env GOWORK=off
+go list -mod=mod all
+env GOWORK=
+
+# Test that duplicates in the use list return an error
+cp go.work go.work.backup
+cp go.work.dup go.work
+! go run example.com/b
+stderr 'reading go.work: path .* appears multiple times in workspace'
+cp go.work.backup go.work
+
+cp go.work.d go.work
+go work use # update go version
+go run example.com/d
+
+# Test that we don't run into "newRequirements called with unsorted roots"
+# panic with unsorted main modules.
+cp go.work.backwards go.work
+go work use # update go version
+go run example.com/d
+
+# Test that command-line-arguments work inside and outside modules.
+# This exercises the code that determines which module command-line-arguments
+# belongs to.
+go list ./b/main.go
+env GOWORK=off
+go build -n -o foo foo.go
+env GOWORK=
+go build -n -o foo foo.go
+
+-- go.work.dup --
+go 1.18
+
+use (
+ a
+ b
+ ../src/a
+)
+-- go.work.want --
+go $goversion
+
+use (
+ ./a
+ ./b
+)
+-- go.work.d --
+go 1.18
+
+use (
+ a
+ b
+ d
+)
+-- a/go.mod --
+
+module example.com/a
+
+-- a/a.go --
+package a
+
+import "fmt"
+import "rsc.io/quote"
+
+func HelloFromA() {
+ fmt.Println(quote.Hello())
+}
+
+-- b/go.mod --
+
+module example.com/b
+
+-- b/main.go --
+package main
+
+import "example.com/a"
+
+func main() {
+ a.HelloFromA()
+}
+-- b/lib/hello.go --
+package lib
+
+import "example.com/a"
+
+func Hello() {
+ a.HelloFromA()
+}
+
+-- c/README --
+Create this directory so we can cd to
+it and make sure paths are interpreted
+relative to the go.work, not the cwd.
+-- d/go.mod --
+module example.com/d
+
+-- d/main.go --
+package main
+
+import "example.com/b/lib"
+
+func main() {
+ lib.Hello()
+}
+
+-- go.work.backwards --
+go 1.18
+
+use (
+ d
+ b
+ a
+)
+
+-- foo.go --
+package main
+import "fmt"
+func main() {
+ fmt.Println("Hello, World")
+}
diff --git a/src/cmd/go/testdata/script/work_build_no_modules.txt b/src/cmd/go/testdata/script/work_build_no_modules.txt
new file mode 100644
index 0000000..c9859b4
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_build_no_modules.txt
@@ -0,0 +1,13 @@
+! go build .
+stderr 'go: no modules were found in the current workspace; see ''go help work'''
+
+-- go.work --
+go 1.18
+-- go.mod --
+go 1.18
+
+module foo
+-- foo.go --
+package main
+
+func main() {} \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/work_disablevendor.txt b/src/cmd/go/testdata/script/work_disablevendor.txt
new file mode 100644
index 0000000..c4c580b
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_disablevendor.txt
@@ -0,0 +1,56 @@
+# Test that mod=vendor is disabled in workspace mode, even
+# with a single workspace module.
+
+cd workspace
+
+# Base case: ensure the module would default to mod=vendor
+# outside of workspace mode.
+env GOWORK=off
+go list -f '{{.Dir}}' example.com/dep
+stdout $GOPATH[\\/]src[\\/]workspace[\\/]vendor[\\/]example.com[\\/]dep
+
+# Test case: endure the module does not enter mod=vendor outside
+# worspace mode.
+env GOWORK=''
+go list -f '{{.Dir}}' example.com/dep
+stdout $GOPATH[\\/]src[\\/]dep
+
+-- workspace/go.work --
+use .
+replace example.com/dep => ../dep
+-- workspace/main.go --
+package main
+
+import "example.com/dep"
+
+func main() {
+ dep.Dep()
+}
+-- workspace/go.mod --
+module example.com/mod
+
+go 1.20
+
+require example.com/dep v1.0.0
+-- workspace/vendor/example.com/dep/dep.go --
+package dep
+
+import "fmt"
+
+func Dep() {
+ fmt.Println("the vendored dep")
+}
+-- workspace/vendor/modules.txt --
+# example.com/dep v1.0.0
+## explicit
+example.com/dep
+-- dep/go.mod --
+module example.com/dep
+-- dep/dep.go --
+package dep
+
+import "fmt"
+
+func Dep () {
+ fmt.Println("the real dep")
+}
diff --git a/src/cmd/go/testdata/script/work_edit.txt b/src/cmd/go/testdata/script/work_edit.txt
new file mode 100644
index 0000000..c67696d
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_edit.txt
@@ -0,0 +1,166 @@
+# Test editing go.work files.
+
+go work init m
+cmpenv go.work go.work.want_initial
+
+go work edit -use n
+cmpenv go.work go.work.want_use_n
+
+grep go go.work
+go work edit -go none
+! grep go go.work
+
+go work edit -go 1.18
+cmp go.work go.work.want_go_118
+
+go work edit -dropuse m
+cmp go.work go.work.want_dropuse_m
+
+go work edit -replace=x.1@v1.3.0=y.1@v1.4.0 -replace='x.1@v1.4.0 = ../z'
+cmp go.work go.work.want_add_replaces
+
+go work edit -use n -use ../a -use /b -use c -use c
+cmp go.work go.work.want_multiuse
+
+go work edit -dropuse /b -dropuse n
+cmp go.work go.work.want_multidropuse
+
+go work edit -dropreplace='x.1@v1.4.0'
+cmp go.work go.work.want_dropreplace
+
+go work edit -print -go 1.19 -use b -dropuse c -replace 'x.1@v1.4.0 = ../z' -dropreplace x.1 -dropreplace x.1@v1.3.0
+cmp stdout go.work.want_print
+
+go work edit -json -go 1.19 -use b -dropuse c -replace 'x.1@v1.4.0 = ../z' -dropreplace x.1 -dropreplace x.1@v1.3.0
+cmp stdout go.work.want_json
+
+env GOWORK=$GOPATH/src/unformatted
+go work edit -print -fmt
+cmp stdout formatted
+
+-- m/go.mod --
+module m
+
+go 1.18
+-- go.work.want_initial --
+go $goversion
+
+use ./m
+-- go.work.want_use_n --
+go $goversion
+
+use (
+ ./m
+ ./n
+)
+-- go.work.want_go_118 --
+go 1.18
+
+use (
+ ./m
+ ./n
+)
+-- go.work.want_dropuse_m --
+go 1.18
+
+use ./n
+-- go.work.want_add_replaces --
+go 1.18
+
+use ./n
+
+replace (
+ x.1 v1.3.0 => y.1 v1.4.0
+ x.1 v1.4.0 => ../z
+)
+-- go.work.want_multiuse --
+go 1.18
+
+use (
+ ../a
+ ./c
+ ./n
+ /b
+)
+
+replace (
+ x.1 v1.3.0 => y.1 v1.4.0
+ x.1 v1.4.0 => ../z
+)
+-- go.work.want_multidropuse --
+go 1.18
+
+use (
+ ../a
+ ./c
+)
+
+replace (
+ x.1 v1.3.0 => y.1 v1.4.0
+ x.1 v1.4.0 => ../z
+)
+-- go.work.want_dropreplace --
+go 1.18
+
+use (
+ ../a
+ ./c
+)
+
+replace x.1 v1.3.0 => y.1 v1.4.0
+-- go.work.want_print --
+go 1.19
+
+use (
+ ../a
+ ./b
+)
+
+replace x.1 v1.4.0 => ../z
+-- go.work.want_json --
+{
+ "Go": "1.19",
+ "Use": [
+ {
+ "DiskPath": "../a"
+ },
+ {
+ "DiskPath": "./b"
+ }
+ ],
+ "Replace": [
+ {
+ "Old": {
+ "Path": "x.1",
+ "Version": "v1.4.0"
+ },
+ "New": {
+ "Path": "../z"
+ }
+ }
+ ]
+}
+-- unformatted --
+go 1.18
+ use (
+ a
+ b
+ c
+ )
+ replace (
+ x.1 v1.3.0 => y.1 v1.4.0
+ x.1 v1.4.0 => ../z
+ )
+-- formatted --
+go 1.18
+
+use (
+ a
+ b
+ c
+)
+
+replace (
+ x.1 v1.3.0 => y.1 v1.4.0
+ x.1 v1.4.0 => ../z
+)
diff --git a/src/cmd/go/testdata/script/work_edit_toolchain.txt b/src/cmd/go/testdata/script/work_edit_toolchain.txt
new file mode 100644
index 0000000..b4e260d
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_edit_toolchain.txt
@@ -0,0 +1,20 @@
+# Test support for go work edit -toolchain to set toolchain to use
+
+env GOTOOLCHAIN=local
+env GO111MODULE=on
+
+! grep toolchain go.work
+go work edit -toolchain=go1.9
+grep 'toolchain go1.9' go.work
+
+go work edit -toolchain=default
+grep 'toolchain default' go.work
+
+go work edit -toolchain=none
+! grep toolchain go.work
+
+-- go.work --
+go 1.8
+use .
+-- go.mod --
+module m
diff --git a/src/cmd/go/testdata/script/work_empty_panic_GOPATH.txt b/src/cmd/go/testdata/script/work_empty_panic_GOPATH.txt
new file mode 100644
index 0000000..43ebf11
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_empty_panic_GOPATH.txt
@@ -0,0 +1,13 @@
+# Regression test for https://go.dev/issue/58767:
+# with an empty go.work file in GOPATH mode, calls to load.defaultGODEBUG for a
+# package named "main" panicked in modload.MainModules.GoVersion.
+
+env GO111MODULE=off
+cd example
+go list example/m
+
+-- example/go.work --
+go 1.21
+-- example/m/main.go --
+package main
+func main() {}
diff --git a/src/cmd/go/testdata/script/work_env.txt b/src/cmd/go/testdata/script/work_env.txt
new file mode 100644
index 0000000..8b1779e
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_env.txt
@@ -0,0 +1,28 @@
+go env GOWORK
+stdout '^'$GOPATH'[\\/]src[\\/]go.work$'
+go env
+stdout '^(set )?GOWORK=''?'$GOPATH'[\\/]src[\\/]go.work''?$'
+
+cd ..
+go env GOWORK
+! stdout .
+go env
+stdout 'GOWORK=("")?'
+
+cd src
+go env GOWORK
+stdout 'go.work'
+
+env GOWORK='off'
+go env GOWORK
+stdout 'off'
+
+! go env -w GOWORK=off
+stderr '^go: GOWORK cannot be modified$'
+
+-- go.work --
+go 1.18
+
+use a
+-- a/go.mod --
+module example.com/a
diff --git a/src/cmd/go/testdata/script/work_get_toolchain.txt b/src/cmd/go/testdata/script/work_get_toolchain.txt
new file mode 100644
index 0000000..5a851bb
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_get_toolchain.txt
@@ -0,0 +1,24 @@
+# go get should update the go and toolchain lines in go.work
+env TESTGO_VERSION=go1.21
+env TESTGO_VERSION_SWITCH=switch
+env GOTOOLCHAIN=auto
+cp go.mod.new go.mod
+cp go.work.new go.work
+go get rsc.io/needgo121 rsc.io/needgo122 rsc.io/needgo123 rsc.io/needall
+stderr '^go: rsc.io/needall@v0.0.1 requires go >= 1.23; switching to go1.23.9$'
+stderr '^go: added rsc.io/needall v0.0.1'
+grep 'go 1.23$' go.mod
+grep 'go 1.23$' go.work
+grep 'toolchain go1.23.9' go.mod
+grep 'toolchain go1.23.9' go.work
+
+-- go.mod.new --
+module m
+go 1.1
+
+-- p.go --
+package p
+
+-- go.work.new --
+go 1.18
+use .
diff --git a/src/cmd/go/testdata/script/work_goline_order.txt b/src/cmd/go/testdata/script/work_goline_order.txt
new file mode 100644
index 0000000..fe1cddb
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_goline_order.txt
@@ -0,0 +1,34 @@
+# Check that go line in go.work is always >= go line of used modules.
+
+# Using an old Go version, fails during module loading, but we rewrite the error to the
+# same one a switching version would use, without the auto-switch.
+# This is a misconfigured system that should not arise in practice.
+env TESTGO_VERSION=go1.21.1
+env TESTGO_VERSION_SWITCH=switch
+cp go.work go.work.orig
+! go list
+stderr '^go: module . listed in go.work file requires go >= 1.21.2, but go.work lists go 1.21.1; to update it:\n\tgo work use$'
+go work use
+go list
+
+# Using a new enough Go version, fails later and can suggest 'go work use'.
+env TESTGO_VERSION=go1.21.2
+env TESTGO_VERSION_SWITCH=switch
+cp go.work.orig go.work
+! go list
+stderr '^go: module . listed in go.work file requires go >= 1.21.2, but go.work lists go 1.21.1; to update it:\n\tgo work use$'
+
+# go work use fixes the problem.
+go work use
+go list
+
+-- go.work --
+go 1.21.1
+use .
+
+-- go.mod --
+module m
+go 1.21.2
+
+-- p.go --
+package p
diff --git a/src/cmd/go/testdata/script/work_goproxy_off.txt b/src/cmd/go/testdata/script/work_goproxy_off.txt
new file mode 100644
index 0000000..0a602e3
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_goproxy_off.txt
@@ -0,0 +1,59 @@
+go work init
+go work use . ./sub
+
+# Verify that the go.mod files for both modules in the workspace are tidy,
+# and add missing go.sum entries as needed.
+
+cp go.mod go.mod.orig
+go mod tidy
+cmp go.mod go.mod.orig
+
+cd sub
+cp go.mod go.mod.orig
+go mod tidy
+cmp go.mod go.mod.orig
+cd ..
+
+go list -m all
+stdout '^rsc\.io/quote v1\.5\.1$'
+stdout '^rsc\.io/sampler v1\.3\.1$'
+
+# Now remove the module dependencies from the module cache.
+# Because one module upgrades a transitive dependency needed by another,
+# listing the modules in the workspace should error out.
+
+go clean -modcache
+env GOPROXY=off
+! go list -m all
+stderr '^go: rsc.io/sampler@v1.3.0: module lookup disabled by GOPROXY=off$'
+
+-- example.go --
+package example
+
+import _ "rsc.io/sampler"
+-- go.mod --
+module example
+
+go 1.19
+
+require rsc.io/sampler v1.3.0
+
+require (
+ golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c // indirect
+ rsc.io/testonly v1.0.0 // indirect
+)
+-- sub/go.mod --
+module example/sub
+
+go 1.19
+
+require rsc.io/quote v1.5.1
+
+require (
+ golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c // indirect
+ rsc.io/sampler v1.3.1 // indirect
+)
+-- sub/sub.go --
+package example
+
+import _ "rsc.io/quote"
diff --git a/src/cmd/go/testdata/script/work_gowork.txt b/src/cmd/go/testdata/script/work_gowork.txt
new file mode 100644
index 0000000..1cfbf0c
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_gowork.txt
@@ -0,0 +1,24 @@
+env GOWORK=stop.work
+! go list a # require absolute path
+! stderr panic
+env GOWORK=doesnotexist
+! go list a
+! stderr panic
+
+env GOWORK=$GOPATH/src/stop.work
+go list -n a
+go build -n a
+go test -n a
+
+-- stop.work --
+go 1.18
+
+use ./a
+-- a/a.go --
+package a
+-- a/a_test.go --
+package a
+-- a/go.mod --
+module a
+
+go 1.18 \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/work_init_gowork.txt b/src/cmd/go/testdata/script/work_init_gowork.txt
new file mode 100644
index 0000000..55ac99b
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_init_gowork.txt
@@ -0,0 +1,19 @@
+# Test that the GOWORK environment variable flag is used by go work init.
+
+! exists go.work
+go work init
+exists go.work
+
+env GOWORK=$GOPATH/src/foo/foo.work
+! exists foo/foo.work
+go work init
+exists foo/foo.work
+
+env GOWORK=
+cd foo/bar
+! go work init
+stderr 'already exists'
+
+# Create directories to make go.work files in.
+-- foo/dummy.txt --
+-- foo/bar/dummy.txt --
diff --git a/src/cmd/go/testdata/script/work_init_path.txt b/src/cmd/go/testdata/script/work_init_path.txt
new file mode 100644
index 0000000..0a2d372
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_init_path.txt
@@ -0,0 +1,33 @@
+# Regression test for https://go.dev/issue/51448.
+# 'go work init . .. foo/bar' should produce a go.work file
+# with the same paths as 'go work init; go work use -r ..',
+# and it should have 'use .' rather than 'use ./.' inside.
+
+cd dir
+
+go work init . .. foo/bar
+mv go.work go.work.init
+
+go work init
+go work use -r ..
+cmp go.work go.work.init
+
+cmpenv go.work $WORK/go.work.want
+
+-- go.mod --
+module example
+go 1.18
+-- dir/go.mod --
+module example
+go 1.18
+-- dir/foo/bar/go.mod --
+module example
+go 1.18
+-- $WORK/go.work.want --
+go $goversion
+
+use (
+ .
+ ..
+ ./foo/bar
+)
diff --git a/src/cmd/go/testdata/script/work_init_toolchain.txt b/src/cmd/go/testdata/script/work_init_toolchain.txt
new file mode 100644
index 0000000..900ea2c
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_init_toolchain.txt
@@ -0,0 +1,35 @@
+
+# Create basic modules and work space.
+# Note that toolchain lines in modules should be completely ignored.
+env TESTGO_VERSION=go1.50
+mkdir m1_22_0
+go mod init -C m1_22_0
+go mod edit -C m1_22_0 -go=1.22.0 -toolchain=go1.99.0
+
+# work init writes the current Go version to the go line
+go work init
+grep '^go 1.50$' go.work
+! grep toolchain go.work
+
+# work init with older modules should leave go 1.50 in the go.work.
+rm go.work
+go work init ./m1_22_0
+grep '^go 1.50$' go.work
+! grep toolchain go.work
+
+# work init with newer modules should bump go,
+# including updating to a newer toolchain as needed.
+# Because work init writes the current toolchain as the go version,
+# it writes the bumped go version, not the max of the used modules.
+env TESTGO_VERSION=go1.21
+env TESTGO_VERSION_SWITCH=switch
+rm go.work
+env GOTOOLCHAIN=local
+! go work init ./m1_22_0
+stderr '^go: m1_22_0'${/}'go.mod requires go >= 1.22.0 \(running go 1.21; GOTOOLCHAIN=local\)$'
+env GOTOOLCHAIN=auto
+go work init ./m1_22_0
+stderr '^go: m1_22_0'${/}'go.mod requires go >= 1.22.0; switching to go1.22.9$'
+cat go.work
+grep '^go 1.22.9$' go.work
+! grep toolchain go.work
diff --git a/src/cmd/go/testdata/script/work_install_submodule.txt b/src/cmd/go/testdata/script/work_install_submodule.txt
new file mode 100644
index 0000000..3d11717
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_install_submodule.txt
@@ -0,0 +1,36 @@
+# This is a regression test for golang.org/issue/50036
+# Don't check sums for other modules in the workspace.
+
+cd m/sub
+go install -n
+
+-- go.work --
+go 1.18
+
+use (
+ ./m
+ ./m/sub
+)
+-- m/go.mod --
+module example.com/m
+
+go 1.18
+
+-- m/m.go --
+package m
+
+func M() {}
+-- m/sub/go.mod --
+module example.com/m/sub
+
+go 1.18
+
+require example.com/m v1.0.0
+-- m/sub/main.go --
+package main
+
+import "example.com/m"
+
+func main() {
+ m.M()
+}
diff --git a/src/cmd/go/testdata/script/work_issue51204.txt b/src/cmd/go/testdata/script/work_issue51204.txt
new file mode 100644
index 0000000..d483002
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_issue51204.txt
@@ -0,0 +1,57 @@
+go work sync
+
+go list -f '{{.Dir}}' example.com/test
+stdout '^'$PWD${/}test'$'
+
+-- go.work --
+go 1.18
+
+use (
+ ./test2
+ ./test2/sub
+)
+-- test/go.mod --
+module example.com/test
+
+go 1.18
+-- test/file.go --
+package test
+
+func DoSomething() {
+}
+-- test2/go.mod --
+module example.com/test2
+
+go 1.18
+
+replace example.com/test => ../test
+
+require example.com/test v0.0.0-00010101000000-000000000000
+-- test2/file.go --
+package test2
+
+import (
+ "example.com/test"
+)
+
+func DoSomething() {
+ test.DoSomething()
+}
+-- test2/sub/go.mod --
+module example.com/test2/sub
+
+go 1.18
+
+replace example.com/test => ../../test
+
+require example.com/test v0.0.0
+-- test2/sub/file.go --
+package test2
+
+import (
+ "example.com/test"
+)
+
+func DoSomething() {
+ test.DoSomething()
+}
diff --git a/src/cmd/go/testdata/script/work_issue54048.txt b/src/cmd/go/testdata/script/work_issue54048.txt
new file mode 100644
index 0000000..ced3d90
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_issue54048.txt
@@ -0,0 +1,19 @@
+! go list -m -json all
+stderr 'go: module example.com/foo appears multiple times in workspace'
+
+-- go.work --
+go 1.18
+
+use (
+ ./a
+ ./b
+)
+-- a/go.mod --
+module example.com/foo
+
+go 1.18
+
+-- b/go.mod --
+module example.com/foo
+
+go 1.18
diff --git a/src/cmd/go/testdata/script/work_issue54372.txt b/src/cmd/go/testdata/script/work_issue54372.txt
new file mode 100644
index 0000000..bd3108a
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_issue54372.txt
@@ -0,0 +1,37 @@
+# go mod verify should not try to verify the workspace modules.
+# This is a test for #54372.
+
+go mod verify
+stdout 'all modules verified'
+! stderr .
+
+-- go.work --
+go 1.21
+
+use (
+ ./a
+ ./b
+ ./c
+ ./d
+)
+-- a/go.mod --
+module example.com/a
+
+go 1.21
+
+require rsc.io/quote v1.1.0
+-- a/a.go --
+package a
+import _ "rsc.io/quote"
+-- b/go.mod --
+module example.com/b
+
+go 1.21
+-- c/go.mod --
+module example.com/c
+
+go 1.21
+-- d/go.mod --
+module example.com/d
+
+go 1.21 \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/work_module_not_in_go_work.txt b/src/cmd/go/testdata/script/work_module_not_in_go_work.txt
new file mode 100644
index 0000000..074bac5
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_module_not_in_go_work.txt
@@ -0,0 +1,40 @@
+# This is a regression test for issue #49632.
+# The Go command should mention go.work if the user
+# tries to load a local package that's in a module
+# that's not in go.work and can't be resolved.
+
+! go list ./...
+stderr 'pattern ./...: directory prefix . does not contain modules listed in go.work or their selected dependencies'
+
+! go list ./a/c
+stderr 'directory a[\\/]c is contained in a module that is not one of the workspace modules listed in go.work. You can add the module to the workspace using:\n\tgo work use a'
+
+! go install ./a/c
+stderr 'directory a[\\/]c is contained in a module that is not one of the workspace modules listed in go.work. You can add the module to the workspace using:\n\tgo work use a'
+
+cd a/c
+! go run .
+stderr 'current directory is contained in a module that is not one of the workspace modules listed in go.work. You can add the module to the workspace using:\n\tgo work use \.\.'
+
+cd ../..
+! go run .
+stderr 'current directory outside modules listed in go.work or their selected dependencies'
+
+-- go.work --
+go 1.18
+
+use ./b
+-- a/go.mod --
+module example.com/a
+
+go 1.18
+-- a/a.go --
+package a
+-- a/c/c.go --
+package main
+-- b/go.mod --
+module example.com/b
+
+go 1.18
+-- foo.go --
+package foo
diff --git a/src/cmd/go/testdata/script/work_nowork.txt b/src/cmd/go/testdata/script/work_nowork.txt
new file mode 100644
index 0000000..b4c9b1d
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_nowork.txt
@@ -0,0 +1,20 @@
+! go work use
+stderr '^go: no go\.work file found\n\t\(run ''go work init'' first or specify path using GOWORK environment variable\)$'
+
+! go work use .
+stderr '^go: no go\.work file found\n\t\(run ''go work init'' first or specify path using GOWORK environment variable\)$'
+
+! go work edit
+stderr '^go: no go\.work file found\n\t\(run ''go work init'' first or specify path using GOWORK environment variable\)$'
+
+! go work edit -go=1.18
+stderr '^go: no go\.work file found\n\t\(run ''go work init'' first or specify path using GOWORK environment variable\)$'
+
+! go work sync
+stderr '^go: no go\.work file found\n\t\(run ''go work init'' first or specify path using GOWORK environment variable\)$'
+
+-- go.mod --
+module example
+go 1.18
+-- README.txt --
+There is no go.work file here.
diff --git a/src/cmd/go/testdata/script/work_prune.txt b/src/cmd/go/testdata/script/work_prune.txt
new file mode 100644
index 0000000..b1f569e
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_prune.txt
@@ -0,0 +1,103 @@
+# This test makes sure workspace mode's handling of the module graph
+# is compatible with module pruning. The graph we load from either of
+# the workspace modules should be the same, even if their graphs
+# don't overlap.
+#
+# This is the module graph in the test:
+#
+# example.com/a -> example.com/b v1.0.0 -> example.com/q v1.1.0
+# example.com/p -> example.com/q v1.0.0
+#
+# If we didn't load the whole graph and didn't load the dependencies of b
+# when loading p, we would end up loading q v1.0.0, rather than v1.1.0,
+# which is selected by MVS.
+
+go list -m -f '{{.Version}}' example.com/q
+stdout '^v1.1.0$'
+
+-- go.work --
+go 1.18
+
+use (
+ ./a
+ ./p
+)
+-- a/go.mod --
+module example.com/a
+
+go 1.18
+
+require example.com/b v1.0.0
+
+replace example.com/b v1.0.0 => ../b
+-- a/foo.go --
+package main
+
+import "example.com/b"
+
+func main() {
+ b.B()
+}
+-- b/go.mod --
+module example.com/b
+
+go 1.18
+
+require example.com/q v1.1.0
+
+replace example.com/q v1.0.0 => ../q1_0_0
+replace example.com/q v1.1.0 => ../q1_1_0
+-- b/b.go --
+package b
+
+func B() {
+}
+-- b/b_test.go --
+package b
+
+import "example.com/q"
+
+func TestB() {
+ q.PrintVersion()
+}
+-- p/go.mod --
+module example.com/p
+
+go 1.18
+
+require example.com/q v1.0.0
+
+replace example.com/q v1.0.0 => ../q1_0_0
+replace example.com/q v1.1.0 => ../q1_1_0
+-- p/main.go --
+package main
+
+import "example.com/q"
+
+func main() {
+ q.PrintVersion()
+}
+-- q1_0_0/go.mod --
+module example.com/q
+
+go 1.18
+-- q1_0_0/q.go --
+package q
+
+import "fmt"
+
+func PrintVersion() {
+ fmt.Println("version 1.0.0")
+}
+-- q1_1_0/go.mod --
+module example.com/q
+
+go 1.18
+-- q1_1_0/q.go --
+package q
+
+import "fmt"
+
+func PrintVersion() {
+ fmt.Println("version 1.1.0")
+}
diff --git a/src/cmd/go/testdata/script/work_prune_all.txt b/src/cmd/go/testdata/script/work_prune_all.txt
new file mode 100644
index 0000000..a7ad9c0
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_prune_all.txt
@@ -0,0 +1,176 @@
+# This test makes sure workspace mode's handling of the module graph
+# is compatible with module pruning. The graph we load from either of
+# the workspace modules should be the same, even if their graphs
+# don't overlap.
+#
+# This is the module graph in the test:
+#
+# example.com/p -> example.com/q v1.0.0
+# example.com/a -> example.com/b v1.0.0 -> example.com/q v1.1.0 -> example.com/w v1.0.0 -> example.com/x v1.0.0 -> example.com/y v1.0.0
+# |-> example.com/z v1.0.0 |-> example.com/z v1.1.0
+# |-> example.com/q v1.0.5 -> example.com/r v1.0.0
+# If we didn't load the whole graph and didn't load the dependencies of b
+# when loading p, we would end up loading q v1.0.0, rather than v1.1.0,
+# which is selected by MVS.
+
+go list -m all
+stdout 'example.com/w v1.0.0'
+stdout 'example.com/q v1.1.0'
+stdout 'example.com/z v1.1.0'
+stdout 'example.com/x v1.0.0'
+! stdout 'example.com/r'
+! stdout 'example.com/y'
+
+-- go.work --
+go 1.18
+
+use (
+ ./a
+ ./p
+)
+
+replace example.com/b v1.0.0 => ./b
+replace example.com/q v1.0.0 => ./q1_0_0
+replace example.com/q v1.0.5 => ./q1_0_5
+replace example.com/q v1.1.0 => ./q1_1_0
+replace example.com/r v1.0.0 => ./r
+replace example.com/w v1.0.0 => ./w
+replace example.com/x v1.0.0 => ./x
+replace example.com/y v1.0.0 => ./y
+replace example.com/z v1.0.0 => ./z1_0_0
+replace example.com/z v1.1.0 => ./z1_1_0
+
+-- a/go.mod --
+module example.com/a
+
+go 1.18
+
+require example.com/b v1.0.0
+require example.com/z v1.0.0
+-- a/foo.go --
+package main
+
+import "example.com/b"
+
+func main() {
+ b.B()
+}
+-- b/go.mod --
+module example.com/b
+
+go 1.18
+
+require example.com/q v1.1.0
+-- b/b.go --
+package b
+
+func B() {
+}
+-- p/go.mod --
+module example.com/p
+
+go 1.18
+
+require example.com/q v1.0.0
+
+replace example.com/q v1.0.0 => ../q1_0_0
+replace example.com/q v1.1.0 => ../q1_1_0
+-- p/main.go --
+package main
+
+import "example.com/q"
+
+func main() {
+ q.PrintVersion()
+}
+-- q1_0_0/go.mod --
+module example.com/q
+
+go 1.18
+-- q1_0_0/q.go --
+package q
+
+import "fmt"
+
+func PrintVersion() {
+ fmt.Println("version 1.0.0")
+}
+-- q1_0_5/go.mod --
+module example.com/q
+
+go 1.18
+
+require example.com/r v1.0.0
+-- q1_0_5/q.go --
+package q
+
+import _ "example.com/r"
+-- q1_1_0/go.mod --
+module example.com/q
+
+require example.com/w v1.0.0
+require example.com/z v1.1.0
+
+go 1.18
+-- q1_1_0/q.go --
+package q
+
+import _ "example.com/w"
+import _ "example.com/z"
+
+import "fmt"
+
+func PrintVersion() {
+ fmt.Println("version 1.1.0")
+}
+-- r/go.mod --
+module example.com/r
+
+go 1.18
+
+require example.com/r v1.0.0
+-- r/r.go --
+package r
+-- w/go.mod --
+module example.com/w
+
+go 1.18
+
+require example.com/x v1.0.0
+-- w/w.go --
+package w
+-- w/w_test.go --
+package w
+
+import _ "example.com/x"
+-- x/go.mod --
+module example.com/x
+
+go 1.18
+-- x/x.go --
+package x
+-- x/x_test.go --
+package x
+import _ "example.com/y"
+-- y/go.mod --
+module example.com/y
+
+go 1.18
+-- y/y.go --
+package y
+-- z1_0_0/go.mod --
+module example.com/z
+
+go 1.18
+
+require example.com/q v1.0.5
+-- z1_0_0/z.go --
+package z
+
+import _ "example.com/q"
+-- z1_1_0/go.mod --
+module example.com/z
+
+go 1.18
+-- z1_1_0/z.go --
+package z
diff --git a/src/cmd/go/testdata/script/work_regression_hang.txt b/src/cmd/go/testdata/script/work_regression_hang.txt
new file mode 100644
index 0000000..a7661b6
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_regression_hang.txt
@@ -0,0 +1,71 @@
+# This test makes checks against a regression of a bug in the Go command
+# where the module loader hung forever because all main module dependencies
+# kept workspace pruning instead of adopting the pruning in their go.mod
+# files, and the loader kept adding dependencies on the queue until they
+# were either pruned or unpruned, never breaking a module dependency cycle.
+#
+# This is the module graph in the test:
+#
+# /-------------------------\
+# | |
+# V |
+# example.com/a -> example.com/b v1.0.0 -> example.com/c v1.1.0
+
+go list -m -f '{{.Version}}' example.com/c
+
+-- go.work --
+go 1.16
+
+use (
+ ./a
+)
+-- a/go.mod --
+module example.com/a
+
+go 1.18
+
+require example.com/b v1.0.0
+
+replace example.com/b v1.0.0 => ../b
+replace example.com/c v1.0.0 => ../c
+-- a/foo.go --
+package main
+
+import "example.com/b"
+
+func main() {
+ b.B()
+}
+-- b/go.mod --
+module example.com/b
+
+go 1.18
+
+require example.com/c v1.0.0
+-- b/b.go --
+package b
+
+func B() {
+}
+-- b/cmd/main.go --
+package main
+
+import "example.com/c"
+
+func main() {
+ c.C()
+}
+-- c/go.mod --
+module example.com/c
+
+go 1.18
+
+require example.com/b v1.0.0
+-- c/c.go --
+package c
+
+import "example.com/b"
+
+func C() {
+ b.B()
+} \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/work_reject_modfile.txt b/src/cmd/go/testdata/script/work_reject_modfile.txt
new file mode 100644
index 0000000..f0cfa3b
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_reject_modfile.txt
@@ -0,0 +1,34 @@
+# Test that -modfile=path/to/go.mod is rejected in workspace mode.
+
+! go list -m -modfile=./a/go.alt.mod
+stderr 'go: -modfile cannot be used in workspace mode'
+
+env GOFLAGS=-modfile=./a/go.alt.mod
+! go list -m
+stderr 'go: -modfile cannot be used in workspace mode'
+
+-- go.work --
+go 1.20
+
+use (
+ ./a
+)
+
+-- a/go.mod --
+module example.com/foo
+
+go 1.20
+
+-- a/go.alt.mod --
+module example.com/foo
+
+go 1.20
+
+-- a/main.go --
+package main
+
+import "fmt"
+
+func main() {
+ fmt.Println("Hello world!")
+}
diff --git a/src/cmd/go/testdata/script/work_replace.txt b/src/cmd/go/testdata/script/work_replace.txt
new file mode 100644
index 0000000..81268e5
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_replace.txt
@@ -0,0 +1,55 @@
+# Support replace statement in go.work file
+
+# Replacement in go.work file, and none in go.mod file.
+go list -m example.com/dep
+stdout 'example.com/dep v1.0.0 => ./dep'
+
+# Wildcard replacement in go.work file overrides version replacement in go.mod
+# file.
+go list -m example.com/other
+stdout 'example.com/other v1.0.0 => ./other2'
+
+-- go.work --
+use m
+
+replace example.com/dep => ./dep
+replace example.com/other => ./other2
+
+-- m/go.mod --
+module example.com/m
+
+require example.com/dep v1.0.0
+require example.com/other v1.0.0
+
+replace example.com/other v1.0.0 => ./other
+-- m/m.go --
+package m
+
+import "example.com/dep"
+import "example.com/other"
+
+func F() {
+ dep.G()
+ other.H()
+}
+-- dep/go.mod --
+module example.com/dep
+-- dep/dep.go --
+package dep
+
+func G() {
+}
+-- other/go.mod --
+module example.com/other
+-- other/dep.go --
+package other
+
+func G() {
+}
+-- other2/go.mod --
+module example.com/other
+-- other2/dep.go --
+package other
+
+func G() {
+} \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/work_replace_conflict.txt b/src/cmd/go/testdata/script/work_replace_conflict.txt
new file mode 100644
index 0000000..7b71b0f
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_replace_conflict.txt
@@ -0,0 +1,53 @@
+# Conflicting replaces in workspace modules returns error that suggests
+# overriding it in the go.work file.
+
+! go list -m example.com/dep
+stderr 'go: conflicting replacements for example.com/dep@v1.0.0:\n\t'$PWD${/}'dep1\n\t'$PWD${/}'dep2\nuse "go work edit -replace example.com/dep@v1.0.0=\[override\]" to resolve'
+go work edit -replace example.com/dep@v1.0.0=./dep1
+go list -m example.com/dep
+stdout 'example.com/dep v1.0.0 => ./dep1'
+
+-- foo --
+-- go.work --
+use m
+use n
+-- m/go.mod --
+module example.com/m
+
+require example.com/dep v1.0.0
+replace example.com/dep v1.0.0 => ../dep1
+-- m/m.go --
+package m
+
+import "example.com/dep"
+
+func F() {
+ dep.G()
+}
+-- n/go.mod --
+module example.com/n
+
+require example.com/dep v1.0.0
+replace example.com/dep v1.0.0 => ../dep2
+-- n/n.go --
+package n
+
+import "example.com/dep"
+
+func F() {
+ dep.G()
+}
+-- dep1/go.mod --
+module example.com/dep
+-- dep1/dep.go --
+package dep
+
+func G() {
+}
+-- dep2/go.mod --
+module example.com/dep
+-- dep2/dep.go --
+package dep
+
+func G() {
+}
diff --git a/src/cmd/go/testdata/script/work_replace_conflict_override.txt b/src/cmd/go/testdata/script/work_replace_conflict_override.txt
new file mode 100644
index 0000000..c62084b
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_replace_conflict_override.txt
@@ -0,0 +1,57 @@
+# Conflicting workspace module replaces can be overridden by a replace in the
+# go.work file.
+
+go list -m example.com/dep
+stdout 'example.com/dep v1.0.0 => ./dep3'
+
+-- go.work --
+use m
+use n
+replace example.com/dep => ./dep3
+-- m/go.mod --
+module example.com/m
+
+require example.com/dep v1.0.0
+replace example.com/dep => ./dep1
+-- m/m.go --
+package m
+
+import "example.com/dep"
+
+func F() {
+ dep.G()
+}
+-- n/go.mod --
+module example.com/n
+
+require example.com/dep v1.0.0
+replace example.com/dep => ./dep2
+-- n/n.go --
+package n
+
+import "example.com/dep"
+
+func F() {
+ dep.G()
+}
+-- dep1/go.mod --
+module example.com/dep
+-- dep1/dep.go --
+package dep
+
+func G() {
+}
+-- dep2/go.mod --
+module example.com/dep
+-- dep2/dep.go --
+package dep
+
+func G() {
+}
+-- dep3/go.mod --
+module example.com/dep
+-- dep3/dep.go --
+package dep
+
+func G() {
+}
diff --git a/src/cmd/go/testdata/script/work_replace_main_module.txt b/src/cmd/go/testdata/script/work_replace_main_module.txt
new file mode 100644
index 0000000..b213764
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_replace_main_module.txt
@@ -0,0 +1,45 @@
+# Ensure that replaces of the main module in workspace modules
+# are ignored, and replaces in the go.work file are disallowed.
+# This tests against an issue where requirements of the
+# main module were being ignored because the main module
+# was replaced in a transitive dependency with another
+# version.
+
+go list example.com/dep
+
+cp replace_main_module.go.work go.work
+! go list example.com/dep
+stderr 'go: workspace module example.com/mainmoda is replaced at all versions in the go.work file. To fix, remove the replacement from the go.work file or specify the version at which to replace the module.'
+
+-- replace_main_module.go.work --
+go 1.18
+use (
+ ./mainmoda
+ ./mainmodb
+)
+replace example.com/mainmoda => ../mainmodareplacement
+-- go.work --
+go 1.18
+use (
+ ./mainmoda
+ ./mainmodb
+)
+-- mainmoda/go.mod --
+module example.com/mainmoda
+
+go 1.18
+
+require example.com/dep v1.0.0
+replace example.com/dep => ../dep
+
+-- dep/go.mod --
+module example.com/dep
+-- dep/dep.go --
+package dep
+-- mainmodb/go.mod --
+module example.com/mainmodb
+go 1.18
+replace example.com/mainmoda => ../mainmodareplacement
+-- mainmodareplacement/go.mod --
+module example.com/mainmoda
+go 1.18 \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/work_sum.txt b/src/cmd/go/testdata/script/work_sum.txt
new file mode 100644
index 0000000..19dbb90
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_sum.txt
@@ -0,0 +1,34 @@
+# Test adding sums to go.work.sum when sum isn't in go.mod.
+
+go run .
+cmp go.work.sum want.sum
+
+-- want.sum --
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw=
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0=
+rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
+-- go.work --
+go 1.18
+
+use .
+-- go.mod --
+go 1.18
+
+module example.com/hi
+
+require "rsc.io/quote" v1.5.2
+-- go.sum --
+rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+-- main.go --
+package main
+
+import (
+ "fmt"
+ "rsc.io/quote"
+)
+
+func main() {
+ fmt.Println(quote.Hello())
+} \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/work_sum_mismatch.txt b/src/cmd/go/testdata/script/work_sum_mismatch.txt
new file mode 100644
index 0000000..ca5d71d
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_sum_mismatch.txt
@@ -0,0 +1,61 @@
+# Test mismatched sums in go.sum files
+
+! go run ./a
+cmpenv stderr want-error
+
+-- want-error --
+verifying rsc.io/sampler@v1.3.0/go.mod: checksum mismatch
+ downloaded: h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+ $WORK${/}gopath${/}src${/}a${/}go.sum: h1:U1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+
+SECURITY ERROR
+This download does NOT match an earlier download recorded in go.sum.
+The bits may have been replaced on the origin server, or an attacker may
+have intercepted the download attempt.
+
+For more information, see 'go help module-auth'.
+-- go.work --
+go 1.18
+
+use ./a
+use ./b
+-- a/go.mod --
+go 1.18
+
+module example.com/hi
+
+require "rsc.io/quote" v1.5.2
+-- a/go.sum --
+rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII=
+rsc.io/sampler v1.3.0/go.mod h1:U1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+-- a/main.go --
+package main
+
+import (
+ "fmt"
+ "rsc.io/quote"
+)
+
+func main() {
+ fmt.Println(quote.Hello())
+}
+-- b/go.mod --
+go 1.18
+
+module example.com/hi2
+
+require "rsc.io/quote" v1.5.2
+-- b/go.sum --
+rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+-- b/main.go --
+package main
+
+import (
+ "fmt"
+ "rsc.io/quote"
+)
+
+func main() {
+ fmt.Println(quote.Hello())
+} \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/work_sync.txt b/src/cmd/go/testdata/script/work_sync.txt
new file mode 100644
index 0000000..69167d4
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_sync.txt
@@ -0,0 +1,119 @@
+go work sync
+cmp a/go.mod a/want_go.mod
+cmp b/go.mod b/want_go.mod
+
+-- go.work --
+go 1.18
+
+use (
+ ./a
+ ./b
+)
+
+-- a/go.mod --
+go 1.18
+
+module example.com/a
+
+require (
+ example.com/p v1.0.0
+ example.com/q v1.1.0
+ example.com/r v1.0.0
+)
+
+replace (
+ example.com/p => ../p
+ example.com/q => ../q
+ example.com/r => ../r
+)
+-- a/want_go.mod --
+go 1.18
+
+module example.com/a
+
+require (
+ example.com/p v1.1.0
+ example.com/q v1.1.0
+)
+
+replace (
+ example.com/p => ../p
+ example.com/q => ../q
+ example.com/r => ../r
+)
+-- a/a.go --
+package a
+
+import (
+ "example.com/p"
+ "example.com/q"
+)
+
+func Foo() {
+ p.P()
+ q.Q()
+}
+-- b/go.mod --
+go 1.18
+
+module example.com/b
+
+require (
+ example.com/p v1.1.0
+ example.com/q v1.0.0
+)
+
+replace (
+ example.com/p => ../p
+ example.com/q => ../q
+)
+-- b/want_go.mod --
+go 1.18
+
+module example.com/b
+
+require (
+ example.com/p v1.1.0
+ example.com/q v1.1.0
+)
+
+replace (
+ example.com/p => ../p
+ example.com/q => ../q
+)
+-- b/b.go --
+package b
+
+import (
+ "example.com/p"
+ "example.com/q"
+)
+
+func Foo() {
+ p.P()
+ q.Q()
+}
+-- p/go.mod --
+go 1.18
+
+module example.com/p
+-- p/p.go --
+package p
+
+func P() {}
+-- q/go.mod --
+go 1.18
+
+module example.com/q
+-- q/q.go --
+package q
+
+func Q() {}
+-- r/go.mod --
+go 1.18
+
+module example.com/r
+-- r/q.go --
+package r
+
+func R() {} \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/work_sync_irrelevant_dependency.txt b/src/cmd/go/testdata/script/work_sync_irrelevant_dependency.txt
new file mode 100644
index 0000000..072323d
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_sync_irrelevant_dependency.txt
@@ -0,0 +1,119 @@
+# Test of go work sync in a workspace in which some dependency needed by `a`
+# appears at a lower version in the build list of `b`, but is not needed at all
+# by `b` (so it should not be upgraded within b).
+#
+# a -> p 1.1
+# b -> q 1.0 -(through a test dependency)-> p 1.0
+go work sync
+cmp a/go.mod a/want_go.mod
+cmp b/go.mod b/want_go.mod
+
+-- go.work --
+go 1.18
+
+use (
+ ./a
+ ./b
+)
+
+-- a/go.mod --
+go 1.18
+
+module example.com/a
+
+require (
+ example.com/p v1.1.0
+)
+
+replace (
+ example.com/p => ../p
+)
+-- a/want_go.mod --
+go 1.18
+
+module example.com/a
+
+require (
+ example.com/p v1.1.0
+)
+
+replace (
+ example.com/p => ../p
+)
+-- a/a.go --
+package a
+
+import (
+ "example.com/p"
+)
+
+func Foo() {
+ p.P()
+}
+-- b/go.mod --
+go 1.18
+
+module example.com/b
+
+require (
+ example.com/q v1.0.0
+)
+
+replace (
+ example.com/q => ../q
+)
+-- b/want_go.mod --
+go 1.18
+
+module example.com/b
+
+require (
+ example.com/q v1.0.0
+)
+
+replace (
+ example.com/q => ../q
+)
+-- b/b.go --
+package b
+
+import (
+ "example.com/q"
+)
+
+func Foo() {
+ q.Q()
+}
+-- p/go.mod --
+go 1.18
+
+module example.com/p
+-- p/p.go --
+package p
+
+func P() {}
+-- q/go.mod --
+go 1.18
+
+module example.com/q
+
+require (
+ example.com/p v1.0.0
+)
+
+replace (
+ example.com/p => ../p
+)
+-- q/q.go --
+package q
+
+func Q() {
+}
+-- q/q_test.go --
+package q
+
+import example.com/p
+
+func TestQ(t *testing.T) {
+ p.P()
+} \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/work_sync_missing_module.txt b/src/cmd/go/testdata/script/work_sync_missing_module.txt
new file mode 100644
index 0000000..0018c73
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_sync_missing_module.txt
@@ -0,0 +1,12 @@
+# Ensure go work sync works without any modules in go.work.
+go work sync
+
+# Ensure go work sync works even without a go.mod file.
+rm go.mod
+go work sync
+
+-- go.work --
+go 1.18
+-- go.mod --
+go 1.18
+module foo
diff --git a/src/cmd/go/testdata/script/work_sync_relevant_dependency.txt b/src/cmd/go/testdata/script/work_sync_relevant_dependency.txt
new file mode 100644
index 0000000..d799702
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_sync_relevant_dependency.txt
@@ -0,0 +1,106 @@
+# Test of go work sync in a workspace in which some dependency in the build
+# list of 'b' (but not otherwise needed by `b`, so not seen when lazy loading
+# occurs) actually is relevant to `a`.
+#
+# a -> p 1.0
+# b -> q 1.1 -> p 1.1
+go work sync
+cmp a/go.mod a/want_go.mod
+cmp b/go.mod b/want_go.mod
+
+-- go.work --
+go 1.18
+
+use (
+ ./a
+ ./b
+)
+
+-- a/go.mod --
+go 1.18
+
+module example.com/a
+
+require (
+ example.com/p v1.0.0
+)
+
+replace (
+ example.com/p => ../p
+)
+-- a/want_go.mod --
+go 1.18
+
+module example.com/a
+
+require example.com/p v1.1.0
+
+replace example.com/p => ../p
+-- a/a.go --
+package a
+
+import (
+ "example.com/p"
+)
+
+func Foo() {
+ p.P()
+}
+-- b/go.mod --
+go 1.18
+
+module example.com/b
+
+require (
+ example.com/q v1.1.0
+)
+
+replace (
+ example.com/q => ../q
+)
+-- b/want_go.mod --
+go 1.18
+
+module example.com/b
+
+require (
+ example.com/q v1.1.0
+)
+
+replace (
+ example.com/q => ../q
+)
+-- b/b.go --
+package b
+
+import (
+ "example.com/q"
+)
+
+func Foo() {
+ q.Q()
+}
+-- p/go.mod --
+go 1.18
+
+module example.com/p
+-- p/p.go --
+package p
+
+func P() {}
+-- q/go.mod --
+go 1.18
+
+module example.com/q
+
+require example.com/p v1.1.0
+
+replace example.com/p => ../p
+-- q/q.go --
+package q
+
+import example.com/p
+
+func Q() {
+ p.P()
+}
diff --git a/src/cmd/go/testdata/script/work_sync_sum.txt b/src/cmd/go/testdata/script/work_sync_sum.txt
new file mode 100644
index 0000000..656fd31
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_sync_sum.txt
@@ -0,0 +1,40 @@
+# Test that the sum file data state is properly reset between modules in
+# go work sync so that the sum file that's written is correct.
+# Exercises the fix to #50038.
+
+cp b/go.sum b/go.sum.want
+
+# As a sanity check, verify b/go.sum is tidy.
+cd b
+go mod tidy
+cd ..
+cmp b/go.sum b/go.sum.want
+
+# Run go work sync and verify it doesn't change b/go.sum.
+go work sync
+cmp b/go.sum b/go.sum.want
+
+-- b/go.sum --
+rsc.io/quote v1.0.0 h1:kQ3IZQzPTiDJxSZI98YaWgxFEhlNdYASHvh+MplbViw=
+rsc.io/quote v1.0.0/go.mod h1:v83Ri/njykPcgJltBc/gEkJTmjTsNgtO1Y7vyIK1CQA=
+-- go.work --
+go 1.18
+use (
+ ./a
+ ./b
+)
+replace example.com/c => ./c
+-- a/go.mod --
+module example.com/a
+go 1.18
+require rsc.io/fortune v1.0.0
+-- a/a.go --
+package a
+import "rsc.io/fortune"
+-- b/go.mod --
+module example.com/b
+go 1.18
+require rsc.io/quote v1.0.0
+-- b/b.go --
+package b
+import _ "rsc.io/quote"
diff --git a/src/cmd/go/testdata/script/work_sync_toolchain.txt b/src/cmd/go/testdata/script/work_sync_toolchain.txt
new file mode 100644
index 0000000..b752462
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_sync_toolchain.txt
@@ -0,0 +1,45 @@
+# Create basic modules and work space.
+env TESTGO_VERSION=go1.50
+mkdir m1_22_0
+go mod init -C m1_22_0
+go mod edit -C m1_22_0 -go=1.22.0 -toolchain=go1.99.0
+mkdir m1_22_1
+go mod init -C m1_22_1
+go mod edit -C m1_22_1 -go=1.22.1 -toolchain=go1.99.1
+mkdir m1_24_rc0
+go mod init -C m1_24_rc0
+go mod edit -C m1_24_rc0 -go=1.24rc0 -toolchain=go1.99.2
+
+go work init ./m1_22_0 ./m1_22_1
+grep '^go 1.50$' go.work
+! grep toolchain go.work
+
+# work sync with older modules should leave go 1.50 in the go.work.
+go work sync
+cat go.work
+grep '^go 1.50$' go.work
+! grep toolchain go.work
+
+# work sync with newer modules should update go 1.21 -> 1.22.1 and toolchain -> go1.22.9 in go.work
+env TESTGO_VERSION=go1.21
+env TESTGO_VERSION_SWITCH=switch
+go work edit -go=1.21
+grep '^go 1.21$' go.work
+! grep toolchain go.work
+env GOTOOLCHAIN=local
+! go work sync
+stderr '^go: cannot load module m1_22_0 listed in go.work file: m1_22_0'${/}'go.mod requires go >= 1.22.0 \(running go 1.21; GOTOOLCHAIN=local\)$'
+stderr '^go: cannot load module m1_22_1 listed in go.work file: m1_22_1'${/}'go.mod requires go >= 1.22.1 \(running go 1.21; GOTOOLCHAIN=local\)$'
+env GOTOOLCHAIN=auto
+go work sync
+stderr '^go: m1_22_1'${/}'go.mod requires go >= 1.22.1; switching to go1.22.9$'
+grep '^go 1.22.1$' go.work
+grep '^toolchain go1.22.9$' go.work
+
+# work sync with newer modules should update go 1.22.1 -> 1.24rc1 and drop toolchain
+go work edit -use=./m1_24_rc0
+go work sync
+stderr '^go: m1_24_rc0'${/}'go.mod requires go >= 1.24rc0; switching to go1.24rc1$'
+cat go.work
+grep '^go 1.24rc0$' go.work
+grep '^toolchain go1.24rc1$' go.work
diff --git a/src/cmd/go/testdata/script/work_use.txt b/src/cmd/go/testdata/script/work_use.txt
new file mode 100644
index 0000000..7470899
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_use.txt
@@ -0,0 +1,36 @@
+go work use -r foo
+cmp go.work go.want_work_r
+
+! go work use other
+stderr '^go: error reading other'${/}'go.mod: missing module declaration'
+
+go mod edit -C other -module=other
+go work use other
+cmp go.work go.want_work_other
+-- go.work --
+go 1.18
+
+use (
+ foo
+ foo/bar // doesn't exist
+)
+-- go.want_work_r --
+go 1.18
+
+use (
+ ./foo
+ ./foo/bar/baz
+)
+-- go.want_work_other --
+go 1.18
+
+use (
+ ./foo
+ ./foo/bar/baz
+ ./other
+)
+-- foo/go.mod --
+module foo
+-- foo/bar/baz/go.mod --
+module baz
+-- other/go.mod --
diff --git a/src/cmd/go/testdata/script/work_use_deleted.txt b/src/cmd/go/testdata/script/work_use_deleted.txt
new file mode 100644
index 0000000..b379cbc
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_use_deleted.txt
@@ -0,0 +1,22 @@
+go work use -r .
+cmp go.work go.work.want
+
+-- go.work --
+go 1.18
+
+use (
+ .
+ ./sub
+ ./sub/dir/deleted
+)
+-- go.work.want --
+go 1.18
+
+use ./sub/dir
+-- sub/README.txt --
+A go.mod file has been deleted from this directory.
+In addition, the entire subdirectory sub/dir/deleted
+has been deleted, along with sub/dir/deleted/go.mod.
+-- sub/dir/go.mod --
+module example/sub/dir
+go 1.18
diff --git a/src/cmd/go/testdata/script/work_use_dot.txt b/src/cmd/go/testdata/script/work_use_dot.txt
new file mode 100644
index 0000000..8f21042
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_use_dot.txt
@@ -0,0 +1,49 @@
+cp go.work go.work.orig
+
+# If the current directory contains a go.mod file,
+# 'go work use .' should add an entry for it.
+cd bar/baz
+go work use .
+cmp ../../go.work ../../go.work.rel
+
+# If the current directory lacks a go.mod file, 'go work use .'
+# should remove its entry.
+mv go.mod go.mod.bak
+go work use .
+cmp ../../go.work ../../go.work.orig
+
+# If the path is absolute, it should remain absolute.
+mv go.mod.bak go.mod
+go work use $PWD
+grep -count=1 '^use ' ../../go.work
+grep '^use ["]?'$PWD'["]?$' ../../go.work
+
+# An absolute path should replace an entry for the corresponding relative path
+# and vice-versa.
+go work use .
+cmp ../../go.work ../../go.work.rel
+go work use $PWD
+grep -count=1 '^use ' ../../go.work
+grep '^use ["]?'$PWD'["]?$' ../../go.work
+
+# If both the absolute and relative paths are named, 'go work use' should error
+# out: we don't know which one to use, and shouldn't add both because the
+# resulting workspace would contain a duplicate module.
+cp ../../go.work.orig ../../go.work
+! go work use $PWD .
+stderr '^go: already added "\./bar/baz" as "'$PWD'"$'
+cmp ../../go.work ../../go.work.orig
+
+
+-- go.mod --
+module example
+go 1.18
+-- go.work --
+go 1.18
+-- go.work.rel --
+go 1.18
+
+use ./bar/baz
+-- bar/baz/go.mod --
+module example/bar/baz
+go 1.18
diff --git a/src/cmd/go/testdata/script/work_use_issue50958.txt b/src/cmd/go/testdata/script/work_use_issue50958.txt
new file mode 100644
index 0000000..7a25531
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_use_issue50958.txt
@@ -0,0 +1,17 @@
+go work use -r .
+cmp go.work go.work.want
+
+-- go.mod --
+module example
+go 1.18
+-- go.work --
+go 1.18
+
+use sub
+-- go.work.want --
+go 1.18
+
+use .
+-- sub/README.txt --
+This directory no longer contains a go.mod file.
+
diff --git a/src/cmd/go/testdata/script/work_use_issue55952.txt b/src/cmd/go/testdata/script/work_use_issue55952.txt
new file mode 100644
index 0000000..befec67
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_use_issue55952.txt
@@ -0,0 +1,11 @@
+! go list .
+stderr '^go: cannot load module y listed in go\.work file: open y'${/}'go\.mod:'
+
+-- go.work --
+use ./y
+-- x/go.mod --
+module x
+
+go 1.19
+-- x/m.go --
+package m
diff --git a/src/cmd/go/testdata/script/work_use_only_dirs.txt b/src/cmd/go/testdata/script/work_use_only_dirs.txt
new file mode 100644
index 0000000..5d0fcdd
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_use_only_dirs.txt
@@ -0,0 +1,17 @@
+! go work use foo bar baz
+
+stderr '^go: foo is not a directory'
+stderr '^go: directory baz does not exist'
+cmp go.work go.work_want
+
+! go work use -r qux
+stderr '^go: qux is not a directory'
+
+-- go.work --
+go 1.18
+-- go.work_want --
+go 1.18
+-- foo --
+-- qux --
+-- bar/go.mod --
+module bar
diff --git a/src/cmd/go/testdata/script/work_use_toolchain.txt b/src/cmd/go/testdata/script/work_use_toolchain.txt
new file mode 100644
index 0000000..bb3db9c
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_use_toolchain.txt
@@ -0,0 +1,51 @@
+# Create basic modules and work space.
+env TESTGO_VERSION=go1.50
+mkdir m1_22_0
+go mod init -C m1_22_0
+go mod edit -C m1_22_0 -go=1.22.0 -toolchain=go1.99.0
+mkdir m1_22_1
+go mod init -C m1_22_1
+go mod edit -C m1_22_1 -go=1.22.1 -toolchain=go1.99.1
+mkdir m1_24_rc0
+go mod init -C m1_24_rc0
+go mod edit -C m1_24_rc0 -go=1.24rc0 -toolchain=go1.99.2
+
+go work init
+grep '^go 1.50$' go.work
+! grep toolchain go.work
+
+# work use with older modules should leave go 1.50 in the go.work.
+go work use ./m1_22_0
+grep '^go 1.50$' go.work
+! grep toolchain go.work
+
+# work use with newer modules should bump go and toolchain,
+# including updating to a newer toolchain as needed.
+env TESTGO_VERSION=go1.21
+env TESTGO_VERSION_SWITCH=switch
+rm go.work
+go work init
+env GOTOOLCHAIN=local
+! go work use ./m1_22_0
+stderr '^go: m1_22_0'${/}'go.mod requires go >= 1.22.0 \(running go 1.21; GOTOOLCHAIN=local\)$'
+env GOTOOLCHAIN=auto
+go work use ./m1_22_0
+stderr '^go: m1_22_0'${/}'go.mod requires go >= 1.22.0; switching to go1.22.9$'
+grep '^go 1.22.0$' go.work
+grep '^toolchain go1.22.9$' go.work
+
+# work use with an even newer module should bump go again.
+go work use ./m1_22_1
+! stderr switching
+grep '^go 1.22.1$' go.work
+grep '^toolchain go1.22.9$' go.work # unchanged
+
+# work use with an even newer module should bump go and toolchain again.
+env GOTOOLCHAIN=go1.22.9
+! go work use ./m1_24_rc0
+stderr '^go: m1_24_rc0'${/}'go.mod requires go >= 1.24rc0 \(running go 1.22.9; GOTOOLCHAIN=go1.22.9\)$'
+env GOTOOLCHAIN=auto
+go work use ./m1_24_rc0
+stderr '^go: m1_24_rc0'${/}'go.mod requires go >= 1.24rc0; switching to go1.24rc1$'
+grep '^go 1.24rc0$' go.work
+grep '^toolchain go1.24rc1$' go.work
diff --git a/src/cmd/go/testdata/script/work_vendor_empty.txt b/src/cmd/go/testdata/script/work_vendor_empty.txt
new file mode 100644
index 0000000..3c0c7ed
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_vendor_empty.txt
@@ -0,0 +1,16 @@
+go work vendor
+stderr 'go: no dependencies to vendor'
+! exists vendor/modules.txt
+! go list .
+stderr 'go: no modules were found in the current workspace'
+mkdir vendor
+mv bad_modules.txt vendor/modules.txt
+! go list .
+stderr 'go: no modules were found in the current workspace'
+
+-- bad_modules.txt --
+# a/module
+a/package
+-- go.work --
+go 1.21
+
diff --git a/src/cmd/go/testdata/script/work_vendor_main_module_replaced.txt b/src/cmd/go/testdata/script/work_vendor_main_module_replaced.txt
new file mode 100644
index 0000000..70446c7
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_vendor_main_module_replaced.txt
@@ -0,0 +1,46 @@
+# This is a test that if one of the main modules replaces the other
+# the vendor consistency checks still pass. The replacement is ignored
+# because it is of a main module, but it is still recorded in
+# vendor/modules.txt.
+
+go work vendor
+go list all # make sure the consistency checks pass
+! stderr .
+
+# Removing the replace causes consistency checks to fail
+cp a_go_mod_no_replace a/go.mod
+! go list all # consistency checks fail
+stderr 'example.com/b@v0.0.0: is marked as replaced in vendor/modules.txt, but not replaced in the workspace'
+
+
+-- a_go_mod_no_replace --
+module example.com/a
+
+go 1.21
+
+require example.com/b v0.0.0
+-- go.work --
+go 1.21
+
+use (
+ a
+ b
+)
+-- a/go.mod --
+module example.com/a
+
+go 1.21
+
+require example.com/b v0.0.0
+
+replace example.com/b => ../b
+-- a/a.go --
+package a
+
+import _ "example.com/b"
+-- b/go.mod --
+module example.com/b
+
+go 1.21
+-- b/b.go --
+package b \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/work_vendor_modules_txt_conditional.txt b/src/cmd/go/testdata/script/work_vendor_modules_txt_conditional.txt
new file mode 100644
index 0000000..3d671eb
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_vendor_modules_txt_conditional.txt
@@ -0,0 +1,62 @@
+# This test checks to see if we only start in workspace vendor
+# mode if the modules.txt specifies ## workspace (and only in
+# standard vendor if it doesn't).
+
+# vendor directory produced for workspace, workspace mode
+# runs in mod=vendor
+go work vendor
+cmp vendor/modules.txt want_workspace_modules_txt
+go list -f {{.Dir}} example.com/b
+stdout $GOPATH[\\/]src[\\/]vendor[\\/]example.com[\\/]b
+
+# vendor directory produced for workspace, module mode
+# runs in mod=readonly
+env GOWORK=off
+go list -f {{.Dir}} example.com/b
+stdout $GOPATH[\\/]src[\\/]b
+
+# vendor directory produced for module, module mode
+# runs in mod=vendor
+go mod vendor
+cmp vendor/modules.txt want_module_modules_txt
+go list -f {{.Dir}} example.com/b
+stdout $GOPATH[\\/]src[\\/]vendor[\\/]example.com[\\/]b
+
+# vendor directory produced for module, workspace mode
+# runs in mod=readonly
+env GOWORK=
+go list -f {{.Dir}} example.com/b
+stdout $GOPATH[\\/]src[\\/]b
+
+-- want_workspace_modules_txt --
+## workspace
+# example.com/b v0.0.0 => ./b
+## explicit; go 1.21
+example.com/b
+# example.com/b => ./b
+-- want_module_modules_txt --
+# example.com/b v0.0.0 => ./b
+## explicit; go 1.21
+example.com/b
+# example.com/b => ./b
+-- go.work --
+go 1.21
+
+use .
+-- go.mod --
+module example.com/a
+
+go 1.21
+
+require example.com/b v0.0.0
+replace example.com/b => ./b
+-- a.go --
+package a
+
+import _ "example.com/b"
+-- b/go.mod --
+module example.com/b
+
+go 1.21
+-- b/b.go --
+package b \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/work_vendor_modules_txt_consistent.txt b/src/cmd/go/testdata/script/work_vendor_modules_txt_consistent.txt
new file mode 100644
index 0000000..bc0f068
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_vendor_modules_txt_consistent.txt
@@ -0,0 +1,141 @@
+go work vendor
+cmp modules.txt.want vendor/modules.txt
+go list example.com/a example.com/b
+
+# Module required in go.mod but not marked explicit in modules.txt
+cp modules.txt.required_but_not_explicit vendor/modules.txt
+! go list example.com/a example.com/b
+cmpenv stderr required_but_not_explicit_error.txt
+
+# Replacement in go.mod but no replacement in modules.txt
+cp modules.txt.missing_replacement vendor/modules.txt
+! go list example.com/a example.com/b
+cmpenv stderr missing_replacement_error.txt
+
+# Replacement in go.mod but different replacement target in modules.txt
+cp modules.txt.different_replacement vendor/modules.txt
+! go list example.com/a example.com/b
+cmpenv stderr different_replacement_error.txt
+
+# Module marked explicit in modules.txt but not required in go.mod
+cp modules.txt.extra_explicit vendor/modules.txt
+! go list example.com/a example.com/b
+cmpenv stderr extra_explicit_error.txt
+
+# Replacement in modules.txt but not in go.mod
+cp modules.txt.extra_replacement vendor/modules.txt
+! go list example.com/a example.com/b
+cmpenv stderr extra_replacement_error.txt
+
+-- modules.txt.want --
+## workspace
+# example.com/p v1.0.0 => ./p
+## explicit; go 1.21
+# example.com/q v1.0.0 => ./q
+## explicit; go 1.21
+-- modules.txt.required_but_not_explicit --
+## workspace
+# example.com/p v1.0.0 => ./p
+## go 1.21
+# example.com/q v1.0.0 => ./q
+## explicit; go 1.21
+-- required_but_not_explicit_error.txt --
+go: inconsistent vendoring in $GOPATH${/}src:
+ example.com/p@v1.0.0: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
+
+ To ignore the vendor directory, use -mod=readonly or -mod=mod.
+ To sync the vendor directory, run:
+ go work vendor
+-- modules.txt.missing_replacement --
+## workspace
+# example.com/p v1.0.0
+## explicit; go 1.21
+# example.com/q v1.0.0 => ./q
+## explicit; go 1.21
+-- missing_replacement_error.txt --
+go: inconsistent vendoring in $GOPATH${/}src:
+ example.com/p@v1.0.0: is replaced in a${/}go.mod, but not marked as replaced in vendor/modules.txt
+
+ To ignore the vendor directory, use -mod=readonly or -mod=mod.
+ To sync the vendor directory, run:
+ go work vendor
+-- modules.txt.different_replacement --
+## workspace
+# example.com/p v1.0.0 => ./r
+## explicit; go 1.21
+# example.com/q v1.0.0 => ./q
+## explicit; go 1.21
+-- different_replacement_error.txt --
+go: inconsistent vendoring in $GOPATH${/}src:
+ example.com/p@v1.0.0: is replaced by ../p in a${/}go.mod, but marked as replaced by ./r in vendor/modules.txt
+
+ To ignore the vendor directory, use -mod=readonly or -mod=mod.
+ To sync the vendor directory, run:
+ go work vendor
+-- modules.txt.extra_explicit --
+## workspace
+# example.com/p v1.0.0 => ./p
+## explicit; go 1.21
+# example.com/q v1.0.0 => ./q
+## explicit; go 1.21
+# example.com/r v1.0.0
+example.com/r
+## explicit; go 1.21
+-- extra_explicit_error.txt --
+go: inconsistent vendoring in $GOPATH${/}src:
+ example.com/r@v1.0.0: is marked as explicit in vendor/modules.txt, but not explicitly required in a go.mod
+
+ To ignore the vendor directory, use -mod=readonly or -mod=mod.
+ To sync the vendor directory, run:
+ go work vendor
+-- modules.txt.extra_replacement --
+## workspace
+# example.com/p v1.0.0 => ./p
+## explicit; go 1.21
+# example.com/q v1.0.0 => ./q
+## explicit; go 1.21
+# example.com/r v1.0.0 => ./r
+example.com/r
+## go 1.21
+-- extra_replacement_error.txt --
+go: inconsistent vendoring in $GOPATH${/}src:
+ example.com/r@v1.0.0: is marked as replaced in vendor/modules.txt, but not replaced in the workspace
+
+ To ignore the vendor directory, use -mod=readonly or -mod=mod.
+ To sync the vendor directory, run:
+ go work vendor
+-- go.work --
+go 1.21
+
+use (
+ ./a
+ ./b
+)
+-- a/go.mod --
+module example.com/a
+
+go 1.21
+
+require example.com/p v1.0.0
+
+replace example.com/p v1.0.0 => ../p
+-- a/a.go --
+package p
+-- b/go.mod --
+module example.com/b
+
+go 1.21
+
+require example.com/q v1.0.0
+
+replace example.com/q v1.0.0 => ../q
+-- b/b.go --
+package b
+-- p/go.mod --
+module example.com/p
+
+go 1.21
+-- q/go.mod --
+module example.com/q
+
+go 1.21
diff --git a/src/cmd/go/testdata/script/work_vendor_prune.txt b/src/cmd/go/testdata/script/work_vendor_prune.txt
new file mode 100644
index 0000000..424b4d5
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_vendor_prune.txt
@@ -0,0 +1,116 @@
+# This test exercises that vendoring works properly using the workspace in the
+# the work_prune test case.
+
+go work vendor
+cmp vendor/modules.txt modules.txt.want
+cmp vendor/example.com/b/b.go b/b.go
+cmp vendor/example.com/q/q.go q1_1_0/q.go
+go list -m -f '{{.Version}}' example.com/q
+stdout '^v1.1.0$'
+
+go list -f '{{.Dir}}' example.com/q
+stdout $GOPATH[\\/]src[\\/]vendor[\\/]example.com[\\/]q
+go list -f '{{.Dir}}' example.com/b
+stdout $GOPATH[\\/]src[\\/]vendor[\\/]example.com[\\/]b
+
+[short] skip
+
+rm b
+rm q1_0_0
+rm q1_1_0
+go run example.com/p
+stdout 'version 1.1.0'
+
+-- modules.txt.want --
+## workspace
+# example.com/b v1.0.0 => ./b
+## explicit; go 1.18
+example.com/b
+# example.com/q v1.0.0 => ./q1_0_0
+## explicit; go 1.18
+# example.com/q v1.1.0 => ./q1_1_0
+## go 1.18
+example.com/q
+-- go.work --
+go 1.18
+
+use (
+ ./a
+ ./p
+)
+-- a/go.mod --
+module example.com/a
+
+go 1.18
+
+require example.com/b v1.0.0
+
+replace example.com/b v1.0.0 => ../b
+-- a/foo.go --
+package main
+
+import "example.com/b"
+
+func main() {
+ b.B()
+}
+-- b/go.mod --
+module example.com/b
+
+go 1.18
+
+require example.com/q v1.1.0
+-- b/b.go --
+package b
+
+func B() {
+}
+-- b/b_test.go --
+package b
+
+import "example.com/q"
+
+func TestB() {
+ q.PrintVersion()
+}
+-- p/go.mod --
+module example.com/p
+
+go 1.18
+
+require example.com/q v1.0.0
+
+replace example.com/q v1.0.0 => ../q1_0_0
+replace example.com/q v1.1.0 => ../q1_1_0
+-- p/main.go --
+package main
+
+import "example.com/q"
+
+func main() {
+ q.PrintVersion()
+}
+-- q1_0_0/go.mod --
+module example.com/q
+
+go 1.18
+-- q1_0_0/q.go --
+package q
+
+import "fmt"
+
+func PrintVersion() {
+ fmt.Println("version 1.0.0")
+}
+-- q1_1_0/go.mod --
+module example.com/q
+
+go 1.18
+-- q1_1_0/q.go --
+package q
+
+import "fmt"
+
+func PrintVersion() {
+ fmt.Println("version 1.1.0")
+}
diff --git a/src/cmd/go/testdata/script/work_vendor_prune_all.txt b/src/cmd/go/testdata/script/work_vendor_prune_all.txt
new file mode 100644
index 0000000..a369d22
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_vendor_prune_all.txt
@@ -0,0 +1,201 @@
+# This test exercises that vendoring works properly using the workspace in the
+# the work_prune test case.
+
+go work vendor
+cmp vendor/modules.txt modules.txt.want
+go list -f '{{with .Module}}{{.Path}}@{{.Version}}{{end}}' all
+cmp stdout want_versions
+
+go list -f '{{.Dir}}' example.com/q
+stdout $GOPATH[\\/]src[\\/]vendor[\\/]example.com[\\/]q
+go list -f '{{.Dir}}' example.com/b
+stdout $GOPATH[\\/]src[\\/]vendor[\\/]example.com[\\/]b
+go list -f '{{.Dir}}' example.com/w
+stdout $GOPATH[\\/]src[\\/]vendor[\\/]example.com[\\/]w
+go list -f '{{.Dir}}' example.com/z
+stdout $GOPATH[\\/]src[\\/]vendor[\\/]example.com[\\/]z
+
+cmp $GOPATH/src/vendor/example.com/q/q.go q1_1_0/q.go
+
+-- modules.txt.want --
+## workspace
+# example.com/b v1.0.0 => ./b
+## explicit; go 1.18
+example.com/b
+# example.com/q v1.0.0 => ./q1_0_0
+## explicit; go 1.18
+# example.com/q v1.1.0 => ./q1_1_0
+## go 1.18
+example.com/q
+# example.com/w v1.0.0 => ./w
+## go 1.18
+example.com/w
+# example.com/z v1.0.0 => ./z1_0_0
+## explicit; go 1.18
+# example.com/z v1.1.0 => ./z1_1_0
+## go 1.18
+example.com/z
+# example.com/q v1.0.5 => ./q1_0_5
+# example.com/r v1.0.0 => ./r
+# example.com/x v1.0.0 => ./x
+# example.com/y v1.0.0 => ./y
+-- want_versions --
+example.com/a@
+example.com/b@v1.0.0
+example.com/p@
+example.com/q@v1.1.0
+example.com/w@v1.0.0
+example.com/z@v1.1.0
+-- go.work --
+go 1.18
+
+use (
+ ./a
+ ./p
+)
+
+replace example.com/b v1.0.0 => ./b
+replace example.com/q v1.0.0 => ./q1_0_0
+replace example.com/q v1.0.5 => ./q1_0_5
+replace example.com/q v1.1.0 => ./q1_1_0
+replace example.com/r v1.0.0 => ./r
+replace example.com/w v1.0.0 => ./w
+replace example.com/x v1.0.0 => ./x
+replace example.com/y v1.0.0 => ./y
+replace example.com/z v1.0.0 => ./z1_0_0
+replace example.com/z v1.1.0 => ./z1_1_0
+
+-- a/go.mod --
+module example.com/a
+
+go 1.18
+
+require example.com/b v1.0.0
+require example.com/z v1.0.0
+-- a/foo.go --
+package main
+
+import "example.com/b"
+
+func main() {
+ b.B()
+}
+-- b/go.mod --
+module example.com/b
+
+go 1.18
+
+require example.com/q v1.1.0
+-- b/b.go --
+package b
+
+func B() {
+}
+-- p/go.mod --
+module example.com/p
+
+go 1.18
+
+require example.com/q v1.0.0
+
+replace example.com/q v1.0.0 => ../q1_0_0
+replace example.com/q v1.1.0 => ../q1_1_0
+-- p/main.go --
+package main
+
+import "example.com/q"
+
+func main() {
+ q.PrintVersion()
+}
+-- q1_0_0/go.mod --
+module example.com/q
+
+go 1.18
+-- q1_0_0/q.go --
+package q
+
+import "fmt"
+
+func PrintVersion() {
+ fmt.Println("version 1.0.0")
+}
+-- q1_0_5/go.mod --
+module example.com/q
+
+go 1.18
+
+require example.com/r v1.0.0
+-- q1_0_5/q.go --
+package q
+
+import _ "example.com/r"
+-- q1_1_0/go.mod --
+module example.com/q
+
+require example.com/w v1.0.0
+require example.com/z v1.1.0
+
+go 1.18
+-- q1_1_0/q.go --
+package q
+
+import _ "example.com/w"
+import _ "example.com/z"
+
+import "fmt"
+
+func PrintVersion() {
+ fmt.Println("version 1.1.0")
+}
+-- r/go.mod --
+module example.com/r
+
+go 1.18
+
+require example.com/r v1.0.0
+-- r/r.go --
+package r
+-- w/go.mod --
+module example.com/w
+
+go 1.18
+
+require example.com/x v1.0.0
+-- w/w.go --
+package w
+-- w/w_test.go --
+package w
+
+import _ "example.com/x"
+-- x/go.mod --
+module example.com/x
+
+go 1.18
+-- x/x.go --
+package x
+-- x/x_test.go --
+package x
+import _ "example.com/y"
+-- y/go.mod --
+module example.com/y
+
+go 1.18
+-- y/y.go --
+package y
+-- z1_0_0/go.mod --
+module example.com/z
+
+go 1.18
+
+require example.com/q v1.0.5
+-- z1_0_0/z.go --
+package z
+
+import _ "example.com/q"
+-- z1_1_0/go.mod --
+module example.com/z
+
+go 1.18
+-- z1_1_0/z.go --
+package z
diff --git a/src/cmd/go/testdata/script/work_vet.txt b/src/cmd/go/testdata/script/work_vet.txt
new file mode 100644
index 0000000..f95cadd
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_vet.txt
@@ -0,0 +1,19 @@
+! go vet ./a
+stderr 'fmt.Println call has possible Printf formatting directive'
+
+-- go.work --
+go 1.18
+
+use ./a
+-- a/go.mod --
+module example.com/a
+
+go 1.18
+-- a/a.go --
+package a
+
+import "fmt"
+
+func A() {
+ fmt.Println("%s")
+} \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/work_why_download_graph.txt b/src/cmd/go/testdata/script/work_why_download_graph.txt
new file mode 100644
index 0000000..8f1aedd
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_why_download_graph.txt
@@ -0,0 +1,65 @@
+# Test go mod download, why, and graph work in workspace mode.
+# TODO(bcmills): clarify the interaction with #44435
+
+go mod download rsc.io/quote
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.info
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.mod
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.info
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.mod
+grep '^rsc\.io/quote v1\.5\.2/go\.mod h1:' go.work.sum
+grep '^rsc\.io/quote v1\.5\.2 h1:' go.work.sum
+
+go clean -modcache
+rm go.work.sum
+go mod download
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.info
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.mod
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.info
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.mod
+grep '^rsc\.io/quote v1\.5\.2/go\.mod h1:' go.work.sum
+grep '^rsc\.io/quote v1\.5\.2 h1:' go.work.sum
+
+go mod why rsc.io/quote
+stdout '# rsc.io/quote\nexample.com/a\nrsc.io/quote'
+
+go mod graph
+stdout 'example.com/a rsc.io/quote@v1.5.2\nexample.com/b example.com/c@v1.0.0\nrsc.io/quote@v1.5.2 rsc.io/sampler@v1.3.0\nrsc.io/sampler@v1.3.0 golang.org/x/text@v0.0.0-20170915032832-14c0d48ead0c'
+
+-- go.work --
+go 1.18
+
+use (
+ ./a
+ ./b
+)
+-- a/go.mod --
+go 1.18
+
+module example.com/a
+
+require "rsc.io/quote" v1.5.2
+-- a/main.go --
+package main
+
+import (
+ "fmt"
+ "rsc.io/quote"
+)
+
+func main() {
+ fmt.Println(quote.Hello())
+}
+-- b/go.mod --
+go 1.18
+
+module example.com/b
+
+require example.com/c v1.0.0
+replace example.com/c => ../c
+-- c/go.mod --
+go 1.18
+
+module example.com/c
+