Rust: Split downgrade preservation test

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Paolo Tranquilli
2026-05-27 10:25:53 +02:00
parent d8d546c0be
commit b05c52cba8
14 changed files with 225 additions and 30 deletions

View File

@@ -3,6 +3,7 @@ provide:
- "*/ql/lib/qlpack.yml"
- "*/ql/test*/qlpack.yml"
- "*/ql/upgrade-tests/qlpack.yml"
- "*/ql/downgrade-tests/qlpack.yml"
- "*/ql/examples/qlpack.yml"
- "*/ql/consistency-queries/qlpack.yml"
- "*/ql/automodel/src/qlpack.yml"

3
rust/ql/downgrade-tests/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
*.testproj/
*.actual
*.log

View File

@@ -0,0 +1,5 @@
*.testproj/
*.actual
*.log
Cargo.toml
lib.rs

View File

@@ -0,0 +1,24 @@
# Downgrade Regression Test for rust-analyzer 0.0.328 -> 0.0.301
This test verifies that the dbscheme downgrade script correctly preserves recoverable data when migrating databases from the new schema back to the old schema.
## Running the test
```bash
./run-test.sh
```
This will:
1. Build the current extractor
2. Create a database with the new schema from `upgrade_shapes.rs`
3. Validate the new-schema extraction
4. Downgrade the database to the old schema
5. Check out the old commit (491c373e076)
6. Verify that the recovered old-schema properties still match
## Files
- `new.ql` / `new.expected`: Query for the new schema (validates extraction)
- `downgraded.ql` / `downgraded.expected`: Query for the downgraded old schema
- `upgrade_shapes.rs`: Rust source containing test shapes for all affected schema elements
- `run-test.sh`: Test runner script

View File

@@ -1,6 +1,6 @@
formatArgsArgName
| upgrade_shapes.rs:22:37:22:41 | FormatArgsArg | upgrade_shapes.rs:22:37:22:37 | (no string representation) | upgrade_shapes.rs:22:41:22:41 | 1 | 37 |
| upgrade_shapes.rs:22:44:22:48 | FormatArgsArg | upgrade_shapes.rs:22:44:22:44 | (no string representation) | upgrade_shapes.rs:22:48:22:48 | 2 | 44 |
| upgrade_shapes.rs:22:37:22:41 | FormatArgsArg | upgrade_shapes.rs:22:13:22:49 | (no string representation) | upgrade_shapes.rs:22:41:22:41 | 1 | 13 |
| upgrade_shapes.rs:22:44:22:48 | FormatArgsArg | upgrade_shapes.rs:22:13:22:49 | (no string representation) | upgrade_shapes.rs:22:48:22:48 | 2 | 13 |
tryBlock
| upgrade_shapes.rs:21:13:21:21 | { ... } |
structFieldDefault

View File

@@ -0,0 +1,20 @@
formatArgNamePreserved
| upgrade_shapes.rs:22:37:22:41 | FormatArgsArg | upgrade_shapes.rs:22:37:22:39 | FormatArgsArgName | upgrade_shapes.rs:22:41:22:41 | 1 | 37 | 1 |
| upgrade_shapes.rs:22:44:22:48 | FormatArgsArg | upgrade_shapes.rs:22:44:22:46 | FormatArgsArgName | upgrade_shapes.rs:22:48:22:48 | 2 | 44 | 2 |
tryBlockModifierPreserved
| upgrade_shapes.rs:21:13:21:21 | { ... } | upgrade_shapes.rs:21:13:21:15 | TryBlockModifier |
structFieldDefaultPreserved
| upgrade_shapes.rs:9:5:9:17 | field: u8 | upgrade_shapes.rs:9:17:9:17 | ConstArg | upgrade_shapes.rs:9:17:9:17 | 1 |
variantDiscriminantPreserved
| upgrade_shapes.rs:13:5:13:9 | V | upgrade_shapes.rs:13:9:13:9 | ConstArg | upgrade_shapes.rs:13:9:13:9 | 2 |
pathMetaPreserved
| upgrade_shapes.rs:4:3:4:11 | PathMeta | path_meta |
| upgrade_shapes.rs:7:10:7:18 | PathMeta | path_meta |
keyValueMetaPreserved
| upgrade_shapes.rs:5:3:5:15 | KeyValueMeta | key_value | upgrade_shapes.rs:5:15:5:15 | 1 |
tokenTreeMetaPreserved
| upgrade_shapes.rs:6:3:6:18 | TokenTreeMeta | token_tree | upgrade_shapes.rs:6:13:6:18 | TokenTree |
unsafeMetaPreserved
| upgrade_shapes.rs:7:3:7:19 | UnsafeMeta | upgrade_shapes.rs:7:10:7:18 | PathMeta | path_meta |
traitAliasPreserved
| upgrade_shapes.rs:16:1:18:12 | trait Alias | upgrade_shapes.rs:16:7:16:11 | Alias | upgrade_shapes.rs:16:18:16:22 | ... | upgrade_shapes.rs:17:1:18:11 | WhereClause |

