1#!/bin/bash 2# Copyright 2022 Google LLC 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15################################################################################ 16 17# This script runs tests on a given Go module. 18# 19# Usage: 20# ./kokoro/testutils/run_gomod_tests.sh \ 21# <Full module URL> \ 22# <Local path of the Go module> \ 23# <Module version> \ 24# <Branch at HEAD for the Go module on GitHub> 25 26set -eo pipefail 27 28FULL_GITHUB_MODULE_NAME= 29GO_MODULE_LOCAL_PATH= 30GO_MODULE_VERSION= 31GO_MODULE_GITHUB_HEAD_BRANCH= 32 33usage() { 34 echo "Usage: $0 <full module URL> <go module's local path> \\" 35 echo " <module version> <branch at HEAD>" 36 exit 1 37} 38 39####################################### 40# Process command line arguments. 41# 42# Globals: 43# FULL_GITHUB_MODULE_NAME 44# GO_MODULE_LOCAL_PATH 45# GO_MODULE_VERSION 46# GO_MODULE_GITHUB_HEAD_BRANCH 47####################################### 48process_args() { 49 FULL_GITHUB_MODULE_NAME="$1" 50 readonly FULL_GITHUB_MODULE_NAME 51 GO_MODULE_LOCAL_PATH="$2" 52 readonly GO_MODULE_LOCAL_PATH 53 GO_MODULE_VERSION="$3" 54 readonly GO_MODULE_VERSION 55 GO_MODULE_GITHUB_HEAD_BRANCH="$4" 56 readonly GO_MODULE_GITHUB_HEAD_BRANCH 57 58 if [[ -z "${FULL_GITHUB_MODULE_NAME}" ]]; then 59 usage 60 fi 61 if [[ -z "${GO_MODULE_LOCAL_PATH}" ]]; then 62 usage 63 fi 64 if [[ -z "${GO_MODULE_VERSION}" ]]; then 65 usage 66 fi 67 if [[ -z "${GO_MODULE_GITHUB_HEAD_BRANCH}" ]]; then 68 usage 69 fi 70} 71 72####################################### 73# Add a require statement for a module and a replace statement to point it 74# to the local copy. 75# Arguments: 76# full_github_module_name: The full module name. 77# module_local_path: The root directory of the local Go module. 78# tink_version: Tink version. 79####################################### 80function overlay_module() { 81 local full_github_module_name="$1" 82 local module_local_path="$2" 83 local tink_version="$3" 84 85 go mod edit "-require=${full_github_module_name}@v${tink_version}" 86 go mod edit "-replace=${full_github_module_name}=${module_local_path}" 87} 88 89####################################### 90# Search the go.mod being tested for internal dependencies and overlay them with 91# the local copies. 92# 93# Globals: 94# FULL_GITHUB_MODULE_NAME 95# GO_MODULE_LOCAL_PATH 96# GO_MODULE_VERSION 97####################################### 98overlay_internal_deps() { 99 declare -a internal_deps 100 while read internal_dep; do 101 internal_deps+=("${internal_dep}") 102 done < <(grep "${FULL_GITHUB_MODULE_NAME}" "${GO_MODULE_LOCAL_PATH}/go.mod" \ 103 | grep -v ^module \ 104 | awk '{print $1}') 105 106 # If internal_deps are found... 107 if [[ ! -z "${internal_deps+x}" ]]; then 108 for full_dep_name in "${internal_deps[@]}"; do 109 local dep_name="$(echo "${full_dep_name}" \ 110 | sed "s#${FULL_GITHUB_MODULE_NAME}/##")" 111 overlay_module \ 112 "${full_dep_name}" \ 113 "${dep_name}" \ 114 "${GO_MODULE_VERSION}" 115 done 116 fi 117} 118 119####################################### 120# Builds and tests a given local module. 121# 122# Globals: 123# GO_MODULE_LOCAL_PATH 124# Outputs: 125# Prints progress to STDOUT. 126####################################### 127build_and_test_local_go_mod() { 128 echo "### Testing local Go module at ${GO_MODULE_LOCAL_PATH}" 129 ( 130 set -x 131 cd "${GO_MODULE_LOCAL_PATH}" 132 go build -v ./... 133 go test -v ./... 134 ) 135} 136 137####################################### 138# Builds and tests a given local module. 139# 140# Globals: 141# FULL_GITHUB_MODULE_NAME 142# GO_MODULE_LOCAL_PATH 143# GO_MODULE_VERSION 144# GO_MODULE_GITHUB_HEAD_BRANCH 145# Outputs: 146# Prints progress to STDOUT. 147####################################### 148test_go_module_depending_on_local_one() { 149 # Create a temporary directory for performing module tests. 150 local -r test_tmp_dir="$(mktemp -dt tink-gomod-test.XXXXXX)" 151 local -r go_module_tmp_directory="${test_tmp_dir}/go-mod-test" 152 mkdir "${go_module_tmp_directory}" 153 ( 154 cd "${go_module_tmp_directory}" 155 echo "Using go binary from $(which go): $(go version)" 156 157 set -x 158 # Initialize a test Go module. 159 go mod init tink-go-mod-test 160 overlay_module \ 161 "${FULL_GITHUB_MODULE_NAME}" \ 162 "${GO_MODULE_LOCAL_PATH}" \ 163 "${GO_MODULE_VERSION}" 164 overlay_internal_deps 165 166 # Print the prepared go.mod. 167 cat go.mod 168 169 # Get the module at the latest commit and print graph output depicting 170 # direct dependencies. 171 go get -v "${FULL_GITHUB_MODULE_NAME}@${GO_MODULE_GITHUB_HEAD_BRANCH}" 172 173 # Pint contextual information concerning dependencies. 174 go mod graph | grep tink 175 go list -m all | grep tink 176 ) 177 178 # Leave a clean environment for subsequent tests. 179 go clean -modcache 180 rm -rf "${test_tmp_dir}" 181} 182 183main() { 184 process_args "$@" 185 build_and_test_local_go_mod 186 # Skip this test for modules that are not on github.com/google/tink. 187 if [[ "${FULL_GITHUB_MODULE_NAME}" =~ github.com/google/tink[a-z./]+ ]]; then 188 test_go_module_depending_on_local_one 189 fi 190} 191 192main "$@" 193