Skip to content

Commit ff05a8d

Browse files
authored
Merge pull request #2054 from apache/jbilleter/recc
Add recc integration tests
2 parents d1191c6 + 9c9e17d commit ff05a8d

File tree

9 files changed

+373
-4
lines changed

9 files changed

+373
-4
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#!/bin/sh
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# Generate a base sysroot for running the BuildStream integration tests.
16+
#
17+
# The sysroot is based off the Debian Linux distribution.
18+
19+
set -eux
20+
21+
DOCKER_ARCH=${DOCKER_ARCH:-amd64}
22+
23+
export DOCKER_DEFAULT_PLATFORM="linux/%{DOCKER_ARCH}"
24+
25+
IMAGE_NAME="integration-tests-debian-base"
26+
27+
docker build --tag ${IMAGE_NAME} -f - << "EOF"
28+
FROM debian:trixie-slim
29+
RUN apt-get update && apt-get install -y --no-install-recommends \
30+
gcc libc6-dev make autoconf automake && \
31+
rm -rf /var/lib/apt/lists/*
32+
EOF
33+
34+
CONTAINER_NAME="$(docker create ${IMAGE_NAME})"
35+
36+
docker export "${CONTAINER_NAME}" | xz > ${IMAGE_NAME}.tar.xz
37+
38+
docker rm "${CONTAINER_NAME}"

tests/integration/project/elements/base/base-alpine.bst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ sources:
1111
(?):
1212
- arch == "x86-64":
1313
ref: 3eb559250ba82b64a68d86d0636a6b127aa5f6d25d3601a79f79214dc9703639
14-
url: "alpine:integration-tests-base.v1.x86_64.tar.xz"
14+
url: "test-images:integration-tests-base.v1.x86_64.tar.xz"
1515
- arch == "aarch64":
1616
ref: 431fb5362032ede6f172e70a3258354a8fd71fcbdeb1edebc0e20968c792329a
17-
url: "alpine:integration-tests-base.v1.aarch64.tar.xz"
17+
url: "test-images:integration-tests-base.v1.aarch64.tar.xz"
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
kind: import
2+
3+
description: |
4+
Debian Linux base for tests
5+
6+
Generated using the `tests/integration/base/generate-debian-base.sh` script.
7+
8+
sources:
9+
- kind: tar
10+
base-dir: ''
11+
ref: 4964ce8b12f2200a3cf1570ac93756bea27055dad771bf2be97751c7a2a0f92c
12+
url: test-images:integration-tests-debian-base.v1.x86_64.tar.xz
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
kind: autotools
2+
description: recc test with autotools
3+
4+
build-depends:
5+
- filename: base/base-debian.bst
6+
config:
7+
digest-environment: RECC_REMOTE_PLATFORM_chrootRootDigest
8+
- recc/recc.bst
9+
10+
sources:
11+
- kind: tar
12+
url: project_dir:/files/amhello.tar.gz
13+
ref: 534a884bc1974ffc539a9c215e35c4217b6f666a134cd729e786b9c84af99650
14+
15+
sandbox:
16+
remote-apis-socket:
17+
path: /tmp/casd.sock
18+
action-cache-enable-update: true
19+
20+
environment:
21+
CC: recc gcc
22+
RECC_LOG_LEVEL: debug
23+
RECC_LOG_DIRECTORY: .recc-log
24+
RECC_DEPS_GLOBAL_PATHS: 1
25+
RECC_NO_PATH_REWRITE: 1
26+
RECC_LINK: 1
27+
RECC_CACHE_ONLY: 1
28+
RECC_CACHE_UPLOAD_LOCAL_BUILD: 1
29+
RECC_SERVER: unix:/tmp/casd.sock
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
kind: import
2+
3+
sources:
4+
- kind: tar
5+
base-dir: ''
6+
ref: 00795f1781fd5f80757dd0c60f6335c221dacfa852edad8209b390dd9cfb1f83
7+
url: buildbox:buildbox-integration/-/releases/1.3.31/downloads/recc-x86_64-linux-gnu.tgz
8+
directory: usr/bin
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
kind: autotools
2+
description: recc test with autotools
3+
4+
build-depends:
5+
- filename: base/base-debian.bst
6+
config:
7+
digest-environment: RECC_REMOTE_PLATFORM_chrootRootDigest
8+
- recc/recc.bst
9+
10+
sources:
11+
- kind: tar
12+
url: project_dir:/files/amhello.tar.gz
13+
ref: 534a884bc1974ffc539a9c215e35c4217b6f666a134cd729e786b9c84af99650
14+
15+
sandbox:
16+
remote-apis-socket:
17+
path: /tmp/casd.sock
18+
19+
environment:
20+
CC: recc gcc
21+
RECC_LOG_LEVEL: debug
22+
RECC_LOG_DIRECTORY: .recc-log
23+
RECC_DEPS_GLOBAL_PATHS: 1
24+
RECC_NO_PATH_REWRITE: 1
25+
RECC_LINK: 1
26+
RECC_SERVER: unix:/tmp/casd.sock

tests/integration/project/project.conf

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ min-version: 2.0
44
element-path: elements
55

66
aliases:
7-
alpine: https://bst-integration-test-images.ams3.cdn.digitaloceanspaces.com/
7+
test-images: https://bst-integration-test-images.ams3.cdn.digitaloceanspaces.com/
8+
buildbox: https://gitlab.com/BuildGrid/buildbox/
89
project_dir: file://{project_dir}
910

1011
plugins:

tests/integration/recc.py

Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
#
2+
# Licensed under the Apache License, Version 2.0 (the "License");
3+
# you may not use this file except in compliance with the License.
4+
# You may obtain a copy of the License at
5+
#
6+
# http://www.apache.org/licenses/LICENSE-2.0
7+
#
8+
# Unless required by applicable law or agreed to in writing, software
9+
# distributed under the License is distributed on an "AS IS" BASIS,
10+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
# See the License for the specific language governing permissions and
12+
# limitations under the License.
13+
#
14+
15+
# Pylint doesn't play well with fixtures and dependency injection from pytest
16+
# pylint: disable=redefined-outer-name
17+
18+
import os
19+
import pytest
20+
21+
from buildstream._testing import cli_integration as cli # pylint: disable=unused-import
22+
from buildstream._testing.integration import assert_contains
23+
from buildstream._testing._utils.site import HAVE_SANDBOX
24+
25+
pytestmark = pytest.mark.integration
26+
27+
28+
DATA_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "project")
29+
30+
31+
@pytest.mark.skipif(not HAVE_SANDBOX, reason="Only available with a functioning sandbox")
32+
@pytest.mark.datafiles(DATA_DIR)
33+
def test_remote_execution(cli, datafiles):
34+
project = str(datafiles)
35+
checkout1 = os.path.join(cli.directory, "checkout1")
36+
checkout2 = os.path.join(cli.directory, "checkout2")
37+
element_name = "recc/remoteexecution.bst"
38+
39+
# Always cache buildtrees to be able to check recc logs
40+
result = cli.run(project=project, args=["--cache-buildtrees", "always", "build", element_name])
41+
if result.exit_code != 0:
42+
# Output recc logs in case of failure
43+
cli.run(
44+
project=project,
45+
args=[
46+
"shell",
47+
"--build",
48+
"--use-buildtree",
49+
element_name,
50+
"--",
51+
"sh",
52+
"-c",
53+
"cat config.log .recc-log/* */.recc-log/*",
54+
],
55+
)
56+
assert result.exit_code == 0
57+
58+
result = cli.run(project=project, args=["artifact", "checkout", element_name, "--directory", checkout1])
59+
assert result.exit_code == 0
60+
61+
assert_contains(
62+
checkout1,
63+
[
64+
"/usr",
65+
"/usr/bin",
66+
"/usr/share",
67+
"/usr/bin/hello",
68+
"/usr/share/doc",
69+
"/usr/share/doc/amhello",
70+
"/usr/share/doc/amhello/README",
71+
],
72+
)
73+
74+
# Check the main build log
75+
result = cli.run(project=project, args=["artifact", "log", element_name])
76+
assert result.exit_code == 0
77+
log = result.output
78+
79+
# Verify we get expected output exactly once
80+
assert log.count("Making all in src") == 1
81+
82+
result = cli.run(
83+
project=project,
84+
args=[
85+
"shell",
86+
"--build",
87+
"--use-buildtree",
88+
element_name,
89+
"--",
90+
"sh",
91+
"-c",
92+
"cat src/.recc-log/recc.buildbox*",
93+
],
94+
)
95+
assert result.exit_code == 0
96+
recc_log = result.output
97+
98+
# Verify recc is successfully using remote execution for both, compiling and linking
99+
assert recc_log.count("Executing action remotely") == 2
100+
assert recc_log.count("Remote execution finished with exit code 0") == 2
101+
102+
# Delete artifact from BuildStream cache to trigger a BuildStream rebuild with action cache hits for recc
103+
result = cli.run(project=project, args=["artifact", "delete", element_name])
104+
assert result.exit_code == 0
105+
106+
result = cli.run(project=project, args=["--cache-buildtrees", "always", "build", element_name])
107+
assert result.exit_code == 0
108+
109+
result = cli.run(project=project, args=["artifact", "checkout", element_name, "--directory", checkout2])
110+
assert result.exit_code == 0
111+
112+
assert_contains(
113+
checkout2,
114+
[
115+
"/usr",
116+
"/usr/bin",
117+
"/usr/share",
118+
"/usr/bin/hello",
119+
"/usr/share/doc",
120+
"/usr/share/doc/amhello",
121+
"/usr/share/doc/amhello/README",
122+
],
123+
)
124+
125+
result = cli.run(
126+
project=project,
127+
args=[
128+
"shell",
129+
"--build",
130+
"--use-buildtree",
131+
element_name,
132+
"--",
133+
"sh",
134+
"-c",
135+
"cat src/.recc-log/recc.buildbox*",
136+
],
137+
)
138+
assert result.exit_code == 0
139+
recc_log = result.output
140+
141+
# Verify recc is getting action cache hits for both, compiling and linking
142+
assert recc_log.count("Action Cache hit") == 2
143+
144+
145+
@pytest.mark.skipif(not HAVE_SANDBOX, reason="Only available with a functioning sandbox")
146+
@pytest.mark.datafiles(DATA_DIR)
147+
def test_cache_only(cli, datafiles):
148+
project = str(datafiles)
149+
checkout1 = os.path.join(cli.directory, "checkout1")
150+
checkout2 = os.path.join(cli.directory, "checkout2")
151+
element_name = "recc/cacheonly.bst"
152+
153+
# Always cache buildtrees to be able to check recc logs
154+
result = cli.run(project=project, args=["--cache-buildtrees", "always", "build", element_name])
155+
if result.exit_code != 0:
156+
# Output recc logs in case of failure
157+
cli.run(
158+
project=project,
159+
args=[
160+
"shell",
161+
"--build",
162+
"--use-buildtree",
163+
element_name,
164+
"--",
165+
"sh",
166+
"-c",
167+
"cat config.log .recc-log/* */.recc-log/*",
168+
],
169+
)
170+
assert result.exit_code == 0
171+
172+
result = cli.run(project=project, args=["artifact", "checkout", element_name, "--directory", checkout1])
173+
assert result.exit_code == 0
174+
175+
assert_contains(
176+
checkout1,
177+
[
178+
"/usr",
179+
"/usr/bin",
180+
"/usr/share",
181+
"/usr/bin/hello",
182+
"/usr/share/doc",
183+
"/usr/share/doc/amhello",
184+
"/usr/share/doc/amhello/README",
185+
],
186+
)
187+
188+
# Check the main build log
189+
result = cli.run(project=project, args=["artifact", "log", element_name])
190+
assert result.exit_code == 0
191+
log = result.output
192+
193+
# Verify we get expected output exactly once
194+
assert log.count("Making all in src") == 1
195+
196+
result = cli.run(
197+
project=project,
198+
args=[
199+
"shell",
200+
"--build",
201+
"--use-buildtree",
202+
element_name,
203+
"--",
204+
"sh",
205+
"-c",
206+
"cat src/.recc-log/recc.buildbox*",
207+
],
208+
)
209+
assert result.exit_code == 0
210+
recc_log = result.output
211+
212+
# Verify recc is using local execution for both, compiling and linking
213+
assert recc_log.count("Action not cached and running in cache-only mode, executing locally") == 2
214+
215+
# Delete artifact from BuildStream cache to trigger a BuildStream rebuild with action cache hits for recc
216+
result = cli.run(project=project, args=["artifact", "delete", element_name])
217+
assert result.exit_code == 0
218+
219+
result = cli.run(project=project, args=["--cache-buildtrees", "always", "build", element_name])
220+
assert result.exit_code == 0
221+
222+
result = cli.run(project=project, args=["artifact", "checkout", element_name, "--directory", checkout2])
223+
assert result.exit_code == 0
224+
225+
assert_contains(
226+
checkout2,
227+
[
228+
"/usr",
229+
"/usr/bin",
230+
"/usr/share",
231+
"/usr/bin/hello",
232+
"/usr/share/doc",
233+
"/usr/share/doc/amhello",
234+
"/usr/share/doc/amhello/README",
235+
],
236+
)
237+
238+
result = cli.run(
239+
project=project,
240+
args=[
241+
"shell",
242+
"--build",
243+
"--use-buildtree",
244+
element_name,
245+
"--",
246+
"sh",
247+
"-c",
248+
"cat src/.recc-log/recc.buildbox*",
249+
],
250+
)
251+
assert result.exit_code == 0
252+
recc_log = result.output
253+
254+
# Verify recc is getting action cache hits for both, compiling and linking
255+
assert recc_log.count("Action Cache hit") == 2

0 commit comments

Comments
 (0)