View File

@@ -0,0 +1,73 @@
import codeql.rust.elements
private predicate inUpgradeShapesFile(Locatable loc) {
loc.getFile().getBaseName() = "upgrade_shapes.rs"
}
query predicate formatArgNamePreserved(
FormatArgsArg arg, FormatArgsArgName argName, Expr expr, int argNameColumn, string exprText
) {
inUpgradeShapesFile(arg) and
argName = arg.getArgName() and
expr = arg.getExpr() and
argNameColumn = argName.getLocation().getStartColumn() and
exprText = expr.toString()
}
query predicate tryBlockModifierPreserved(BlockExpr block, TryBlockModifier modifier) {
inUpgradeShapesFile(block) and
modifier = block.getTryBlockModifier() and
modifier.isTry() and
not modifier.hasTypeRepr()
}
query predicate structFieldDefaultPreserved(StructField field, ConstArg defaultVal, Expr expr) {
inUpgradeShapesFile(field) and
defaultVal = field.getDefaultVal() and
expr = defaultVal.getExpr()
}
query predicate variantDiscriminantPreserved(Variant variant, ConstArg constArg, Expr expr) {
inUpgradeShapesFile(variant) and
constArg = variant.getConstArg() and
expr = constArg.getExpr()
}
query predicate pathMetaPreserved(PathMeta meta, string pathText) {
inUpgradeShapesFile(meta) and
pathText = meta.getPath().getText() and
pathText = "path_meta"
}
query predicate keyValueMetaPreserved(KeyValueMeta meta, string pathText, Expr expr) {
inUpgradeShapesFile(meta) and
pathText = meta.getPath().getText() and
pathText = "key_value" and
expr = meta.getExpr()
}
query predicate tokenTreeMetaPreserved(TokenTreeMeta meta, string pathText, TokenTree tokenTree) {
inUpgradeShapesFile(meta) and
pathText = meta.getPath().getText() and
pathText = "token_tree" and
tokenTree = meta.getTokenTree()
}
query predicate unsafeMetaPreserved(UnsafeMeta meta, PathMeta inner, string pathText) {
inUpgradeShapesFile(meta) and
meta.isUnsafe() and
inner = meta.getMeta() and
pathText = inner.getPath().getText() and
pathText = "path_meta"
}
query predicate traitAliasPreserved(
Trait trait, Name name, TypeBoundList bounds, WhereClause whereClause
) {
inUpgradeShapesFile(trait) and
name = trait.getName() and
name.getText() = "Alias" and
bounds = trait.getTypeBoundList() and
whereClause = trait.getWhereClause() and
not trait.hasAssocItemList()
}

View File

