Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tests for spdx "relationshipType": "PACKAGE_OF" #1186

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

chirino
Copy link
Contributor

@chirino chirino commented Jan 22, 2025

Verify the relationship type shows up in
/api/v2/analysis/root-component API calls.

Part of issue #1140

Verify the relationship type shows up in 
`/api/v2/analysis/root-component` API calls.

Part of issue trustification#1140

Signed-off-by: Hiram Chirino <[email protected]>
@chirino chirino requested a review from jcrossley3 January 23, 2025 17:22
log::debug!("{response:#?}");
log::debug!("{}", serde_json::to_string_pretty(&response)?);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really wish serde's impl of :#? used to_string_pretty. I can remember the former, but never the latter. :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

100%

);
let request: Request = TestRequest::get().uri(&uri).to_request();
let response: Value = app.call_and_read_body_json(request).await;
log::info!("{}", serde_json::to_string_pretty(&response)?);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use log::debug! inside tests. Our default test output is noisy enough.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

your right.. will fix.

Comment on lines 694 to 702
m == &&json!({
"sbom_id": sbom["sbom_id"],
"node_id": m["node_id"],
"relationship": "PackageOf",
"purl": m["purl"], // long list assume it's correct
"cpe": m["cpe"], // long list assume it's correct
"name": "rubygem-google-cloud-compute",
"version": "0.5.0-1.el8sat"
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To me, this is a brittle test. I'd want my expectation to be the minimum required to affirm the test. If some future change adds or takes away one of the fields that has nothing to do with this test, it's still gonna break. Is that good or annoying? I'd rather something like this, maybe even omitting name and version, too:

Suggested change
m == &&json!({
"sbom_id": sbom["sbom_id"],
"node_id": m["node_id"],
"relationship": "PackageOf",
"purl": m["purl"], // long list assume it's correct
"cpe": m["cpe"], // long list assume it's correct
"name": "rubygem-google-cloud-compute",
"version": "0.5.0-1.el8sat"
})
m["sbom_id"] == sbom["sbom_id"]
&& m["relationship"] == "PackageOf"
&& m["name"] == "rubygem-google-cloud-compute"
&& m["version"] == "0.5.0-1.el8sat"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I kinda was thinking about similar lines. Is there an existing function that can test if an actual Value matches a partial set of fields of another expected Value? The assertion would become more concise and less brittle then.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not that I know of. You can always downcast the Value to an AncestorSummary or DepSummary, but I'm not sure m["name"] is all that better or worse than m.name.

Another option is to use Value::pointer, but I haven't personally tried that.

Copy link
Contributor

@jcrossley3 jcrossley3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like where you're going, but you haven't gone far enough!!!

Comment on lines +12 to +25
// This function checks if the actual JSON object has all the fields of the expected JSON object.
pub fn has_json_fields(actual: &Value, expected: &Value) -> bool {
match (actual.as_object(), expected.as_object()) {
(Some(actual), Some(expected)) => {
for (key, value_a) in expected {
if Some(value_a) != actual.get(key.as_str()) {
return false;
}
}
true
}
_ => false,
}
}
Copy link
Contributor

@jcrossley3 jcrossley3 Jan 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a very cool idea! I want it to do more, though, so forgive me for challenging you. 😄

The function expects Value's, but fails if they're not a specific type of Value. Make it work for any kind of Value. If it's an object, then use recursion to compare the key/value pairs. Probably want to rename the function to is_same or subset or contains or some such.

You'll essentially have two branches:

pub fn is_subset(actual: &Value, expected: &Value) -> bool {
    if expected.is_object() {
        expected.iter().all(|(k, v)| is_subset(&actual[k], v))
    } else {
        expected == actual
    }
}

And no, that won't actually compile due to Value's overly-complicated API, but you can make it work!

And this will be useful all over, so let's stick it somewhere in test-context maybe?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants