Sorry for my novice question. I have written a rego rule to check for ASV Names, and now I am looking to write a test case for the same. I have looked at sample test cases but has no success in writing for my policy(pasted below). Was wondering how could I get a positive and a failure case for the rule below.
asv_list = {"ASVONE","ASVXYZ"}
check_asv := { resources[i]: Reason |
resources:=[resource | data[j] ;
list := {x| x:=asv_list[_]}
not(list[data[j].ASV])
resource:=data[j].Name]
Reason := sprintf("THE ASV - %v being used is not a valid ASV", [data[j].ASV])
}
data = {resource |
doc = input[i];
key_ids := [k | doc[k]; startswith(k, "tag."); k != "tag.#"; endswith(k, ".key")]
resource := {
doc[k] : doc[replace(k, ".key", ".value")] | key_ids[_] == k
}
}
If you're trying to test
check_asv
your positive and negative test cases will look similar:check_asv
is equal to expected value when evaluated with test inputFor example:
Before you start writing tests for your rule though, I think you should clarify the logic you're trying to express because there are a few red flags that jump out. I've tried to breakdown the issues I see in the policy below. At the end, I've written out some example test cases.
Format the file to make it easier to read
First of all, just format the Rego so that it's easier to read. I pasted your example into a file, added a
package
(to make it a valid .rego file) and then ranopa fmt file.rego
:This a little bit easier to read.
Do not name rules
data
I recommend NOT naming that rule
data
.data
in Rego is a special global variable that refers to state cached inside the policy engine. Any data from outside OPA or generated by rules inside of OPA is accessible underdata
. Defining a rule nameddata
is allowed but it's confusing. Renamedata
to something meaningful in the domain. E.g., if these were virtual machine resources, you could name themvm_resources
. In this case, I don't have much to go on, so I'm going to rename it toinput_docs
sincedoc
was used as a variable name:Simplify the
input_docs
helper rule (which was calleddata
in the original)At first glance, this rule is doing quite a bit of work, but in reality, it's not. The first line (
doc = input[i]
) just iterates over each element ininput
. The rest of the rule is based on each element ininput
. The second expression,key_ids := [...
, computes an array of object keys from the element. The third expression,resources := {doc[k]: ...
, constructs a new object by mapping the element.The first expression can't be simplified much, however, it's better to use
:=
instead of=
and sincei
is not referenced anywhere else we can just use_
. The first expression becomes:The second expression computes an array of keys but the filtering is a bit redundant:
k
cannot be equal totag.#
AND end with.key
so the!=
expression can be removed:At this point we could stop however it's worth noticing that the second and third expression in the rule are both just iterating over the
doc
object. There's no reason for two separate expressions here. To simplify this rule we can combine them:Simplify the
check_asv
ruleNow that we have a simplified version of the
input_docs
rule that generates a set of mapped resources we can focus on thecheck_asv
rule. Thecheck_asv
rule can be simplified quite a bit:i
andj
) when there should be only one.The rule can be simplified down to the following:
input_docs
twice (in fact this would be incorrect.)asv_list
, it's already a set.Putting it all together
At this point the policy looks like this:
To test this policy we can easily write a few test cases:
Here's a link to the full policy in the playground: https://play.openpolicyagent.org/p/6w7aC9xWYH