@@ -0,0 +1,65 @@
#!/usr/bin/env bash
# Manual regression test for the Rust dbscheme downgrade from rust-analyzer 0.0.328 to 0.0.301.
# See README.md for details.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(git rev-parse --show-toplevel)"
OLD_COMMIT="${OLD_COMMIT:-491c373e076}" # origin/main at time of this upgrade
OLD_DBSCHEME="rust/downgrades/109496fd2f20f28a35e50b110859e74882ee80d6/rust.dbscheme"
cd "$REPO_ROOT"
if ! git diff --quiet HEAD || [ -n "$(git ls-files --others --exclude-standard)" ]; then
echo "ERROR: Working directory has uncommitted changes." >&2
echo "Please commit or stash your changes before running this test." >&2
exit 1
fi
ORIGINAL_REF="$(git rev-parse --abbrev-ref HEAD)"
if [ "$ORIGINAL_REF" = "HEAD" ]; then
ORIGINAL_REF="$(git rev-parse HEAD)"
fi
restore_ref() {
echo "==> Restoring original ref ($ORIGINAL_REF)..."
git checkout --quiet "$ORIGINAL_REF"
}
trap 'restore_ref' EXIT
echo "==> Building current extractor (this may take a while)..."
bazel run //rust:install
echo "==> Creating new-schema test database..."
codeql test run \
--search-path . \
--keep-databases \
"$SCRIPT_DIR/new.ql" "$@"
echo "==> Downgrading dataset to old schema..."
DATASET_DIR=("$SCRIPT_DIR"/*.testproj/db-rust)
if [[ ! -d "${DATASET_DIR[0]}" ]]; then
echo "ERROR: No testproj found at $SCRIPT_DIR/*.testproj" >&2
exit 1
fi
codeql dataset upgrade "${DATASET_DIR[0]}" \
--allow-downgrades \
--search-path rust \
--target-dbscheme "$OLD_DBSCHEME"
echo "==> Checking out old commit ($OLD_COMMIT) for downgrade verification..."
git checkout --quiet "$OLD_COMMIT"
git checkout --quiet "$ORIGINAL_REF" -- rust/ql/downgrade-tests codeql-workspace.yml
echo "==> Running preservation test on downgraded dataset..."
codeql test run \
--search-path . \
--dataset "${DATASET_DIR[0]}" \
--check-databases \
"$SCRIPT_DIR/downgraded.ql" "$@"
restore_ref
trap '' EXIT
echo "==> All tests passed!"

View File

@@ -0,0 +1,23 @@
#![allow(dead_code)]
#![feature(more_qualified_paths)]
#[path_meta]
#[key_value = 1]
#[token_tree(list)]
#[unsafe(path_meta)]
struct S {
field: u8 = 1,
}
enum E {
V = 2,
}
trait Alias<T> = Clone
where
T: Copy;
fn f() {
let _ = try { 1 };
let _ = format_args!("{b} {a}", a = 1, b = 2);
}

View File

@@ -0,0 +1,5 @@
name: codeql/rust-downgrade-tests
version: 0.0.0
extractor: rust
dependencies:
codeql/rust-all: ${workspace}

View File

@@ -1,3 +1,5 @@
*.testproj/
*.actual
*.log
Cargo.toml
lib.rs

View File

@@ -1,6 +1,6 @@
# Upgrade Regression Test for rust-analyzer 0.0.301 → 0.0.328
This test verifies that the dbscheme upgrade and downgrade scripts correctly preserve data when migrating databases between the old and new schemas.
This test verifies that the dbscheme upgrade script correctly preserves data when migrating databases from the old schema to the new schema.
## Running the test
@@ -16,13 +16,10 @@ This will:
5. Restore your branch
6. Upgrade the database to the new schema
7. Verify that the old properties are still accessible via the new schema
8. Downgrade the database back to the old schema
9. Verify that the recovered old-schema properties still match
## Files
- `old.ql` / `old.expected`: Query for the old schema (validates extraction and downgrade)
- `old.ql` / `old.expected`: Query for the old schema (validates extraction)
- `new.ql` / `new.expected`: Query for the new schema (validates upgrade preserved data)
- `downgraded.ql` / `downgraded.expected`: Query for the downgraded old schema
- `upgrade_shapes.rs`: Rust source containing test shapes for all affected schema elements
- `run-test.sh`: Test runner script

View File

@@ -7,7 +7,6 @@ set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(git rev-parse --show-toplevel)"
OLD_COMMIT="${OLD_COMMIT:-491c373e076}" # origin/main at time of this upgrade
OLD_DBSCHEME="rust/downgrades/109496fd2f20f28a35e50b110859e74882ee80d6/rust.dbscheme"
cd "$REPO_ROOT"
@@ -65,26 +64,4 @@ codeql test run \
--check-databases \
"$SCRIPT_DIR/new.ql" "$@"
echo "==> Downgrading dataset back to old schema..."
codeql dataset upgrade "${DATASET_DIR[0]}" \
--allow-downgrades \
--search-path rust \
--target-dbscheme "$OLD_DBSCHEME"
trap 'restore_ref' EXIT
echo "==> Checking out old commit ($OLD_COMMIT) for downgrade verification..."
git checkout --quiet "$OLD_COMMIT"
git checkout --quiet "$ORIGINAL_REF" -- rust/ql/upgrade-tests codeql-workspace.yml
echo "==> Running preservation test on downgraded dataset..."
codeql test run \
--search-path . \
--dataset "${DATASET_DIR[0]}" \
--check-databases \
"$SCRIPT_DIR/downgraded.ql" "$@"
restore_ref
trap '' EXIT
echo "==> All tests passed!"