xref: /aosp_15_r20/build/soong/etc/install_symlink_test.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1// Copyright 2023 Google Inc. All rights reserved.
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 etc
16
17import (
18	"android/soong/android"
19	"strings"
20	"testing"
21)
22
23var prepareForInstallSymlinkTest = android.GroupFixturePreparers(
24	android.PrepareForTestWithArchMutator,
25	android.FixtureRegisterWithContext(RegisterInstallSymlinkBuildComponents),
26)
27
28func TestInstallSymlinkBasic(t *testing.T) {
29	result := prepareForInstallSymlinkTest.RunTestWithBp(t, `
30		install_symlink {
31			name: "foo",
32			installed_location: "bin/foo",
33			symlink_target: "/system/system_ext/bin/foo",
34		}
35	`)
36
37	foo_variants := result.ModuleVariantsForTests("foo")
38	if len(foo_variants) != 1 {
39		t.Fatalf("expected 1 variant, got %#v", foo_variants)
40	}
41
42	foo := result.ModuleForTests("foo", "android_common").Module()
43	androidMkEntries := android.AndroidMkEntriesForTest(t, result.TestContext, foo)
44	if len(androidMkEntries) != 1 {
45		t.Fatalf("expected 1 androidmkentry, got %d", len(androidMkEntries))
46	}
47
48	symlinks := androidMkEntries[0].EntryMap["LOCAL_SOONG_INSTALL_SYMLINKS"]
49	if len(symlinks) != 1 {
50		t.Fatalf("Expected 1 symlink, got %d", len(symlinks))
51	}
52
53	if !strings.HasSuffix(symlinks[0], "system/bin/foo") {
54		t.Fatalf("Expected symlink install path to end in system/bin/foo, got: %s", symlinks[0])
55	}
56}
57
58func TestInstallSymlinkToRecovery(t *testing.T) {
59	result := prepareForInstallSymlinkTest.RunTestWithBp(t, `
60		install_symlink {
61			name: "foo",
62			installed_location: "bin/foo",
63			symlink_target: "/system/system_ext/bin/foo",
64			recovery: true,
65		}
66	`)
67
68	foo_variants := result.ModuleVariantsForTests("foo")
69	if len(foo_variants) != 1 {
70		t.Fatalf("expected 1 variant, got %#v", foo_variants)
71	}
72
73	foo := result.ModuleForTests("foo", "android_common").Module()
74	androidMkEntries := android.AndroidMkEntriesForTest(t, result.TestContext, foo)
75	if len(androidMkEntries) != 1 {
76		t.Fatalf("expected 1 androidmkentry, got %d", len(androidMkEntries))
77	}
78
79	symlinks := androidMkEntries[0].EntryMap["LOCAL_SOONG_INSTALL_SYMLINKS"]
80	if len(symlinks) != 1 {
81		t.Fatalf("Expected 1 symlink, got %d", len(symlinks))
82	}
83
84	if !strings.HasSuffix(symlinks[0], "recovery/root/system/bin/foo") {
85		t.Fatalf("Expected symlink install path to end in recovery/root/system/bin/foo, got: %s", symlinks[0])
86	}
87}
88
89func TestErrorOnNonCleanTarget(t *testing.T) {
90	prepareForInstallSymlinkTest.
91		ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern("Should be a clean filepath")).
92		RunTestWithBp(t, `
93		install_symlink {
94			name: "foo",
95			installed_location: "bin/foo",
96			symlink_target: "/system/system_ext/../bin/foo",
97		}
98	`)
99}
100
101func TestErrorOnNonCleanInstalledLocation(t *testing.T) {
102	prepareForInstallSymlinkTest.
103		ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern("Should be a clean filepath")).
104		RunTestWithBp(t, `
105		install_symlink {
106			name: "foo",
107			installed_location: "bin/../foo",
108			symlink_target: "/system/system_ext/bin/foo",
109		}
110	`)
111}
112
113func TestErrorOnInstalledPathStartingWithDotDot(t *testing.T) {
114	prepareForInstallSymlinkTest.
115		ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern("Should not start with / or \\.\\./")).
116		RunTestWithBp(t, `
117		install_symlink {
118			name: "foo",
119			installed_location: "../bin/foo",
120			symlink_target: "/system/system_ext/bin/foo",
121		}
122	`)
123}
124
125func TestErrorOnInstalledPathStartingWithSlash(t *testing.T) {
126	prepareForInstallSymlinkTest.
127		ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern("Should not start with / or \\.\\./")).
128		RunTestWithBp(t, `
129		install_symlink {
130			name: "foo",
131			installed_location: "/bin/foo",
132			symlink_target: "/system/system_ext/bin/foo",
133		}
134	`)
135}
136
137var prepareForInstallSymlinkHostTest = android.GroupFixturePreparers(
138	android.PrepareForTestWithAndroidBuildComponents,
139	android.FixtureRegisterWithContext(RegisterInstallSymlinkBuildComponents),
140)
141
142func TestInstallSymlinkHostBasic(t *testing.T) {
143	result := prepareForInstallSymlinkHostTest.RunTestWithBp(t, `
144		install_symlink_host {
145			name: "foo",
146			installed_location: "bin/foo",
147			symlink_target: "aa/bb/cc",
148		}
149	`)
150
151	buildOS := result.Config.BuildOS.String()
152	foo := result.ModuleForTests("foo", buildOS+"_common").Module()
153
154	androidMkEntries := android.AndroidMkEntriesForTest(t, result.TestContext, foo)
155	if len(androidMkEntries) != 1 {
156		t.Fatalf("expected 1 androidmkentry, got %d", len(androidMkEntries))
157	}
158
159	symlinks := androidMkEntries[0].EntryMap["LOCAL_SOONG_INSTALL_SYMLINKS"]
160	if len(symlinks) != 1 {
161		t.Fatalf("Expected 1 symlink, got %d", len(symlinks))
162	}
163
164	if !strings.HasSuffix(symlinks[0], "bin/foo") {
165		t.Fatalf("Expected symlink install path to end in bin/foo, got: %s", symlinks[0])
166	}
167
168	if !strings.Contains(symlinks[0], "host") {
169		t.Fatalf("Expected symlink install path to contain `host`, got: %s", symlinks[0])
170	}
171}
172