1// Copyright (C) 2020 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package sdk 16 17import ( 18 "testing" 19 20 "android/soong/android" 21 22 "github.com/google/blueprint/proptools" 23) 24 25func propertySetFixture() interface{} { 26 set := newPropertySet() 27 set.AddProperty("x", "taxi") 28 set.AddPropertyWithTag("y", 1729, "tag_y") 29 subset := set.AddPropertySet("sub") 30 subset.AddPropertyWithTag("x", "taxi", "tag_x") 31 subset.AddProperty("y", 1729) 32 return set 33} 34 35func intPtr(i int) *int { return &i } 36 37type propertyStruct struct { 38 X *string 39 Y *int 40 Unset *bool 41 Sub struct { 42 X *string 43 Y *int 44 Unset *bool 45 } 46} 47 48func propertyStructFixture() interface{} { 49 str := &propertyStruct{} 50 str.X = proptools.StringPtr("taxi") 51 str.Y = intPtr(1729) 52 str.Sub.X = proptools.StringPtr("taxi") 53 str.Sub.Y = intPtr(1729) 54 return str 55} 56 57func checkPropertySetFixture(t *testing.T, val interface{}, hasTags bool) { 58 set := val.(*bpPropertySet) 59 android.AssertDeepEquals(t, "wrong x value", "taxi", set.getValue("x")) 60 android.AssertDeepEquals(t, "wrong y value", 1729, set.getValue("y")) 61 62 subset := set.getValue("sub").(*bpPropertySet) 63 android.AssertDeepEquals(t, "wrong sub.x value", "taxi", subset.getValue("x")) 64 android.AssertDeepEquals(t, "wrong sub.y value", 1729, subset.getValue("y")) 65 66 if hasTags { 67 android.AssertDeepEquals(t, "wrong y tag", "tag_y", set.getTag("y")) 68 android.AssertDeepEquals(t, "wrong sub.x tag", "tag_x", subset.getTag("x")) 69 } else { 70 android.AssertDeepEquals(t, "wrong y tag", nil, set.getTag("y")) 71 android.AssertDeepEquals(t, "wrong sub.x tag", nil, subset.getTag("x")) 72 } 73} 74 75func TestAddPropertySimple(t *testing.T) { 76 t.Parallel() 77 set := newPropertySet() 78 for name, val := range map[string]interface{}{ 79 "x": "taxi", 80 "y": 1729, 81 "t": true, 82 "f": false, 83 "arr": []string{"a", "b", "c"}, 84 } { 85 set.AddProperty(name, val) 86 android.AssertDeepEquals(t, "wrong value", val, set.getValue(name)) 87 } 88 android.AssertPanicMessageContains(t, "adding x again should panic", `Property "x" already exists in property set`, 89 func() { set.AddProperty("x", "taxi") }) 90 android.AssertPanicMessageContains(t, "adding arr again should panic", `Property "arr" already exists in property set`, 91 func() { set.AddProperty("arr", []string{"d"}) }) 92} 93 94func TestAddPropertySubset(t *testing.T) { 95 t.Parallel() 96 getFixtureMap := map[string]func() interface{}{ 97 "property set": propertySetFixture, 98 "property struct": propertyStructFixture, 99 } 100 101 t.Run("add new subset", func(t *testing.T) { 102 t.Parallel() 103 for name, getFixture := range getFixtureMap { 104 t.Run(name, func(t *testing.T) { 105 t.Parallel() 106 set := propertySetFixture().(*bpPropertySet) 107 set.AddProperty("new", getFixture()) 108 checkPropertySetFixture(t, set, true) 109 checkPropertySetFixture(t, set.getValue("new"), name == "property set") 110 }) 111 } 112 }) 113 114 t.Run("merge existing subset", func(t *testing.T) { 115 t.Parallel() 116 for name, getFixture := range getFixtureMap { 117 t.Run(name, func(t *testing.T) { 118 t.Parallel() 119 set := newPropertySet() 120 subset := set.AddPropertySet("sub") 121 subset.AddProperty("flag", false) 122 subset.AddPropertySet("sub") 123 set.AddProperty("sub", getFixture()) 124 merged := set.getValue("sub").(*bpPropertySet) 125 android.AssertDeepEquals(t, "wrong flag value", false, merged.getValue("flag")) 126 checkPropertySetFixture(t, merged, name == "property set") 127 }) 128 } 129 }) 130 131 t.Run("add conflicting subset", func(t *testing.T) { 132 t.Parallel() 133 set := propertySetFixture().(*bpPropertySet) 134 android.AssertPanicMessageContains(t, "adding x again should panic", `Property "x" already exists in property set`, 135 func() { set.AddProperty("x", propertySetFixture()) }) 136 }) 137 138 t.Run("add non-pointer struct", func(t *testing.T) { 139 t.Parallel() 140 set := propertySetFixture().(*bpPropertySet) 141 str := propertyStructFixture().(*propertyStruct) 142 android.AssertPanicMessageContains(t, "adding a non-pointer struct should panic", "Value is a struct, not a pointer to one:", 143 func() { set.AddProperty("new", *str) }) 144 }) 145} 146 147func TestAddPropertySetNew(t *testing.T) { 148 t.Parallel() 149 set := newPropertySet() 150 subset := set.AddPropertySet("sub") 151 subset.AddProperty("new", "d^^b") 152 android.AssertDeepEquals(t, "wrong sub.new value", "d^^b", set.getValue("sub").(*bpPropertySet).getValue("new")) 153} 154 155func TestAddPropertySetExisting(t *testing.T) { 156 t.Parallel() 157 set := propertySetFixture().(*bpPropertySet) 158 subset := set.AddPropertySet("sub") 159 subset.AddProperty("new", "d^^b") 160 android.AssertDeepEquals(t, "wrong sub.new value", "d^^b", set.getValue("sub").(*bpPropertySet).getValue("new")) 161} 162 163type removeFredTransformation struct { 164 identityTransformation 165} 166 167func (t removeFredTransformation) transformProperty(name string, value interface{}, tag android.BpPropertyTag) (interface{}, android.BpPropertyTag) { 168 if name == "fred" { 169 return nil, nil 170 } 171 return value, tag 172} 173 174func (t removeFredTransformation) transformPropertySetBeforeContents(name string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag) { 175 if name == "fred" { 176 return nil, nil 177 } 178 return propertySet, tag 179} 180 181func (t removeFredTransformation) transformPropertySetAfterContents(name string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag) { 182 if len(propertySet.properties) == 0 { 183 return nil, nil 184 } 185 return propertySet, tag 186} 187 188func TestTransformRemoveProperty(t *testing.T) { 189 t.Parallel() 190 set := newPropertySet() 191 set.AddProperty("name", "name") 192 set.AddProperty("fred", "12") 193 194 set.transformContents(removeFredTransformation{}) 195 196 contents := &generatedContents{} 197 outputPropertySet(contents, set) 198 android.AssertTrimmedStringEquals(t, "removing property failed", "name: \"name\",\n", contents.content.String()) 199} 200 201func TestTransformRemovePropertySet(t *testing.T) { 202 t.Parallel() 203 set := newPropertySet() 204 set.AddProperty("name", "name") 205 set.AddPropertySet("fred") 206 207 set.transformContents(removeFredTransformation{}) 208 209 contents := &generatedContents{} 210 outputPropertySet(contents, set) 211 android.AssertTrimmedStringEquals(t, "removing property set failed", "name: \"name\",\n", contents.content.String()) 212} 213