| Paul Duffin | 1812294 | 2021-08-24 19:01:25 +0100 | [diff] [blame] | 1 | // Copyright (C) 2021 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 |  | 
|  | 15 | package sdk | 
|  | 16 |  | 
|  | 17 | import ( | 
| Paul Duffin | 545c592 | 2022-01-27 16:51:51 +0000 | [diff] [blame] | 18 | "encoding/json" | 
| Paul Duffin | 1812294 | 2021-08-24 19:01:25 +0100 | [diff] [blame] | 19 | "fmt" | 
|  | 20 | "testing" | 
|  | 21 |  | 
|  | 22 | "android/soong/android" | 
|  | 23 | ) | 
|  | 24 |  | 
|  | 25 | // Tests for build_release.go | 
|  | 26 |  | 
|  | 27 | var ( | 
|  | 28 | // Some additional test specific releases that are added after the currently supported ones and | 
|  | 29 | // so are treated as being for future releases. | 
|  | 30 | buildReleaseFuture1 = initBuildRelease("F1") | 
|  | 31 | buildReleaseFuture2 = initBuildRelease("F2") | 
|  | 32 | ) | 
|  | 33 |  | 
|  | 34 | func TestNameToRelease(t *testing.T) { | 
|  | 35 | t.Run("single release", func(t *testing.T) { | 
|  | 36 | release, err := nameToRelease("S") | 
|  | 37 | android.AssertDeepEquals(t, "errors", nil, err) | 
|  | 38 | android.AssertDeepEquals(t, "release", buildReleaseS, release) | 
|  | 39 | }) | 
|  | 40 | t.Run("invalid release", func(t *testing.T) { | 
|  | 41 | release, err := nameToRelease("A") | 
|  | 42 | android.AssertDeepEquals(t, "release", (*buildRelease)(nil), release) | 
|  | 43 | // Uses a wildcard in the error message to allow for additional build releases to be added to | 
|  | 44 | // the supported set without breaking this test. | 
| Paul Duffin | 03d2cef | 2022-09-29 17:37:49 +0100 | [diff] [blame] | 45 | android.FailIfNoMatchingErrors(t, `unknown release "A", expected one of \[S,Tiramisu,UpsideDownCake,F1,F2,current\]`, []error{err}) | 
| Paul Duffin | 1812294 | 2021-08-24 19:01:25 +0100 | [diff] [blame] | 46 | }) | 
|  | 47 | } | 
|  | 48 |  | 
|  | 49 | func TestParseBuildReleaseSet(t *testing.T) { | 
|  | 50 | t.Run("single release", func(t *testing.T) { | 
|  | 51 | set, err := parseBuildReleaseSet("S") | 
|  | 52 | android.AssertDeepEquals(t, "errors", nil, err) | 
|  | 53 | android.AssertStringEquals(t, "set", "[S]", set.String()) | 
|  | 54 | }) | 
|  | 55 | t.Run("open range", func(t *testing.T) { | 
|  | 56 | set, err := parseBuildReleaseSet("F1+") | 
|  | 57 | android.AssertDeepEquals(t, "errors", nil, err) | 
| Paul Duffin | 42a49f1 | 2022-08-17 22:09:55 +0000 | [diff] [blame] | 58 | android.AssertStringEquals(t, "set", "[F1,F2,current]", set.String()) | 
| Paul Duffin | 1812294 | 2021-08-24 19:01:25 +0100 | [diff] [blame] | 59 | }) | 
|  | 60 | t.Run("closed range", func(t *testing.T) { | 
|  | 61 | set, err := parseBuildReleaseSet("S-F1") | 
|  | 62 | android.AssertDeepEquals(t, "errors", nil, err) | 
| Paul Duffin | 03d2cef | 2022-09-29 17:37:49 +0100 | [diff] [blame] | 63 | android.AssertStringEquals(t, "set", "[S,Tiramisu,UpsideDownCake,F1]", set.String()) | 
| Paul Duffin | 1812294 | 2021-08-24 19:01:25 +0100 | [diff] [blame] | 64 | }) | 
|  | 65 | invalidAReleaseMessage := `unknown release "A", expected one of ` + allBuildReleaseSet.String() | 
|  | 66 | t.Run("invalid release", func(t *testing.T) { | 
|  | 67 | set, err := parseBuildReleaseSet("A") | 
|  | 68 | android.AssertDeepEquals(t, "set", (*buildReleaseSet)(nil), set) | 
|  | 69 | android.AssertStringDoesContain(t, "errors", fmt.Sprint(err), invalidAReleaseMessage) | 
|  | 70 | }) | 
|  | 71 | t.Run("invalid release in open range", func(t *testing.T) { | 
|  | 72 | set, err := parseBuildReleaseSet("A+") | 
|  | 73 | android.AssertDeepEquals(t, "set", (*buildReleaseSet)(nil), set) | 
|  | 74 | android.AssertStringDoesContain(t, "errors", fmt.Sprint(err), invalidAReleaseMessage) | 
|  | 75 | }) | 
|  | 76 | t.Run("invalid release in closed range start", func(t *testing.T) { | 
|  | 77 | set, err := parseBuildReleaseSet("A-S") | 
|  | 78 | android.AssertDeepEquals(t, "set", (*buildReleaseSet)(nil), set) | 
|  | 79 | android.AssertStringDoesContain(t, "errors", fmt.Sprint(err), invalidAReleaseMessage) | 
|  | 80 | }) | 
|  | 81 | t.Run("invalid release in closed range end", func(t *testing.T) { | 
| Paul Duffin | e7babdb | 2022-02-10 13:06:54 +0000 | [diff] [blame] | 82 | set, err := parseBuildReleaseSet("Tiramisu-A") | 
| Paul Duffin | 1812294 | 2021-08-24 19:01:25 +0100 | [diff] [blame] | 83 | android.AssertDeepEquals(t, "set", (*buildReleaseSet)(nil), set) | 
|  | 84 | android.AssertStringDoesContain(t, "errors", fmt.Sprint(err), invalidAReleaseMessage) | 
|  | 85 | }) | 
|  | 86 | t.Run("invalid closed range reversed", func(t *testing.T) { | 
|  | 87 | set, err := parseBuildReleaseSet("F1-S") | 
|  | 88 | android.AssertDeepEquals(t, "set", (*buildReleaseSet)(nil), set) | 
|  | 89 | android.AssertStringDoesContain(t, "errors", fmt.Sprint(err), `invalid closed range, start release "F1" is later than end release "S"`) | 
|  | 90 | }) | 
|  | 91 | } | 
|  | 92 |  | 
|  | 93 | func TestBuildReleaseSetContains(t *testing.T) { | 
|  | 94 | t.Run("contains", func(t *testing.T) { | 
|  | 95 | set, _ := parseBuildReleaseSet("F1-F2") | 
|  | 96 | android.AssertBoolEquals(t, "set contains F1", true, set.contains(buildReleaseFuture1)) | 
|  | 97 | android.AssertBoolEquals(t, "set does not contain S", false, set.contains(buildReleaseS)) | 
|  | 98 | android.AssertBoolEquals(t, "set contains F2", true, set.contains(buildReleaseFuture2)) | 
|  | 99 | android.AssertBoolEquals(t, "set does not contain T", false, set.contains(buildReleaseT)) | 
|  | 100 | }) | 
|  | 101 | } | 
| Paul Duffin | 0c3acbf | 2021-08-24 19:01:25 +0100 | [diff] [blame] | 102 |  | 
|  | 103 | func TestPropertyPrunerInvalidTag(t *testing.T) { | 
|  | 104 | type brokenStruct struct { | 
|  | 105 | Broken string `supported_build_releases:"A"` | 
|  | 106 | } | 
|  | 107 | type containingStruct struct { | 
|  | 108 | Nested brokenStruct | 
|  | 109 | } | 
|  | 110 |  | 
|  | 111 | t.Run("broken struct", func(t *testing.T) { | 
|  | 112 | android.AssertPanicMessageContains(t, "error", "invalid `supported_build_releases` tag on Broken of *sdk.brokenStruct: unknown release \"A\"", func() { | 
|  | 113 | newPropertyPrunerByBuildRelease(&brokenStruct{}, buildReleaseS) | 
|  | 114 | }) | 
|  | 115 | }) | 
|  | 116 |  | 
|  | 117 | t.Run("nested broken struct", func(t *testing.T) { | 
|  | 118 | android.AssertPanicMessageContains(t, "error", "invalid `supported_build_releases` tag on Nested.Broken of *sdk.containingStruct: unknown release \"A\"", func() { | 
|  | 119 | newPropertyPrunerByBuildRelease(&containingStruct{}, buildReleaseS) | 
|  | 120 | }) | 
|  | 121 | }) | 
|  | 122 | } | 
|  | 123 |  | 
|  | 124 | func TestPropertyPrunerByBuildRelease(t *testing.T) { | 
|  | 125 | type nested struct { | 
|  | 126 | F1_only string `supported_build_releases:"F1"` | 
|  | 127 | } | 
|  | 128 |  | 
| Paul Duffin | 106a3a4 | 2022-01-27 16:39:06 +0000 | [diff] [blame] | 129 | type mapped struct { | 
|  | 130 | Default string | 
| Paul Duffin | e7babdb | 2022-02-10 13:06:54 +0000 | [diff] [blame] | 131 | T_only  string `supported_build_releases:"Tiramisu"` | 
| Paul Duffin | 106a3a4 | 2022-01-27 16:39:06 +0000 | [diff] [blame] | 132 | } | 
|  | 133 |  | 
| Paul Duffin | 0c3acbf | 2021-08-24 19:01:25 +0100 | [diff] [blame] | 134 | type testBuildReleasePruner struct { | 
|  | 135 | Default      string | 
| Paul Duffin | e7babdb | 2022-02-10 13:06:54 +0000 | [diff] [blame] | 136 | S_and_T_only string `supported_build_releases:"S-Tiramisu"` | 
|  | 137 | T_later      string `supported_build_releases:"Tiramisu+"` | 
| Paul Duffin | 0c3acbf | 2021-08-24 19:01:25 +0100 | [diff] [blame] | 138 | Nested       nested | 
| Paul Duffin | 106a3a4 | 2022-01-27 16:39:06 +0000 | [diff] [blame] | 139 | Mapped       map[string]*mapped | 
| Paul Duffin | 0c3acbf | 2021-08-24 19:01:25 +0100 | [diff] [blame] | 140 | } | 
|  | 141 |  | 
| Paul Duffin | 545c592 | 2022-01-27 16:51:51 +0000 | [diff] [blame] | 142 | inputFactory := func() testBuildReleasePruner { | 
|  | 143 | return testBuildReleasePruner{ | 
|  | 144 | Default:      "Default", | 
|  | 145 | S_and_T_only: "S_and_T_only", | 
|  | 146 | T_later:      "T_later", | 
|  | 147 | Nested: nested{ | 
|  | 148 | F1_only: "F1_only", | 
|  | 149 | }, | 
| Paul Duffin | 106a3a4 | 2022-01-27 16:39:06 +0000 | [diff] [blame] | 150 | Mapped: map[string]*mapped{ | 
|  | 151 | "one": { | 
|  | 152 | Default: "one-default", | 
|  | 153 | T_only:  "one-t-only", | 
|  | 154 | }, | 
|  | 155 | "two": { | 
|  | 156 | Default: "two-default", | 
|  | 157 | T_only:  "two-t-only", | 
|  | 158 | }, | 
|  | 159 | }, | 
| Paul Duffin | 545c592 | 2022-01-27 16:51:51 +0000 | [diff] [blame] | 160 | } | 
|  | 161 | } | 
|  | 162 |  | 
|  | 163 | marshal := func(t interface{}) string { | 
|  | 164 | bytes, err := json.MarshalIndent(t, "", "  ") | 
|  | 165 | if err != nil { | 
|  | 166 | panic(err) | 
|  | 167 | } | 
|  | 168 | return string(bytes) | 
|  | 169 | } | 
|  | 170 |  | 
|  | 171 | assertJsonEquals := func(t *testing.T, expected, actual interface{}) { | 
|  | 172 | t.Helper() | 
|  | 173 | expectedJson := marshal(expected) | 
|  | 174 | actualJson := marshal(actual) | 
|  | 175 | if actualJson != expectedJson { | 
|  | 176 | t.Errorf("test struct: expected:\n%s\n got:\n%s", expectedJson, actualJson) | 
|  | 177 | } | 
| Paul Duffin | 0c3acbf | 2021-08-24 19:01:25 +0100 | [diff] [blame] | 178 | } | 
|  | 179 |  | 
|  | 180 | t.Run("target S", func(t *testing.T) { | 
| Paul Duffin | 545c592 | 2022-01-27 16:51:51 +0000 | [diff] [blame] | 181 | testStruct := inputFactory() | 
| Paul Duffin | 0c3acbf | 2021-08-24 19:01:25 +0100 | [diff] [blame] | 182 | pruner := newPropertyPrunerByBuildRelease(&testStruct, buildReleaseS) | 
|  | 183 | pruner.pruneProperties(&testStruct) | 
|  | 184 |  | 
| Paul Duffin | 545c592 | 2022-01-27 16:51:51 +0000 | [diff] [blame] | 185 | expected := inputFactory() | 
| Paul Duffin | 0c3acbf | 2021-08-24 19:01:25 +0100 | [diff] [blame] | 186 | expected.T_later = "" | 
|  | 187 | expected.Nested.F1_only = "" | 
| Paul Duffin | 106a3a4 | 2022-01-27 16:39:06 +0000 | [diff] [blame] | 188 | expected.Mapped["one"].T_only = "" | 
|  | 189 | expected.Mapped["two"].T_only = "" | 
| Paul Duffin | 545c592 | 2022-01-27 16:51:51 +0000 | [diff] [blame] | 190 | assertJsonEquals(t, expected, testStruct) | 
| Paul Duffin | 0c3acbf | 2021-08-24 19:01:25 +0100 | [diff] [blame] | 191 | }) | 
|  | 192 |  | 
|  | 193 | t.Run("target T", func(t *testing.T) { | 
| Paul Duffin | 545c592 | 2022-01-27 16:51:51 +0000 | [diff] [blame] | 194 | testStruct := inputFactory() | 
| Paul Duffin | 0c3acbf | 2021-08-24 19:01:25 +0100 | [diff] [blame] | 195 | pruner := newPropertyPrunerByBuildRelease(&testStruct, buildReleaseT) | 
|  | 196 | pruner.pruneProperties(&testStruct) | 
|  | 197 |  | 
| Paul Duffin | 545c592 | 2022-01-27 16:51:51 +0000 | [diff] [blame] | 198 | expected := inputFactory() | 
| Paul Duffin | 0c3acbf | 2021-08-24 19:01:25 +0100 | [diff] [blame] | 199 | expected.Nested.F1_only = "" | 
| Paul Duffin | 545c592 | 2022-01-27 16:51:51 +0000 | [diff] [blame] | 200 | assertJsonEquals(t, expected, testStruct) | 
| Paul Duffin | 0c3acbf | 2021-08-24 19:01:25 +0100 | [diff] [blame] | 201 | }) | 
|  | 202 |  | 
|  | 203 | t.Run("target F1", func(t *testing.T) { | 
| Paul Duffin | 545c592 | 2022-01-27 16:51:51 +0000 | [diff] [blame] | 204 | testStruct := inputFactory() | 
| Paul Duffin | 0c3acbf | 2021-08-24 19:01:25 +0100 | [diff] [blame] | 205 | pruner := newPropertyPrunerByBuildRelease(&testStruct, buildReleaseFuture1) | 
|  | 206 | pruner.pruneProperties(&testStruct) | 
|  | 207 |  | 
| Paul Duffin | 545c592 | 2022-01-27 16:51:51 +0000 | [diff] [blame] | 208 | expected := inputFactory() | 
| Paul Duffin | 0c3acbf | 2021-08-24 19:01:25 +0100 | [diff] [blame] | 209 | expected.S_and_T_only = "" | 
| Paul Duffin | 106a3a4 | 2022-01-27 16:39:06 +0000 | [diff] [blame] | 210 | expected.Mapped["one"].T_only = "" | 
|  | 211 | expected.Mapped["two"].T_only = "" | 
| Paul Duffin | 545c592 | 2022-01-27 16:51:51 +0000 | [diff] [blame] | 212 | assertJsonEquals(t, expected, testStruct) | 
| Paul Duffin | 0c3acbf | 2021-08-24 19:01:25 +0100 | [diff] [blame] | 213 | }) | 
|  | 214 |  | 
|  | 215 | t.Run("target F2", func(t *testing.T) { | 
| Paul Duffin | 545c592 | 2022-01-27 16:51:51 +0000 | [diff] [blame] | 216 | testStruct := inputFactory() | 
| Paul Duffin | 0c3acbf | 2021-08-24 19:01:25 +0100 | [diff] [blame] | 217 | pruner := newPropertyPrunerByBuildRelease(&testStruct, buildReleaseFuture2) | 
|  | 218 | pruner.pruneProperties(&testStruct) | 
|  | 219 |  | 
| Paul Duffin | 545c592 | 2022-01-27 16:51:51 +0000 | [diff] [blame] | 220 | expected := inputFactory() | 
| Paul Duffin | 0c3acbf | 2021-08-24 19:01:25 +0100 | [diff] [blame] | 221 | expected.S_and_T_only = "" | 
|  | 222 | expected.Nested.F1_only = "" | 
| Paul Duffin | 106a3a4 | 2022-01-27 16:39:06 +0000 | [diff] [blame] | 223 | expected.Mapped["one"].T_only = "" | 
|  | 224 | expected.Mapped["two"].T_only = "" | 
| Paul Duffin | 545c592 | 2022-01-27 16:51:51 +0000 | [diff] [blame] | 225 | assertJsonEquals(t, expected, testStruct) | 
| Paul Duffin | 0c3acbf | 2021-08-24 19:01:25 +0100 | [diff] [blame] | 226 | }) | 
|  | 227 | } |