| // Copyright 2022 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| package main |
| |
| import ( |
| "strings" |
| ) |
| |
| // scoreChangedFileProximity computes a 0-100 score of the proximity of a Gerrit |
| // change's affected files to the given test GN label. |
| func scoreChangedFileProximity(changedFiles []string, gnLabel string) int { |
| // If there's no GN label and we can't do this analysis, that significantly |
| // lowers the confidence. |
| if gnLabel == "" { |
| return 0 |
| } |
| |
| strippedLabel := strings.Trim(strings.Split(gnLabel, ":")[0], "/") |
| labelParts := strings.Split(strippedLabel, "/") |
| |
| var proximityScores []float64 |
| |
| for _, file := range changedFiles { |
| pl := sharedPrefixLength(labelParts, strings.Split(file, "/")) |
| |
| // Proximity is determined by the ratio of the shared prefix length to |
| // the length of the GN label directory. |
| // |
| // If a test is declared in directory `src/foo/bar`, any files within |
| // `src/foo/bar` or any subdirectory thereof will have a proximity ratio |
| // of 1. |
| proximityScore := 100 * float64(pl) / float64(len(labelParts)) |
| |
| proximityScores = append(proximityScores, proximityScore) |
| |
| // Add extra weighting for higher proximity scores. If a change touches |
| // a couple files close to the test, along with a large number of |
| // unrelated files, it should still be scored higher than a change that |
| // touches only files that are moderately close to the test. |
| for i := 0; i <= int(proximityScore/25); i++ { |
| proximityScores = append(proximityScores, proximityScore) |
| } |
| } |
| |
| return int(average(proximityScores)) |
| } |
| |
| // sharedPrefixLength computes the length of the longest shared prefix of the |
| // two slices, i.e. the maximum number N such that p1[:N] == p2[:N]. |
| func sharedPrefixLength(p1, p2 []string) int { |
| var i int |
| for ; i < len(p1) && i < len(p2); i++ { |
| if p1[i] != p2[i] { |
| break |
| } |
| } |
| return i |
| } |