Compare commits

...

9 Commits

Author SHA1 Message Date
Sam Robson
9dc0a33a45 some renaming and moving around 2024-12-17 09:19:50 +00:00
Sam Robson
0a41f8aafe add impl files and move bits around 2024-12-16 18:14:24 +00:00
Paolo Tranquilli
d0c5653a0e Just: allow printing of test roots
It was slightly more difficult than I thought, because of some
limitations of just:
* the variadic args story is not super solid when passing them around,
  because just only uses string values internally. There is a plan to
  switch that to string lists though, which would make this easier.
* variables defined on the command line do not cross module boundaries,
  so `just print_test_roots=true rust integration-tests` cannot work.

In the end, this works:

```bash
 # runs the tests
 just rust integration-tests
 # only prints roots
 JUST_PRINT_TEST_ROOTS=true just rust integration-tests
```
2024-12-13 15:18:28 +01:00
Paolo Tranquilli
f1784d5a63 Just: add unit test support 2024-12-12 17:10:31 +01:00
Paolo Tranquilli
3549137982 Just: add C++ (requiring internal repo) 2024-12-12 16:14:02 +01:00
Paolo Tranquilli
066c6c3301 Just: improve structure, add language-tests + integration-tests recipes for rust 2024-12-12 15:21:33 +01:00
Paolo Tranquilli
ee753c6e13 Just: make just install rust work from internal repo 2024-12-12 10:41:10 +01:00
Paolo Tranquilli
1f7d5c0be8 Just: fix standalone case 2024-12-12 10:36:42 +01:00
Paolo Tranquilli
1d88e13446 Just test PoC
This is a rough PoC showcasing [just](https://github.com/casey/just)
as a builder/test runner.

After installing `just` you can (in this PoC <language> can only be
`rust`):
* `just install <language>` to install a language pack in-tree
  `<language>` can be omitted if running from inside its directory.
* `just build <language>` will build `target/intree/codeql-<language>`
  from the internal repository, if available, otherwise it will fall
  back to `install`.
* `just test TESTS... FLAGS...` will run the provided tests, if they
  are of the same kind (integration or QL tests), passing FLAGS to
  the runner. For QL tests the appropriate `build <language>` is run.
  Notably, for QL tests this command works also if using `codeql`
  standalone from the internal repository (using `install` and `codeql`
  from `PATH`). If running from within a test directory, `TESTS` can
  be omitted and defaults to all tests in the current directory.
2024-12-12 10:10:40 +01:00
13 changed files with 170 additions and 0 deletions

4
build.just Normal file
View File

@@ -0,0 +1,4 @@
# import recipes from internal repo, if present
import? '../build_impl.just'
# otherwise, use the local versions
import 'build_impl.just'

9
build_impl.just Normal file
View File

@@ -0,0 +1,9 @@
import 'lib.just'
@_build LANGUAGE:
just install {{ LANGUAGE }};
[group('build')]
build LANGUAGE: (_build LANGUAGE)
alias b := build

1
cpp/justfile Executable file
View File

@@ -0,0 +1 @@
import? '../../cpp.just'

4
cpp/ql/test/justfile Executable file
View File

@@ -0,0 +1,4 @@
import '../../../test.just'
[group('test')]
test *ARGS=".": (_require_semmle_code "C++ language tests") (_language_tests "cpp" ARGS)

2
impl.just Normal file
View File

@@ -0,0 +1,2 @@
import 'build.just'
import 'test.just'

9
install.just Normal file
View File

@@ -0,0 +1,9 @@
import 'lib.just'
@_install LANGUAGE:
cd {{ source_dir() }}; bazel run //{{ trim_end_match(LANGUAGE, '/') }}:install
[group('build')]
install LANGUAGE: (_install LANGUAGE)
alias i := install

9
justfile Executable file
View File

@@ -0,0 +1,9 @@
import 'build.just'
import 'test.just'
import 'install.just'
import? 'local.just'
mod rust
@_default:
{{ just_executable() }} --list --list-submodules

15
lib.just Normal file
View File

@@ -0,0 +1,15 @@
import? '../semmle-code.just' # internal repo just file, if present
set fallback
set allow-duplicate-recipes
set allow-duplicate-variables
set unstable
error := style("error") + "error" + NORMAL + ":"
[no-exit-message]
@_require_semmle_code WHAT:
if [ -z "${SEMMLE_CODE:-}" ]; then \
echo "{{ error }} running {{ WHAT }} requires running from an internal repository checkout" >&2; \
exit 1; \
fi

24
rust/justfile Normal file
View File

@@ -0,0 +1,24 @@
import '../build.just'
import '../install.just'
import '../test.just'
@_default: generate (build "rust")
[group('build')]
install LANGUAGE='rust': (_install LANGUAGE)
[group('build')]
build LANGUAGE='rust': (_build LANGUAGE)
[group('generate')]
generate:
bazel run @codeql//rust/codegen
alias gen := generate
alias g := generate
[group('test')]
integration-tests: (_test_roots 'integration' source_dir() 'ql/integration-tests')
[group('test')]
language-tests: (_test_roots 'language rust' source_dir() 'ql/test')

View File

@@ -0,0 +1,4 @@
import '../../../test.just'
[group('test')]
test *ARGS=".": (_integration_tests ARGS)

4
rust/ql/test/justfile Executable file
View File

@@ -0,0 +1,4 @@
import '../../../test.just'
[group('test')]
test *ARGS=".": (_language_tests "rust" ARGS)

4
test.just Normal file
View File

@@ -0,0 +1,4 @@
# import recipes from internal repo, if present
import? '../test_impl.just'
# otherwise, use the local versions
import 'test_impl.just'

81
test_impl.just Normal file
View File

@@ -0,0 +1,81 @@
print_test_roots := ""
# We want to restrict how much memory codeql threads use, or we can OOM.
RAM := if os() == "linux" { "3000" } else { "2048" }
[no-cd, positional-arguments, no-exit-message]
_language_tests LANGUAGE *ARGS: (_build LANGUAGE)
shift;
codeql test run --search-path={{ source_dir() }} -j0 --ram {{ RAM }} "$@";
@_integration_tests:
echo "No integration tests implemented yet"
[no-cd, script:'python3', positional-arguments, no-exit-message]
_unit_tests *ARGS:
from pathlib import Path as P
import subprocess
import os
import sys
import shutil
def bazel_path(a, cwd):
return P(a).resolve().joinpath("...").relative_to(cwd)
flags = [arg for arg in sys.argv[1:] if arg.startswith('-')]
args = [arg for arg in sys.argv[1:] if not arg.startswith('-')]
cwd = P("{{ source_dir() }}").resolve()
bazel = shutil.which("bazel")
args[:] = [f"//{bazel_path(a, cwd)}" for a in args]
res = subprocess.run([bazel, "test"] + flags + args, cwd=cwd).returncode
sys.exit(res)
[group('test'), no-cd, script:'python3', positional-arguments, no-exit-message]
test +ARGS: # TODO: fuzzy test chooser when no arguments are provided!
import pathlib
import subprocess
import os
import sys
# avoid infinite recursion: this happens when test args are of different kinds
# or for different languages, or also if they are across the external/internal
# repository boundary
# TODO: allow some degree of mixing maybe?
if os.environ.get("CODEQL_JUSTFILE_TEST"):
print("No common test handler found", file=sys.stderr)
sys.exit(1)
os.environ["CODEQL_JUSTFILE_TEST"] = "true"
flags = [arg for arg in sys.argv[1:] if arg.startswith('-')]
args = [arg for arg in sys.argv[1:] if not arg.startswith('-')]
common_path = pathlib.Path(os.path.commonpath(args)).resolve()
if not common_path.is_dir():
common_path = common_path.parent
ret = subprocess.run(
['{{ just_executable() }}', 'test'] + flags + [pathlib.Path(a).resolve().relative_to(common_path) for a in args],
cwd=common_path).returncode
sys.exit(ret)
alias t := test
[script:'python3', positional-arguments, no-exit-message]
_test_roots KIND SOURCE_DIR *ROOTS:
import sys
import subprocess
import os
from pathlib import Path as P
workspace_dir = P("{{ justfile_dir() }}")
just = "{{ just_executable() }}"
kind = sys.argv[1]
if kind.startswith("language"):
_, _, language = kind.partition(" ")
targets = ["_language_tests", language]
else:
targets = [f"_{kind}_tests"]
source_dir = P(sys.argv[2])
roots = sys.argv[3:]
if os.environ.get("JUST_PRINT_TEST_ROOTS"):
source_dir = source_dir.relative_to(workspace_dir)
for root in roots:
print(source_dir / root)
else:
sys.exit(subprocess.run([just] + targets + roots, cwd=source_dir).returncode)