Skip to content

Commit 40024ce

Browse files
authored
ast: not-body marshaling (#8614)
JSON- and pretty format marshaling of `ast.Not` Signed-off-by: Johan Fylling <johan.dev@fylling.se>
1 parent 1a4a713 commit 40024ce

8 files changed

Lines changed: 695 additions & 4 deletions

File tree

cmd/parse_test.go

Lines changed: 374 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"strings"
77
"testing"
88

9+
"github.com/google/go-cmp/cmp"
910
"github.com/open-policy-agent/opa/cmd/formats"
1011
"github.com/open-policy-agent/opa/v1/util/test"
1112
)
@@ -258,6 +259,379 @@ p = 1
258259
}
259260
}
260261

262+
func TestParseOutputWithNotImport(t *testing.T) {
263+
cases := []struct {
264+
format string
265+
exp string
266+
}{
267+
{
268+
format: formats.JSON,
269+
exp: `{
270+
"package": {
271+
"path": [
272+
{
273+
"type": "var",
274+
"value": "data"
275+
},
276+
{
277+
"type": "string",
278+
"value": "test"
279+
}
280+
]
281+
},
282+
"imports": [
283+
{
284+
"path": {
285+
"type": "ref",
286+
"value": [
287+
{
288+
"type": "var",
289+
"value": "future"
290+
},
291+
{
292+
"type": "string",
293+
"value": "keywords"
294+
},
295+
{
296+
"type": "string",
297+
"value": "not"
298+
}
299+
]
300+
}
301+
}
302+
],
303+
"rules": [
304+
{
305+
"body": [
306+
{
307+
"index": 0,
308+
"terms": {
309+
"body": [
310+
{
311+
"index": 0,
312+
"terms": [
313+
{
314+
"type": "ref",
315+
"value": [
316+
{
317+
"type": "var",
318+
"value": "equal"
319+
}
320+
]
321+
},
322+
{
323+
"type": "call",
324+
"value": [
325+
{
326+
"type": "ref",
327+
"value": [
328+
{
329+
"type": "var",
330+
"value": "plus"
331+
}
332+
]
333+
},
334+
{
335+
"type": "ref",
336+
"value": [
337+
{
338+
"type": "var",
339+
"value": "input"
340+
},
341+
{
342+
"type": "string",
343+
"value": "x"
344+
}
345+
]
346+
},
347+
{
348+
"type": "number",
349+
"value": 2
350+
}
351+
]
352+
},
353+
{
354+
"type": "number",
355+
"value": 42
356+
}
357+
]
358+
}
359+
],
360+
"explicit_body": false,
361+
"type": "not"
362+
}
363+
}
364+
],
365+
"head": {
366+
"name": "implicit_body",
367+
"value": {
368+
"type": "boolean",
369+
"value": true
370+
},
371+
"ref": [
372+
{
373+
"type": "var",
374+
"value": "implicit_body"
375+
}
376+
]
377+
}
378+
},
379+
{
380+
"body": [
381+
{
382+
"index": 0,
383+
"terms": {
384+
"body": [
385+
{
386+
"index": 0,
387+
"terms": [
388+
{
389+
"type": "ref",
390+
"value": [
391+
{
392+
"type": "var",
393+
"value": "assign"
394+
}
395+
]
396+
},
397+
{
398+
"type": "var",
399+
"value": "x"
400+
},
401+
{
402+
"type": "ref",
403+
"value": [
404+
{
405+
"type": "var",
406+
"value": "input"
407+
},
408+
{
409+
"type": "string",
410+
"value": "x"
411+
}
412+
]
413+
}
414+
]
415+
},
416+
{
417+
"index": 1,
418+
"terms": [
419+
{
420+
"type": "ref",
421+
"value": [
422+
{
423+
"type": "var",
424+
"value": "assign"
425+
}
426+
]
427+
},
428+
{
429+
"type": "var",
430+
"value": "y"
431+
},
432+
{
433+
"type": "number",
434+
"value": 2
435+
}
436+
]
437+
},
438+
{
439+
"index": 2,
440+
"terms": [
441+
{
442+
"type": "ref",
443+
"value": [
444+
{
445+
"type": "var",
446+
"value": "assign"
447+
}
448+
]
449+
},
450+
{
451+
"type": "var",
452+
"value": "z"
453+
},
454+
{
455+
"type": "call",
456+
"value": [
457+
{
458+
"type": "ref",
459+
"value": [
460+
{
461+
"type": "var",
462+
"value": "plus"
463+
}
464+
]
465+
},
466+
{
467+
"type": "var",
468+
"value": "x"
469+
},
470+
{
471+
"type": "var",
472+
"value": "y"
473+
}
474+
]
475+
}
476+
]
477+
},
478+
{
479+
"index": 3,
480+
"terms": [
481+
{
482+
"type": "ref",
483+
"value": [
484+
{
485+
"type": "var",
486+
"value": "equal"
487+
}
488+
]
489+
},
490+
{
491+
"type": "var",
492+
"value": "z"
493+
},
494+
{
495+
"type": "number",
496+
"value": 42
497+
}
498+
]
499+
}
500+
],
501+
"explicit_body": true,
502+
"type": "not"
503+
}
504+
}
505+
],
506+
"head": {
507+
"name": "explicit_body",
508+
"value": {
509+
"type": "boolean",
510+
"value": true
511+
},
512+
"ref": [
513+
{
514+
"type": "var",
515+
"value": "explicit_body"
516+
}
517+
]
518+
}
519+
}
520+
]
521+
}
522+
`,
523+
},
524+
{
525+
format: formats.Pretty,
526+
exp: `module
527+
package
528+
ref
529+
data
530+
"test"
531+
import
532+
ref
533+
future
534+
"keywords"
535+
"not"
536+
537+
rule
538+
head
539+
ref
540+
implicit_body
541+
true
542+
body
543+
expr index=0
544+
not
545+
body
546+
expr index=0
547+
ref
548+
equal
549+
call
550+
ref
551+
plus
552+
ref
553+
input
554+
"x"
555+
2
556+
42
557+
rule
558+
head
559+
ref
560+
explicit_body
561+
true
562+
body
563+
expr index=0
564+
not
565+
body
566+
expr index=0
567+
ref
568+
assign
569+
x
570+
ref
571+
input
572+
"x"
573+
expr index=1
574+
ref
575+
assign
576+
y
577+
2
578+
expr index=2
579+
ref
580+
assign
581+
z
582+
call
583+
ref
584+
plus
585+
x
586+
y
587+
expr index=3
588+
ref
589+
equal
590+
z
591+
42
592+
`,
593+
},
594+
}
595+
596+
files := map[string]string{
597+
"x.rego": `package test
598+
599+
import future.keywords.not
600+
601+
implicit_body if {
602+
not input.x + 2 == 42
603+
}
604+
605+
explicit_body if {
606+
not {
607+
x := input.x
608+
y := 2
609+
z := x + y
610+
z == 42
611+
}
612+
}
613+
`,
614+
}
615+
616+
for _, tc := range cases {
617+
t.Run(tc.format, func(t *testing.T) {
618+
errc, stdout, stderr, _ := testParse(t, files, &parseParams{
619+
format: formats.Flag(tc.format),
620+
})
621+
if errc != 0 {
622+
t.Fatalf("Expected exit code 0, got %v", errc)
623+
}
624+
if len(stderr) > 0 {
625+
t.Fatalf("Expected no stderr output, got:\n%s\n", string(stderr))
626+
}
627+
628+
if diff := cmp.Diff(tc.exp, string(stdout)); diff != "" {
629+
t.Errorf("unexpected result (-want, +got):\n%s", diff)
630+
}
631+
})
632+
}
633+
}
634+
261635
func TestParseRefsJSONOutput(t *testing.T) {
262636

263637
files := map[string]string{

v1/ast/json/json.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ type NodeToggle struct {
5454
With bool
5555
Annotations bool
5656
AnnotationsRef bool
57+
Not bool
5758
}
5859

5960
// configuredJSONOptions synchronizes access to the global JSON options

0 commit comments

Comments
 (0)