Move sharding functions for reuse
am: 0a2f719bca
Change-Id: I4d1e85ac2fe3fd61f82e4783ce48b42f7a3bbf53
This commit is contained in:
commit
c7503e2fd8
|
@ -304,7 +304,6 @@ bootstrap_go_package {
|
||||||
"java/jdeps_test.go",
|
"java/jdeps_test.go",
|
||||||
"java/kotlin_test.go",
|
"java/kotlin_test.go",
|
||||||
"java/plugin_test.go",
|
"java/plugin_test.go",
|
||||||
"java/robolectric_test.go",
|
|
||||||
"java/sdk_test.go",
|
"java/sdk_test.go",
|
||||||
],
|
],
|
||||||
pluginFor: ["soong_build"],
|
pluginFor: ["soong_build"],
|
||||||
|
|
|
@ -319,3 +319,36 @@ func SplitFileExt(name string) (string, string, string) {
|
||||||
|
|
||||||
return root, suffix, ext
|
return root, suffix, ext
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ShardPaths takes a Paths, and returns a slice of Paths where each one has at most shardSize paths.
|
||||||
|
func ShardPaths(paths Paths, shardSize int) []Paths {
|
||||||
|
if len(paths) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
ret := make([]Paths, 0, (len(paths)+shardSize-1)/shardSize)
|
||||||
|
for len(paths) > shardSize {
|
||||||
|
ret = append(ret, paths[0:shardSize])
|
||||||
|
paths = paths[shardSize:]
|
||||||
|
}
|
||||||
|
if len(paths) > 0 {
|
||||||
|
ret = append(ret, paths)
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShardStrings takes a slice of strings, and returns a slice of slices of strings where each one has at most shardSize
|
||||||
|
// elements.
|
||||||
|
func ShardStrings(s []string, shardSize int) [][]string {
|
||||||
|
if len(s) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
ret := make([][]string, 0, (len(s)+shardSize-1)/shardSize)
|
||||||
|
for len(s) > shardSize {
|
||||||
|
ret = append(ret, s[0:shardSize])
|
||||||
|
s = s[shardSize:]
|
||||||
|
}
|
||||||
|
if len(s) > 0 {
|
||||||
|
ret = append(ret, s)
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
|
@ -469,3 +469,102 @@ func TestSplitFileExt(t *testing.T) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_Shard(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
strings []string
|
||||||
|
shardSize int
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want [][]string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "empty",
|
||||||
|
args: args{
|
||||||
|
strings: nil,
|
||||||
|
shardSize: 1,
|
||||||
|
},
|
||||||
|
want: [][]string(nil),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "single shard",
|
||||||
|
args: args{
|
||||||
|
strings: []string{"a", "b"},
|
||||||
|
shardSize: 2,
|
||||||
|
},
|
||||||
|
want: [][]string{{"a", "b"}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "single short shard",
|
||||||
|
args: args{
|
||||||
|
strings: []string{"a", "b"},
|
||||||
|
shardSize: 3,
|
||||||
|
},
|
||||||
|
want: [][]string{{"a", "b"}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "shard per input",
|
||||||
|
args: args{
|
||||||
|
strings: []string{"a", "b", "c"},
|
||||||
|
shardSize: 1,
|
||||||
|
},
|
||||||
|
want: [][]string{{"a"}, {"b"}, {"c"}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "balanced shards",
|
||||||
|
args: args{
|
||||||
|
strings: []string{"a", "b", "c", "d"},
|
||||||
|
shardSize: 2,
|
||||||
|
},
|
||||||
|
want: [][]string{{"a", "b"}, {"c", "d"}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "unbalanced shards",
|
||||||
|
args: args{
|
||||||
|
strings: []string{"a", "b", "c"},
|
||||||
|
shardSize: 2,
|
||||||
|
},
|
||||||
|
want: [][]string{{"a", "b"}, {"c"}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
t.Run("strings", func(t *testing.T) {
|
||||||
|
if got := ShardStrings(tt.args.strings, tt.args.shardSize); !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("ShardStrings(%v, %v) = %v, want %v",
|
||||||
|
tt.args.strings, tt.args.shardSize, got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("paths", func(t *testing.T) {
|
||||||
|
stringsToPaths := func(strings []string) Paths {
|
||||||
|
if strings == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
paths := make(Paths, len(strings))
|
||||||
|
for i, s := range strings {
|
||||||
|
paths[i] = PathForTesting(s)
|
||||||
|
}
|
||||||
|
return paths
|
||||||
|
}
|
||||||
|
|
||||||
|
paths := stringsToPaths(tt.args.strings)
|
||||||
|
|
||||||
|
var want []Paths
|
||||||
|
if sWant := tt.want; sWant != nil {
|
||||||
|
want = make([]Paths, len(sWant))
|
||||||
|
for i, w := range sWant {
|
||||||
|
want[i] = stringsToPaths(w)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if got := ShardPaths(paths, tt.args.shardSize); !reflect.DeepEqual(got, want) {
|
||||||
|
t.Errorf("ShardPaths(%v, %v) = %v, want %v",
|
||||||
|
paths, tt.args.shardSize, got, want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ var aapt2CompileRule = pctx.AndroidStaticRule("aapt2Compile",
|
||||||
func aapt2Compile(ctx android.ModuleContext, dir android.Path, paths android.Paths,
|
func aapt2Compile(ctx android.ModuleContext, dir android.Path, paths android.Paths,
|
||||||
flags []string) android.WritablePaths {
|
flags []string) android.WritablePaths {
|
||||||
|
|
||||||
shards := shardPaths(paths, AAPT2_SHARD_SIZE)
|
shards := android.ShardPaths(paths, AAPT2_SHARD_SIZE)
|
||||||
|
|
||||||
ret := make(android.WritablePaths, 0, len(paths))
|
ret := make(android.WritablePaths, 0, len(paths))
|
||||||
|
|
||||||
|
|
14
java/java.go
14
java/java.go
|
@ -580,18 +580,6 @@ func hasSrcExt(srcs []string, ext string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func shardPaths(paths android.Paths, shardSize int) []android.Paths {
|
|
||||||
ret := make([]android.Paths, 0, (len(paths)+shardSize-1)/shardSize)
|
|
||||||
for len(paths) > shardSize {
|
|
||||||
ret = append(ret, paths[0:shardSize])
|
|
||||||
paths = paths[shardSize:]
|
|
||||||
}
|
|
||||||
if len(paths) > 0 {
|
|
||||||
ret = append(ret, paths)
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func (j *Module) hasSrcExt(ext string) bool {
|
func (j *Module) hasSrcExt(ext string) bool {
|
||||||
return hasSrcExt(j.properties.Srcs, ext)
|
return hasSrcExt(j.properties.Srcs, ext)
|
||||||
}
|
}
|
||||||
|
@ -1156,7 +1144,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
|
||||||
shardSize := int(*(j.properties.Javac_shard_size))
|
shardSize := int(*(j.properties.Javac_shard_size))
|
||||||
var shardSrcs []android.Paths
|
var shardSrcs []android.Paths
|
||||||
if len(uniqueSrcFiles) > 0 {
|
if len(uniqueSrcFiles) > 0 {
|
||||||
shardSrcs = shardPaths(uniqueSrcFiles, shardSize)
|
shardSrcs = android.ShardPaths(uniqueSrcFiles, shardSize)
|
||||||
for idx, shardSrc := range shardSrcs {
|
for idx, shardSrc := range shardSrcs {
|
||||||
classes := j.compileJavaClasses(ctx, jarName, idx, shardSrc,
|
classes := j.compileJavaClasses(ctx, jarName, idx, shardSrc,
|
||||||
nil, flags, extraJarDeps)
|
nil, flags, extraJarDeps)
|
||||||
|
|
|
@ -123,25 +123,6 @@ func (r *robolectricTest) GenerateAndroidBuildActions(ctx android.ModuleContext)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func shardTests(paths []string, shards int) [][]string {
|
|
||||||
if shards > len(paths) {
|
|
||||||
shards = len(paths)
|
|
||||||
}
|
|
||||||
if shards == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
ret := make([][]string, 0, shards)
|
|
||||||
shardSize := (len(paths) + shards - 1) / shards
|
|
||||||
for len(paths) > shardSize {
|
|
||||||
ret = append(ret, paths[0:shardSize])
|
|
||||||
paths = paths[shardSize:]
|
|
||||||
}
|
|
||||||
if len(paths) > 0 {
|
|
||||||
ret = append(ret, paths)
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func generateRoboTestConfig(ctx android.ModuleContext, outputFile android.WritablePath, instrumentedApp *AndroidApp) {
|
func generateRoboTestConfig(ctx android.ModuleContext, outputFile android.WritablePath, instrumentedApp *AndroidApp) {
|
||||||
manifest := instrumentedApp.mergedManifestFile
|
manifest := instrumentedApp.mergedManifestFile
|
||||||
resourceApk := instrumentedApp.outputFile
|
resourceApk := instrumentedApp.outputFile
|
||||||
|
@ -183,7 +164,9 @@ func (r *robolectricTest) AndroidMkEntries() android.AndroidMkEntries {
|
||||||
entries.ExtraFooters = []android.AndroidMkExtraFootersFunc{
|
entries.ExtraFooters = []android.AndroidMkExtraFootersFunc{
|
||||||
func(w io.Writer, name, prefix, moduleDir string, entries *android.AndroidMkEntries) {
|
func(w io.Writer, name, prefix, moduleDir string, entries *android.AndroidMkEntries) {
|
||||||
if s := r.robolectricProperties.Test_options.Shards; s != nil && *s > 1 {
|
if s := r.robolectricProperties.Test_options.Shards; s != nil && *s > 1 {
|
||||||
shards := shardTests(r.tests, int(*s))
|
numShards := int(*s)
|
||||||
|
shardSize := (len(r.tests) + numShards - 1) / numShards
|
||||||
|
shards := android.ShardStrings(r.tests, shardSize)
|
||||||
for i, shard := range shards {
|
for i, shard := range shards {
|
||||||
r.writeTestRunner(w, name, "Run"+name+strconv.Itoa(i), shard)
|
r.writeTestRunner(w, name, "Run"+name+strconv.Itoa(i), shard)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,88 +0,0 @@
|
||||||
// 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 java
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Test_shardTests(t *testing.T) {
|
|
||||||
type args struct {
|
|
||||||
paths []string
|
|
||||||
shards int
|
|
||||||
}
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
args args
|
|
||||||
want [][]string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "empty",
|
|
||||||
args: args{
|
|
||||||
paths: nil,
|
|
||||||
shards: 1,
|
|
||||||
},
|
|
||||||
want: [][]string(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "too many shards",
|
|
||||||
args: args{
|
|
||||||
paths: []string{"a", "b"},
|
|
||||||
shards: 3,
|
|
||||||
},
|
|
||||||
want: [][]string{{"a"}, {"b"}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "single shard",
|
|
||||||
args: args{
|
|
||||||
paths: []string{"a", "b"},
|
|
||||||
shards: 1,
|
|
||||||
},
|
|
||||||
want: [][]string{{"a", "b"}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "shard per input",
|
|
||||||
args: args{
|
|
||||||
paths: []string{"a", "b", "c"},
|
|
||||||
shards: 3,
|
|
||||||
},
|
|
||||||
want: [][]string{{"a"}, {"b"}, {"c"}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "balanced shards",
|
|
||||||
args: args{
|
|
||||||
paths: []string{"a", "b", "c", "d"},
|
|
||||||
shards: 2,
|
|
||||||
},
|
|
||||||
want: [][]string{{"a", "b"}, {"c", "d"}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "unbalanced shards",
|
|
||||||
args: args{
|
|
||||||
paths: []string{"a", "b", "c"},
|
|
||||||
shards: 2,
|
|
||||||
},
|
|
||||||
want: [][]string{{"a", "b"}, {"c"}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
if got := shardTests(tt.args.paths, tt.args.shards); !reflect.DeepEqual(got, tt.want) {
|
|
||||||
t.Errorf("shardTests() = %v, want %v", got, tt.want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue