...

Source file src/k8s.io/apimachinery/pkg/util/diff/diff.go

Documentation: k8s.io/apimachinery/pkg/util/diff

     1  /*
     2  Copyright 2014 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package diff
    18  
    19  import (
    20  	"bytes"
    21  	"fmt"
    22  	"reflect"
    23  	"strings"
    24  	"text/tabwriter"
    25  
    26  	"github.com/google/go-cmp/cmp"
    27  	"k8s.io/apimachinery/pkg/util/dump"
    28  )
    29  
    30  func legacyDiff(a, b interface{}) string {
    31  	return cmp.Diff(a, b)
    32  }
    33  
    34  // StringDiff diffs a and b and returns a human readable diff.
    35  // DEPRECATED: use github.com/google/go-cmp/cmp.Diff
    36  func StringDiff(a, b string) string {
    37  	return legacyDiff(a, b)
    38  }
    39  
    40  // ObjectDiff prints the diff of two go objects and fails if the objects
    41  // contain unhandled unexported fields.
    42  // DEPRECATED: use github.com/google/go-cmp/cmp.Diff
    43  func ObjectDiff(a, b interface{}) string {
    44  	return legacyDiff(a, b)
    45  }
    46  
    47  // ObjectGoPrintDiff prints the diff of two go objects and fails if the objects
    48  // contain unhandled unexported fields.
    49  // DEPRECATED: use github.com/google/go-cmp/cmp.Diff
    50  func ObjectGoPrintDiff(a, b interface{}) string {
    51  	return legacyDiff(a, b)
    52  }
    53  
    54  // ObjectReflectDiff prints the diff of two go objects and fails if the objects
    55  // contain unhandled unexported fields.
    56  // DEPRECATED: use github.com/google/go-cmp/cmp.Diff
    57  func ObjectReflectDiff(a, b interface{}) string {
    58  	return legacyDiff(a, b)
    59  }
    60  
    61  // ObjectGoPrintSideBySide prints a and b as textual dumps side by side,
    62  // enabling easy visual scanning for mismatches.
    63  func ObjectGoPrintSideBySide(a, b interface{}) string {
    64  	sA := dump.Pretty(a)
    65  	sB := dump.Pretty(b)
    66  
    67  	linesA := strings.Split(sA, "\n")
    68  	linesB := strings.Split(sB, "\n")
    69  	width := 0
    70  	for _, s := range linesA {
    71  		l := len(s)
    72  		if l > width {
    73  			width = l
    74  		}
    75  	}
    76  	for _, s := range linesB {
    77  		l := len(s)
    78  		if l > width {
    79  			width = l
    80  		}
    81  	}
    82  	buf := &bytes.Buffer{}
    83  	w := tabwriter.NewWriter(buf, width, 0, 1, ' ', 0)
    84  	max := len(linesA)
    85  	if len(linesB) > max {
    86  		max = len(linesB)
    87  	}
    88  	for i := 0; i < max; i++ {
    89  		var a, b string
    90  		if i < len(linesA) {
    91  			a = linesA[i]
    92  		}
    93  		if i < len(linesB) {
    94  			b = linesB[i]
    95  		}
    96  		fmt.Fprintf(w, "%s\t%s\n", a, b)
    97  	}
    98  	w.Flush()
    99  	return buf.String()
   100  }
   101  
   102  // IgnoreUnset is an option that ignores fields that are unset on the right
   103  // hand side of a comparison. This is useful in testing to assert that an
   104  // object is a derivative.
   105  func IgnoreUnset() cmp.Option {
   106  	return cmp.Options{
   107  		// ignore unset fields in v2
   108  		cmp.FilterPath(func(path cmp.Path) bool {
   109  			_, v2 := path.Last().Values()
   110  			switch v2.Kind() {
   111  			case reflect.Slice, reflect.Map:
   112  				if v2.IsNil() || v2.Len() == 0 {
   113  					return true
   114  				}
   115  			case reflect.String:
   116  				if v2.Len() == 0 {
   117  					return true
   118  				}
   119  			case reflect.Interface, reflect.Pointer:
   120  				if v2.IsNil() {
   121  					return true
   122  				}
   123  			}
   124  			return false
   125  		}, cmp.Ignore()),
   126  		// ignore map entries that aren't set in v2
   127  		cmp.FilterPath(func(path cmp.Path) bool {
   128  			switch i := path.Last().(type) {
   129  			case cmp.MapIndex:
   130  				if _, v2 := i.Values(); !v2.IsValid() {
   131  					fmt.Println("E")
   132  					return true
   133  				}
   134  			}
   135  			return false
   136  		}, cmp.Ignore()),
   137  	}
   138  }
   139  

View as plain text