• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2018 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 dexpreopt
16
17import (
18	"android/soong/android"
19	"reflect"
20	"strings"
21	"testing"
22)
23
24func testModuleConfig(ctx android.PathContext) ModuleConfig {
25	return ModuleConfig{
26		Name:                            "test",
27		DexLocation:                     "/system/app/test/test.apk",
28		BuildPath:                       android.PathForOutput(ctx, "test/test.apk"),
29		DexPath:                         android.PathForOutput(ctx, "test/dex/test.jar"),
30		UncompressedDex:                 false,
31		HasApkLibraries:                 false,
32		PreoptFlags:                     nil,
33		ProfileClassListing:             android.OptionalPath{},
34		ProfileIsTextListing:            false,
35		EnforceUsesLibraries:            false,
36		OptionalUsesLibraries:           nil,
37		UsesLibraries:                   nil,
38		LibraryPaths:                    nil,
39		Archs:                           []android.ArchType{android.Arm},
40		DexPreoptImages:                 android.Paths{android.PathForTesting("system/framework/arm/boot.art")},
41		PreoptBootClassPathDexFiles:     nil,
42		PreoptBootClassPathDexLocations: nil,
43		PreoptExtractedApk:              false,
44		NoCreateAppImage:                false,
45		ForceCreateAppImage:             false,
46		PresignedPrebuilt:               false,
47		NoStripping:                     false,
48		StripInputPath:                  android.PathForOutput(ctx, "unstripped/test.apk"),
49		StripOutputPath:                 android.PathForOutput(ctx, "stripped/test.apk"),
50	}
51}
52
53func TestDexPreopt(t *testing.T) {
54	ctx := android.PathContextForTesting(android.TestConfig("out", nil), nil)
55	global, module := GlobalConfigForTests(ctx), testModuleConfig(ctx)
56
57	rule, err := GenerateDexpreoptRule(ctx, global, module)
58	if err != nil {
59		t.Fatal(err)
60	}
61
62	wantInstalls := android.RuleBuilderInstalls{
63		{android.PathForOutput(ctx, "test/oat/arm/package.odex"), "/system/app/test/oat/arm/test.odex"},
64		{android.PathForOutput(ctx, "test/oat/arm/package.vdex"), "/system/app/test/oat/arm/test.vdex"},
65	}
66
67	if rule.Installs().String() != wantInstalls.String() {
68		t.Errorf("\nwant installs:\n   %v\ngot:\n   %v", wantInstalls, rule.Installs())
69	}
70}
71
72func TestDexPreoptStrip(t *testing.T) {
73	// Test that we panic if we strip in a configuration where stripping is not allowed.
74	ctx := android.PathContextForTesting(android.TestConfig("out", nil), nil)
75	global, module := GlobalConfigForTests(ctx), testModuleConfig(ctx)
76
77	global.NeverAllowStripping = true
78	module.NoStripping = false
79
80	_, err := GenerateStripRule(global, module)
81	if err == nil {
82		t.Errorf("Expected an error when calling GenerateStripRule on a stripped module")
83	}
84}
85
86func TestDexPreoptSystemOther(t *testing.T) {
87	ctx := android.PathContextForTesting(android.TestConfig("out", nil), nil)
88	global, module := GlobalConfigForTests(ctx), testModuleConfig(ctx)
89
90	global.HasSystemOther = true
91	global.PatternsOnSystemOther = []string{"app/%"}
92
93	rule, err := GenerateDexpreoptRule(ctx, global, module)
94	if err != nil {
95		t.Fatal(err)
96	}
97
98	wantInstalls := android.RuleBuilderInstalls{
99		{android.PathForOutput(ctx, "test/oat/arm/package.odex"), "/system_other/app/test/oat/arm/test.odex"},
100		{android.PathForOutput(ctx, "test/oat/arm/package.vdex"), "/system_other/app/test/oat/arm/test.vdex"},
101	}
102
103	if rule.Installs().String() != wantInstalls.String() {
104		t.Errorf("\nwant installs:\n   %v\ngot:\n   %v", wantInstalls, rule.Installs())
105	}
106}
107
108func TestDexPreoptProfile(t *testing.T) {
109	ctx := android.PathContextForTesting(android.TestConfig("out", nil), nil)
110	global, module := GlobalConfigForTests(ctx), testModuleConfig(ctx)
111
112	module.ProfileClassListing = android.OptionalPathForPath(android.PathForTesting("profile"))
113
114	rule, err := GenerateDexpreoptRule(ctx, global, module)
115	if err != nil {
116		t.Fatal(err)
117	}
118
119	wantInstalls := android.RuleBuilderInstalls{
120		{android.PathForOutput(ctx, "test/profile.prof"), "/system/app/test/test.apk.prof"},
121		{android.PathForOutput(ctx, "test/oat/arm/package.art"), "/system/app/test/oat/arm/test.art"},
122		{android.PathForOutput(ctx, "test/oat/arm/package.odex"), "/system/app/test/oat/arm/test.odex"},
123		{android.PathForOutput(ctx, "test/oat/arm/package.vdex"), "/system/app/test/oat/arm/test.vdex"},
124	}
125
126	if rule.Installs().String() != wantInstalls.String() {
127		t.Errorf("\nwant installs:\n   %v\ngot:\n   %v", wantInstalls, rule.Installs())
128	}
129}
130
131func TestStripDex(t *testing.T) {
132	tests := []struct {
133		name  string
134		setup func(global *GlobalConfig, module *ModuleConfig)
135		strip bool
136	}{
137		{
138			name:  "default strip",
139			setup: func(global *GlobalConfig, module *ModuleConfig) {},
140			strip: true,
141		},
142		{
143			name:  "global no stripping",
144			setup: func(global *GlobalConfig, module *ModuleConfig) { global.DefaultNoStripping = true },
145			strip: false,
146		},
147		{
148			name:  "module no stripping",
149			setup: func(global *GlobalConfig, module *ModuleConfig) { module.NoStripping = true },
150			strip: false,
151		},
152	}
153
154	for _, test := range tests {
155		t.Run(test.name, func(t *testing.T) {
156
157			ctx := android.PathContextForTesting(android.TestConfig("out", nil), nil)
158			global, module := GlobalConfigForTests(ctx), testModuleConfig(ctx)
159
160			test.setup(&global, &module)
161
162			rule, err := GenerateStripRule(global, module)
163			if err != nil {
164				t.Fatal(err)
165			}
166
167			if test.strip {
168				want := `zip2zip -i out/unstripped/test.apk -o out/stripped/test.apk -x "classes*.dex"`
169				if len(rule.Commands()) < 1 || !strings.Contains(rule.Commands()[0], want) {
170					t.Errorf("\nwant commands[0] to have:\n   %v\ngot:\n   %v", want, rule.Commands()[0])
171				}
172			} else {
173				wantCommands := []string{
174					"cp -f out/unstripped/test.apk out/stripped/test.apk",
175				}
176				if !reflect.DeepEqual(rule.Commands(), wantCommands) {
177					t.Errorf("\nwant commands:\n   %v\ngot:\n   %v", wantCommands, rule.Commands())
178				}
179			}
180		})
181	}
182}
183