xref: /aosp_15_r20/external/tink/kokoro/testutils/run_go_mod_tests.sh (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
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