1// Copyright 2020 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 build 16 17import ( 18 "errors" 19 "io/ioutil" 20 "os" 21 "path/filepath" 22 "reflect" 23 "sort" 24 "strconv" 25 "strings" 26 "testing" 27 "time" 28 29 "android/soong/ui/logger" 30) 31 32func TestPruneMetricsFiles(t *testing.T) { 33 rootDir := t.TempDir() 34 35 dirs := []string{ 36 filepath.Join(rootDir, "d1"), 37 filepath.Join(rootDir, "d1", "d2"), 38 filepath.Join(rootDir, "d1", "d2", "d3"), 39 } 40 41 files := []string{ 42 filepath.Join(rootDir, "d1", "f1"), 43 filepath.Join(rootDir, "d1", "d2", "f1"), 44 filepath.Join(rootDir, "d1", "d2", "d3", "f1"), 45 } 46 47 for _, d := range dirs { 48 if err := os.MkdirAll(d, 0777); err != nil { 49 t.Fatalf("got %v, expecting nil error for making directory %q", err, d) 50 } 51 } 52 53 for _, f := range files { 54 if err := ioutil.WriteFile(f, []byte{}, 0777); err != nil { 55 t.Fatalf("got %v, expecting nil error on writing file %q", err, f) 56 } 57 } 58 59 want := []string{ 60 filepath.Join(rootDir, "d1", "f1"), 61 filepath.Join(rootDir, "d1", "d2", "f1"), 62 filepath.Join(rootDir, "d1", "d2", "d3", "f1"), 63 } 64 65 got := pruneMetricsFiles([]string{rootDir}) 66 67 sort.Strings(got) 68 sort.Strings(want) 69 70 if !reflect.DeepEqual(got, want) { 71 t.Errorf("got %q, want %q after pruning metrics files", got, want) 72 } 73} 74 75func TestUploadMetrics(t *testing.T) { 76 ctx := testContext() 77 tests := []struct { 78 description string 79 uploader string 80 createFiles bool 81 files []string 82 }{{ 83 description: "ANDROID_ENABLE_METRICS_UPLOAD not set", 84 }, { 85 description: "no metrics files to upload", 86 uploader: "fake", 87 }, { 88 description: "non-existent metrics files no upload", 89 uploader: "fake", 90 files: []string{"metrics_file_1", "metrics_file_2", "metrics_file_3"}, 91 }, { 92 description: "trigger upload", 93 uploader: "echo", 94 createFiles: true, 95 files: []string{"metrics_file_1", "metrics_file_2"}, 96 }} 97 98 for _, tt := range tests { 99 t.Run(tt.description, func(t *testing.T) { 100 defer logger.Recover(func(err error) { 101 t.Fatalf("got unexpected error: %v", err) 102 }) 103 104 outDir, err := ioutil.TempDir("", "") 105 if err != nil { 106 t.Fatalf("failed to create out directory: %v", outDir) 107 } 108 defer os.RemoveAll(outDir) 109 110 // Supply our own tmpDir to delete the temp dir once the test is done. 111 orgTmpDir := tmpDir 112 tmpDir = func(string, string) (string, error) { 113 retDir := filepath.Join(outDir, "tmp_upload_dir") 114 if err := os.Mkdir(retDir, 0755); err != nil { 115 t.Fatalf("failed to create temporary directory %q: %v", retDir, err) 116 } 117 return retDir, nil 118 } 119 defer func() { tmpDir = orgTmpDir }() 120 121 metricsUploadDir := filepath.Join(outDir, ".metrics_uploader") 122 if err := os.Mkdir(metricsUploadDir, 0755); err != nil { 123 t.Fatalf("failed to create %q directory for oauth valid check: %v", metricsUploadDir, err) 124 } 125 126 var metricsFiles []string 127 if tt.createFiles { 128 for _, f := range tt.files { 129 filename := filepath.Join(outDir, f) 130 metricsFiles = append(metricsFiles, filename) 131 if err := ioutil.WriteFile(filename, []byte("test file"), 0644); err != nil { 132 t.Fatalf("failed to create a fake metrics file %q for uploading: %v", filename, err) 133 } 134 } 135 } 136 137 config := Config{&configImpl{ 138 environ: &Environment{ 139 "OUT_DIR=" + outDir, 140 "ANDROID_ENABLE_METRICS_UPLOAD=" + tt.uploader, 141 }, 142 buildDateTime: strconv.FormatInt(time.Now().UnixNano()/int64(time.Millisecond), 10), 143 }} 144 145 UploadMetrics(ctx, config, false, time.Now(), metricsFiles...) 146 }) 147 } 148} 149 150func TestUploadMetricsErrors(t *testing.T) { 151 ctx := testContext() 152 tests := []struct { 153 description string 154 tmpDir string 155 tmpDirErr error 156 expectedErr string 157 }{{ 158 description: "getTmpDir returned error", 159 tmpDirErr: errors.New("getTmpDir failed"), 160 expectedErr: "getTmpDir failed", 161 }, { 162 description: "copyFile operation error", 163 tmpDir: "/fake_dir", 164 expectedErr: "failed to copy", 165 }} 166 167 for _, tt := range tests { 168 t.Run(tt.description, func(t *testing.T) { 169 defer logger.Recover(func(err error) { 170 got := err.Error() 171 if !strings.Contains(got, tt.expectedErr) { 172 t.Errorf("got %q, want %q to be contained in error", got, tt.expectedErr) 173 } 174 }) 175 176 outDir, err := ioutil.TempDir("", "") 177 if err != nil { 178 t.Fatalf("failed to create out directory: %v", outDir) 179 } 180 defer os.RemoveAll(outDir) 181 182 orgTmpDir := tmpDir 183 tmpDir = func(string, string) (string, error) { 184 return tt.tmpDir, tt.tmpDirErr 185 } 186 defer func() { tmpDir = orgTmpDir }() 187 188 metricsFile := filepath.Join(outDir, "metrics_file_1") 189 if err := ioutil.WriteFile(metricsFile, []byte("test file"), 0644); err != nil { 190 t.Fatalf("failed to create a fake metrics file %q for uploading: %v", metricsFile, err) 191 } 192 193 config := Config{&configImpl{ 194 environ: &Environment{ 195 "ANDROID_ENABLE_METRICS_UPLOAD=fake", 196 "OUT_DIR=/bad", 197 }}} 198 199 UploadMetrics(ctx, config, true, time.Now(), metricsFile) 200 t.Errorf("got nil, expecting %q as a failure", tt.expectedErr) 201 }) 202 } 203} 204