...

Source file src/go.mongodb.org/mongo-driver/internal/assert/assertion_compare.go

Documentation: go.mongodb.org/mongo-driver/internal/assert

     1  // Copied from https://github.com/stretchr/testify/blob/1333b5d3bda8cf5aedcf3e1aaa95cac28aaab892/assert/assertion_compare.go
     2  
     3  // Copyright 2020 Mat Ryer, Tyler Bunnell and all contributors. All rights reserved.
     4  // Use of this source code is governed by an MIT-style license that can be found in
     5  // the THIRD-PARTY-NOTICES file.
     6  
     7  package assert
     8  
     9  import (
    10  	"bytes"
    11  	"fmt"
    12  	"reflect"
    13  	"time"
    14  )
    15  
    16  type CompareType int
    17  
    18  const (
    19  	compareLess CompareType = iota - 1
    20  	compareEqual
    21  	compareGreater
    22  )
    23  
    24  var (
    25  	intType   = reflect.TypeOf(int(1))
    26  	int8Type  = reflect.TypeOf(int8(1))
    27  	int16Type = reflect.TypeOf(int16(1))
    28  	int32Type = reflect.TypeOf(int32(1))
    29  	int64Type = reflect.TypeOf(int64(1))
    30  
    31  	uintType   = reflect.TypeOf(uint(1))
    32  	uint8Type  = reflect.TypeOf(uint8(1))
    33  	uint16Type = reflect.TypeOf(uint16(1))
    34  	uint32Type = reflect.TypeOf(uint32(1))
    35  	uint64Type = reflect.TypeOf(uint64(1))
    36  
    37  	float32Type = reflect.TypeOf(float32(1))
    38  	float64Type = reflect.TypeOf(float64(1))
    39  
    40  	stringType = reflect.TypeOf("")
    41  
    42  	timeType  = reflect.TypeOf(time.Time{})
    43  	bytesType = reflect.TypeOf([]byte{})
    44  )
    45  
    46  func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
    47  	obj1Value := reflect.ValueOf(obj1)
    48  	obj2Value := reflect.ValueOf(obj2)
    49  
    50  	// throughout this switch we try and avoid calling .Convert() if possible,
    51  	// as this has a pretty big performance impact
    52  	switch kind {
    53  	case reflect.Int:
    54  		{
    55  			intobj1, ok := obj1.(int)
    56  			if !ok {
    57  				intobj1 = obj1Value.Convert(intType).Interface().(int)
    58  			}
    59  			intobj2, ok := obj2.(int)
    60  			if !ok {
    61  				intobj2 = obj2Value.Convert(intType).Interface().(int)
    62  			}
    63  			if intobj1 > intobj2 {
    64  				return compareGreater, true
    65  			}
    66  			if intobj1 == intobj2 {
    67  				return compareEqual, true
    68  			}
    69  			if intobj1 < intobj2 {
    70  				return compareLess, true
    71  			}
    72  		}
    73  	case reflect.Int8:
    74  		{
    75  			int8obj1, ok := obj1.(int8)
    76  			if !ok {
    77  				int8obj1 = obj1Value.Convert(int8Type).Interface().(int8)
    78  			}
    79  			int8obj2, ok := obj2.(int8)
    80  			if !ok {
    81  				int8obj2 = obj2Value.Convert(int8Type).Interface().(int8)
    82  			}
    83  			if int8obj1 > int8obj2 {
    84  				return compareGreater, true
    85  			}
    86  			if int8obj1 == int8obj2 {
    87  				return compareEqual, true
    88  			}
    89  			if int8obj1 < int8obj2 {
    90  				return compareLess, true
    91  			}
    92  		}
    93  	case reflect.Int16:
    94  		{
    95  			int16obj1, ok := obj1.(int16)
    96  			if !ok {
    97  				int16obj1 = obj1Value.Convert(int16Type).Interface().(int16)
    98  			}
    99  			int16obj2, ok := obj2.(int16)
   100  			if !ok {
   101  				int16obj2 = obj2Value.Convert(int16Type).Interface().(int16)
   102  			}
   103  			if int16obj1 > int16obj2 {
   104  				return compareGreater, true
   105  			}
   106  			if int16obj1 == int16obj2 {
   107  				return compareEqual, true
   108  			}
   109  			if int16obj1 < int16obj2 {
   110  				return compareLess, true
   111  			}
   112  		}
   113  	case reflect.Int32:
   114  		{
   115  			int32obj1, ok := obj1.(int32)
   116  			if !ok {
   117  				int32obj1 = obj1Value.Convert(int32Type).Interface().(int32)
   118  			}
   119  			int32obj2, ok := obj2.(int32)
   120  			if !ok {
   121  				int32obj2 = obj2Value.Convert(int32Type).Interface().(int32)
   122  			}
   123  			if int32obj1 > int32obj2 {
   124  				return compareGreater, true
   125  			}
   126  			if int32obj1 == int32obj2 {
   127  				return compareEqual, true
   128  			}
   129  			if int32obj1 < int32obj2 {
   130  				return compareLess, true
   131  			}
   132  		}
   133  	case reflect.Int64:
   134  		{
   135  			int64obj1, ok := obj1.(int64)
   136  			if !ok {
   137  				int64obj1 = obj1Value.Convert(int64Type).Interface().(int64)
   138  			}
   139  			int64obj2, ok := obj2.(int64)
   140  			if !ok {
   141  				int64obj2 = obj2Value.Convert(int64Type).Interface().(int64)
   142  			}
   143  			if int64obj1 > int64obj2 {
   144  				return compareGreater, true
   145  			}
   146  			if int64obj1 == int64obj2 {
   147  				return compareEqual, true
   148  			}
   149  			if int64obj1 < int64obj2 {
   150  				return compareLess, true
   151  			}
   152  		}
   153  	case reflect.Uint:
   154  		{
   155  			uintobj1, ok := obj1.(uint)
   156  			if !ok {
   157  				uintobj1 = obj1Value.Convert(uintType).Interface().(uint)
   158  			}
   159  			uintobj2, ok := obj2.(uint)
   160  			if !ok {
   161  				uintobj2 = obj2Value.Convert(uintType).Interface().(uint)
   162  			}
   163  			if uintobj1 > uintobj2 {
   164  				return compareGreater, true
   165  			}
   166  			if uintobj1 == uintobj2 {
   167  				return compareEqual, true
   168  			}
   169  			if uintobj1 < uintobj2 {
   170  				return compareLess, true
   171  			}
   172  		}
   173  	case reflect.Uint8:
   174  		{
   175  			uint8obj1, ok := obj1.(uint8)
   176  			if !ok {
   177  				uint8obj1 = obj1Value.Convert(uint8Type).Interface().(uint8)
   178  			}
   179  			uint8obj2, ok := obj2.(uint8)
   180  			if !ok {
   181  				uint8obj2 = obj2Value.Convert(uint8Type).Interface().(uint8)
   182  			}
   183  			if uint8obj1 > uint8obj2 {
   184  				return compareGreater, true
   185  			}
   186  			if uint8obj1 == uint8obj2 {
   187  				return compareEqual, true
   188  			}
   189  			if uint8obj1 < uint8obj2 {
   190  				return compareLess, true
   191  			}
   192  		}
   193  	case reflect.Uint16:
   194  		{
   195  			uint16obj1, ok := obj1.(uint16)
   196  			if !ok {
   197  				uint16obj1 = obj1Value.Convert(uint16Type).Interface().(uint16)
   198  			}
   199  			uint16obj2, ok := obj2.(uint16)
   200  			if !ok {
   201  				uint16obj2 = obj2Value.Convert(uint16Type).Interface().(uint16)
   202  			}
   203  			if uint16obj1 > uint16obj2 {
   204  				return compareGreater, true
   205  			}
   206  			if uint16obj1 == uint16obj2 {
   207  				return compareEqual, true
   208  			}
   209  			if uint16obj1 < uint16obj2 {
   210  				return compareLess, true
   211  			}
   212  		}
   213  	case reflect.Uint32:
   214  		{
   215  			uint32obj1, ok := obj1.(uint32)
   216  			if !ok {
   217  				uint32obj1 = obj1Value.Convert(uint32Type).Interface().(uint32)
   218  			}
   219  			uint32obj2, ok := obj2.(uint32)
   220  			if !ok {
   221  				uint32obj2 = obj2Value.Convert(uint32Type).Interface().(uint32)
   222  			}
   223  			if uint32obj1 > uint32obj2 {
   224  				return compareGreater, true
   225  			}
   226  			if uint32obj1 == uint32obj2 {
   227  				return compareEqual, true
   228  			}
   229  			if uint32obj1 < uint32obj2 {
   230  				return compareLess, true
   231  			}
   232  		}
   233  	case reflect.Uint64:
   234  		{
   235  			uint64obj1, ok := obj1.(uint64)
   236  			if !ok {
   237  				uint64obj1 = obj1Value.Convert(uint64Type).Interface().(uint64)
   238  			}
   239  			uint64obj2, ok := obj2.(uint64)
   240  			if !ok {
   241  				uint64obj2 = obj2Value.Convert(uint64Type).Interface().(uint64)
   242  			}
   243  			if uint64obj1 > uint64obj2 {
   244  				return compareGreater, true
   245  			}
   246  			if uint64obj1 == uint64obj2 {
   247  				return compareEqual, true
   248  			}
   249  			if uint64obj1 < uint64obj2 {
   250  				return compareLess, true
   251  			}
   252  		}
   253  	case reflect.Float32:
   254  		{
   255  			float32obj1, ok := obj1.(float32)
   256  			if !ok {
   257  				float32obj1 = obj1Value.Convert(float32Type).Interface().(float32)
   258  			}
   259  			float32obj2, ok := obj2.(float32)
   260  			if !ok {
   261  				float32obj2 = obj2Value.Convert(float32Type).Interface().(float32)
   262  			}
   263  			if float32obj1 > float32obj2 {
   264  				return compareGreater, true
   265  			}
   266  			if float32obj1 == float32obj2 {
   267  				return compareEqual, true
   268  			}
   269  			if float32obj1 < float32obj2 {
   270  				return compareLess, true
   271  			}
   272  		}
   273  	case reflect.Float64:
   274  		{
   275  			float64obj1, ok := obj1.(float64)
   276  			if !ok {
   277  				float64obj1 = obj1Value.Convert(float64Type).Interface().(float64)
   278  			}
   279  			float64obj2, ok := obj2.(float64)
   280  			if !ok {
   281  				float64obj2 = obj2Value.Convert(float64Type).Interface().(float64)
   282  			}
   283  			if float64obj1 > float64obj2 {
   284  				return compareGreater, true
   285  			}
   286  			if float64obj1 == float64obj2 {
   287  				return compareEqual, true
   288  			}
   289  			if float64obj1 < float64obj2 {
   290  				return compareLess, true
   291  			}
   292  		}
   293  	case reflect.String:
   294  		{
   295  			stringobj1, ok := obj1.(string)
   296  			if !ok {
   297  				stringobj1 = obj1Value.Convert(stringType).Interface().(string)
   298  			}
   299  			stringobj2, ok := obj2.(string)
   300  			if !ok {
   301  				stringobj2 = obj2Value.Convert(stringType).Interface().(string)
   302  			}
   303  			if stringobj1 > stringobj2 {
   304  				return compareGreater, true
   305  			}
   306  			if stringobj1 == stringobj2 {
   307  				return compareEqual, true
   308  			}
   309  			if stringobj1 < stringobj2 {
   310  				return compareLess, true
   311  			}
   312  		}
   313  	// Check for known struct types we can check for compare results.
   314  	case reflect.Struct:
   315  		{
   316  			// All structs enter here. We're not interested in most types.
   317  			if !canConvert(obj1Value, timeType) {
   318  				break
   319  			}
   320  
   321  			// time.Time can compared!
   322  			timeObj1, ok := obj1.(time.Time)
   323  			if !ok {
   324  				timeObj1 = obj1Value.Convert(timeType).Interface().(time.Time)
   325  			}
   326  
   327  			timeObj2, ok := obj2.(time.Time)
   328  			if !ok {
   329  				timeObj2 = obj2Value.Convert(timeType).Interface().(time.Time)
   330  			}
   331  
   332  			return compare(timeObj1.UnixNano(), timeObj2.UnixNano(), reflect.Int64)
   333  		}
   334  	case reflect.Slice:
   335  		{
   336  			// We only care about the []byte type.
   337  			if !canConvert(obj1Value, bytesType) {
   338  				break
   339  			}
   340  
   341  			// []byte can be compared!
   342  			bytesObj1, ok := obj1.([]byte)
   343  			if !ok {
   344  				bytesObj1 = obj1Value.Convert(bytesType).Interface().([]byte)
   345  
   346  			}
   347  			bytesObj2, ok := obj2.([]byte)
   348  			if !ok {
   349  				bytesObj2 = obj2Value.Convert(bytesType).Interface().([]byte)
   350  			}
   351  
   352  			return CompareType(bytes.Compare(bytesObj1, bytesObj2)), true
   353  		}
   354  	}
   355  
   356  	return compareEqual, false
   357  }
   358  
   359  // Greater asserts that the first element is greater than the second
   360  //
   361  //	assert.Greater(t, 2, 1)
   362  //	assert.Greater(t, float64(2), float64(1))
   363  //	assert.Greater(t, "b", "a")
   364  func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
   365  	if h, ok := t.(tHelper); ok {
   366  		h.Helper()
   367  	}
   368  	return compareTwoValues(t, e1, e2, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...)
   369  }
   370  
   371  // GreaterOrEqual asserts that the first element is greater than or equal to the second
   372  //
   373  //	assert.GreaterOrEqual(t, 2, 1)
   374  //	assert.GreaterOrEqual(t, 2, 2)
   375  //	assert.GreaterOrEqual(t, "b", "a")
   376  //	assert.GreaterOrEqual(t, "b", "b")
   377  func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
   378  	if h, ok := t.(tHelper); ok {
   379  		h.Helper()
   380  	}
   381  	return compareTwoValues(t, e1, e2, []CompareType{compareGreater, compareEqual}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...)
   382  }
   383  
   384  // Less asserts that the first element is less than the second
   385  //
   386  //	assert.Less(t, 1, 2)
   387  //	assert.Less(t, float64(1), float64(2))
   388  //	assert.Less(t, "a", "b")
   389  func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
   390  	if h, ok := t.(tHelper); ok {
   391  		h.Helper()
   392  	}
   393  	return compareTwoValues(t, e1, e2, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...)
   394  }
   395  
   396  // LessOrEqual asserts that the first element is less than or equal to the second
   397  //
   398  //	assert.LessOrEqual(t, 1, 2)
   399  //	assert.LessOrEqual(t, 2, 2)
   400  //	assert.LessOrEqual(t, "a", "b")
   401  //	assert.LessOrEqual(t, "b", "b")
   402  func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
   403  	if h, ok := t.(tHelper); ok {
   404  		h.Helper()
   405  	}
   406  	return compareTwoValues(t, e1, e2, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...)
   407  }
   408  
   409  // Positive asserts that the specified element is positive
   410  //
   411  //	assert.Positive(t, 1)
   412  //	assert.Positive(t, 1.23)
   413  func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) bool {
   414  	if h, ok := t.(tHelper); ok {
   415  		h.Helper()
   416  	}
   417  	zero := reflect.Zero(reflect.TypeOf(e))
   418  	return compareTwoValues(t, e, zero.Interface(), []CompareType{compareGreater}, "\"%v\" is not positive", msgAndArgs...)
   419  }
   420  
   421  // Negative asserts that the specified element is negative
   422  //
   423  //	assert.Negative(t, -1)
   424  //	assert.Negative(t, -1.23)
   425  func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) bool {
   426  	if h, ok := t.(tHelper); ok {
   427  		h.Helper()
   428  	}
   429  	zero := reflect.Zero(reflect.TypeOf(e))
   430  	return compareTwoValues(t, e, zero.Interface(), []CompareType{compareLess}, "\"%v\" is not negative", msgAndArgs...)
   431  }
   432  
   433  func compareTwoValues(t TestingT, e1 interface{}, e2 interface{}, allowedComparesResults []CompareType, failMessage string, msgAndArgs ...interface{}) bool {
   434  	if h, ok := t.(tHelper); ok {
   435  		h.Helper()
   436  	}
   437  
   438  	e1Kind := reflect.ValueOf(e1).Kind()
   439  	e2Kind := reflect.ValueOf(e2).Kind()
   440  	if e1Kind != e2Kind {
   441  		return Fail(t, "Elements should be the same type", msgAndArgs...)
   442  	}
   443  
   444  	compareResult, isComparable := compare(e1, e2, e1Kind)
   445  	if !isComparable {
   446  		return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...)
   447  	}
   448  
   449  	if !containsValue(allowedComparesResults, compareResult) {
   450  		return Fail(t, fmt.Sprintf(failMessage, e1, e2), msgAndArgs...)
   451  	}
   452  
   453  	return true
   454  }
   455  
   456  func containsValue(values []CompareType, value CompareType) bool {
   457  	for _, v := range values {
   458  		if v == value {
   459  			return true
   460  		}
   461  	}
   462  
   463  	return false
   464  }
   465  

View as plain text