From 043bf386ac15c6567a5cc0f6e27d87a6d8663531 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Mon, 15 Jul 2024 14:31:15 -0400 Subject: [PATCH] cty: use unmarked val when Transform walks object attrs When descending into an object inside a Transformer, the marks from the outer object should not be applied to the attribute values. This follows the pattern used in other collection types, and ensures marks are stable across multiple transformations. --- cty/marks_test.go | 18 ++++++++++++++++++ cty/walk.go | 2 +- cty/walk_test.go | 23 +++++++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/cty/marks_test.go b/cty/marks_test.go index 848b6386..ec4196ce 100644 --- a/cty/marks_test.go +++ b/cty/marks_test.go @@ -489,3 +489,21 @@ func TestPathValueMarks(t *testing.T) { }) } } + +func TestReapplyMarks(t *testing.T) { + // Re-applying the same marks to an object value should not change the result. + obj := ObjectVal(map[string]Value{ + "nested": ObjectVal(map[string]Value{ + "attr": StringVal("not directly marked"), + }), + }) + + pvm := []PathValueMarks{{Path: GetAttrPath("nested"), Marks: NewValueMarks("mark")}} + + first := obj.MarkWithPaths(pvm) + second := first.MarkWithPaths(pvm) + + if !first.RawEquals(second) { + t.Fatalf("Value changed re-applying marks\n1st: %#v\n2nd: %#v\n", first, second) + } +} diff --git a/cty/walk.go b/cty/walk.go index 87ba32e7..a18af04d 100644 --- a/cty/walk.go +++ b/cty/walk.go @@ -213,7 +213,7 @@ func transform(path Path, val Value, t Transformer) (Value, error) { atys := ty.AttributeTypes() newAVs := make(map[string]Value) for name := range atys { - av := val.GetAttr(name) + av := rawVal.GetAttr(name) path := append(path, GetAttrStep{ Name: name, }) diff --git a/cty/walk_test.go b/cty/walk_test.go index 80a672e2..98d56f12 100644 --- a/cty/walk_test.go +++ b/cty/walk_test.go @@ -261,3 +261,26 @@ func TestTransform(t *testing.T) { t.Fatalf("wrong value\n got: %#v\nwant: %#v", gotVal, wantVal) } } + +func TestTransformMarked(t *testing.T) { + val := ObjectVal(map[string]Value{ + "list": ListVal([]Value{True, True, False}).Mark("mark"), + "set": SetVal([]Value{True, False}).Mark("mark"), + "map": MapVal(map[string]Value{"a": True, "b": False}).Mark("mark"), + "object": ObjectVal(map[string]Value{ + "a": True, + "b": ListVal([]Value{False, False, False}), + }).Mark("mark"), + }) + + // This noop transform should not change any values or marks. + gotVal, err := Transform(val, func(p Path, v Value) (Value, error) { + return v, nil + }) + if err != nil { + t.Fatalf("unexpected error: %s", err) + } + if !gotVal.RawEquals(val) { + t.Fatalf("wrong value\n got: %#v\nwant: %#v", gotVal, val) + } +}