1package testhelper 2 3import ( 4 "bytes" 5 "fmt" 6 "io" 7 "math" 8 "strings" 9 10 "github.com/aryann/difflib" 11) 12 13func Diff(want, got string, context int) (string, bool) { 14 records := difflib.Diff( 15 strings.Split(want, "\n"), 16 strings.Split(got, "\n"), 17 ) 18 19 w := &bytes.Buffer{} 20 21 changed := checkAndPrintRecords(w, records, context) 22 23 return w.String(), changed 24} 25 26func checkAndPrintRecords(w io.Writer, records []difflib.DiffRecord, context int) bool { 27 var changed bool 28 if context >= 0 { 29 distances := calculateDistances(records) 30 omitting := false 31 for i, diff := range records { 32 if diff.Delta != difflib.Common { 33 changed = true 34 } 35 if distances[i] > context { 36 if !omitting { 37 fmt.Fprintln(w, "...") 38 omitting = true 39 } 40 } else { 41 omitting = false 42 fmt.Fprintln(w, formatRecord(diff)) 43 } 44 } 45 } else { 46 for _, diff := range records { 47 if diff.Delta != difflib.Common { 48 changed = true 49 } 50 fmt.Fprintln(w, formatRecord(diff)) 51 } 52 } 53 return changed 54} 55 56func formatRecord(diff difflib.DiffRecord) string { 57 var prefix string 58 switch diff.Delta { 59 case difflib.RightOnly: 60 prefix = "+ " 61 case difflib.LeftOnly: 62 prefix = "- " 63 case difflib.Common: 64 prefix = " " 65 } 66 67 return prefix + diff.Payload 68} 69 70// Shamelessly and thankfully copied from https://github.com/databus23/helm-diff/blob/99b8474af7726ca6f57b37b0b8b8f3cd36c991e8/diff/diff.go#L116 71func calculateDistances(diffs []difflib.DiffRecord) map[int]int { 72 distances := map[int]int{} 73 74 // Iterate forwards through diffs, set 'distance' based on closest 'change' before this line 75 change := -1 76 for i, diff := range diffs { 77 if diff.Delta != difflib.Common { 78 change = i 79 } 80 distance := math.MaxInt32 81 if change != -1 { 82 distance = i - change 83 } 84 distances[i] = distance 85 } 86 87 // Iterate backwards through diffs, reduce 'distance' based on closest 'change' after this line 88 change = -1 89 for i := len(diffs) - 1; i >= 0; i-- { 90 diff := diffs[i] 91 if diff.Delta != difflib.Common { 92 change = i 93 } 94 if change != -1 { 95 distance := change - i 96 if distance < distances[i] { 97 distances[i] = distance 98 } 99 } 100 } 101 102 return distances 103} 104