Merge remote-tracking branch 'upstream/master' into master
* upstream/master:
Skip mutated struct properties in bpdoc.
Test: TreeHugger
Change-Id: Ic0f28e81975cf353f487c78ca56d0a098acd0883
diff --git a/Blueprints b/Blueprints
index 35e4190..d58169e 100644
--- a/Blueprints
+++ b/Blueprints
@@ -125,6 +125,8 @@
"bootstrap/bpdoc/reader.go",
],
testSrcs: [
+ "bootstrap/bpdoc/bpdoc_test.go",
+ "bootstrap/bpdoc/properties_test.go",
"bootstrap/bpdoc/reader_test.go",
],
}
diff --git a/bootstrap/bpdoc/bpdoc.go b/bootstrap/bpdoc/bpdoc.go
index 8ce41cf..4acfc5d 100644
--- a/bootstrap/bpdoc/bpdoc.go
+++ b/bootstrap/bpdoc/bpdoc.go
@@ -173,6 +173,9 @@
// The field is not exported so just skip it.
continue
}
+ if proptools.HasTag(field, "blueprint", "mutated") {
+ continue
+ }
fieldValue := structValue.Field(i)
diff --git a/bootstrap/bpdoc/bpdoc_test.go b/bootstrap/bpdoc/bpdoc_test.go
new file mode 100644
index 0000000..687d97b
--- /dev/null
+++ b/bootstrap/bpdoc/bpdoc_test.go
@@ -0,0 +1,46 @@
+package bpdoc
+
+import (
+ "reflect"
+ "testing"
+)
+
+type parentProps struct {
+ A string
+
+ Child *childProps
+
+ Mutated *mutatedProps `blueprint:"mutated"`
+}
+
+type childProps struct {
+ B int
+
+ Child *grandchildProps
+}
+
+type grandchildProps struct {
+ C bool
+}
+
+type mutatedProps struct {
+ D int
+}
+
+func TestNestedPropertyStructs(t *testing.T) {
+ parent := parentProps{Child: &childProps{Child: &grandchildProps{}}, Mutated: &mutatedProps{}}
+
+ allStructs := nestedPropertyStructs(reflect.ValueOf(parent))
+
+ // mutated shouldn't be found because it's a mutated property.
+ expected := []string{"child", "child.child"}
+ if len(allStructs) != len(expected) {
+ t.Errorf("expected %d structs, got %d, all entries: %q",
+ len(expected), len(allStructs), allStructs)
+ }
+ for _, e := range expected {
+ if _, ok := allStructs[e]; !ok {
+ t.Errorf("missing entry %q, all entries: %q", e, allStructs)
+ }
+ }
+}
diff --git a/bootstrap/bpdoc/properties.go b/bootstrap/bpdoc/properties.go
index 23b1ffd..9256d8e 100644
--- a/bootstrap/bpdoc/properties.go
+++ b/bootstrap/bpdoc/properties.go
@@ -250,17 +250,23 @@
// len(props) times to this slice will overwrite the original slice contents
filtered := (*props)[:0]
for _, x := range *props {
- tag := x.Tag.Get(key)
- for _, entry := range strings.Split(tag, ",") {
- if (entry == value) == !exclude {
- filtered = append(filtered, x)
- }
+ if hasTag(x.Tag, key, value) == !exclude {
+ filtered = append(filtered, x)
}
}
*props = filtered
}
+func hasTag(tag reflect.StructTag, key, value string) bool {
+ for _, entry := range strings.Split(tag.Get(key), ",") {
+ if entry == value {
+ return true
+ }
+ }
+ return false
+}
+
func formatText(text string) template.HTML {
var html template.HTML
lines := strings.Split(text, "\n")
diff --git a/bootstrap/bpdoc/properties_test.go b/bootstrap/bpdoc/properties_test.go
new file mode 100644
index 0000000..4045cb1
--- /dev/null
+++ b/bootstrap/bpdoc/properties_test.go
@@ -0,0 +1,58 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package bpdoc
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestExcludeByTag(t *testing.T) {
+ r := NewReader(pkgFiles)
+ ps, err := r.PropertyStruct(pkgPath, "tagTestProps", reflect.ValueOf(tagTestProps{}))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ ps.ExcludeByTag("tag1", "a")
+
+ expected := []string{"c"}
+ actual := []string{}
+ for _, p := range ps.Properties {
+ actual = append(actual, p.Name)
+ }
+ if !reflect.DeepEqual(expected, actual) {
+ t.Errorf("unexpected ExcludeByTag result, expected: %q, actual: %q", expected, actual)
+ }
+}
+
+func TestIncludeByTag(t *testing.T) {
+ r := NewReader(pkgFiles)
+ ps, err := r.PropertyStruct(pkgPath, "tagTestProps", reflect.ValueOf(tagTestProps{A: "B"}))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ ps.IncludeByTag("tag1", "c")
+
+ expected := []string{"b", "c"}
+ actual := []string{}
+ for _, p := range ps.Properties {
+ actual = append(actual, p.Name)
+ }
+ if !reflect.DeepEqual(expected, actual) {
+ t.Errorf("unexpected IncludeByTag result, expected: %q, actual: %q", expected, actual)
+ }
+}
diff --git a/bootstrap/bpdoc/reader_test.go b/bootstrap/bpdoc/reader_test.go
index b8ff109..0d608b3 100644
--- a/bootstrap/bpdoc/reader_test.go
+++ b/bootstrap/bpdoc/reader_test.go
@@ -34,6 +34,13 @@
A string
}
+// for properties_test.go
+type tagTestProps struct {
+ A string `tag1:"a,b" tag2:"c"`
+ B string `tag1:"a,c"`
+ C string `tag1:"b,c"`
+}
+
var pkgPath string
var pkgFiles map[string][]string