...

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

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

     1  // Copyright (C) MongoDB, Inc. 2023-present.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License"); you may
     4  // not use this file except in compliance with the License. You may obtain
     5  // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
     6  
     7  // assertion_mongo.go contains MongoDB-specific extensions to the "assert"
     8  // package.
     9  
    10  package assert
    11  
    12  import (
    13  	"context"
    14  	"fmt"
    15  	"reflect"
    16  	"time"
    17  	"unsafe"
    18  )
    19  
    20  // DifferentAddressRanges asserts that two byte slices reference distinct memory
    21  // address ranges, meaning they reference different underlying byte arrays.
    22  func DifferentAddressRanges(t TestingT, a, b []byte) (ok bool) {
    23  	if h, ok := t.(tHelper); ok {
    24  		h.Helper()
    25  	}
    26  
    27  	if len(a) == 0 || len(b) == 0 {
    28  		return true
    29  	}
    30  
    31  	// Find the start and end memory addresses for the underlying byte array for
    32  	// each input byte slice.
    33  	sliceAddrRange := func(b []byte) (uintptr, uintptr) {
    34  		sh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
    35  		return sh.Data, sh.Data + uintptr(sh.Cap-1)
    36  	}
    37  	aStart, aEnd := sliceAddrRange(a)
    38  	bStart, bEnd := sliceAddrRange(b)
    39  
    40  	// If "b" starts after "a" ends or "a" starts after "b" ends, there is no
    41  	// overlap.
    42  	if bStart > aEnd || aStart > bEnd {
    43  		return true
    44  	}
    45  
    46  	// Otherwise, calculate the overlap start and end and print the memory
    47  	// overlap error message.
    48  	min := func(a, b uintptr) uintptr {
    49  		if a < b {
    50  			return a
    51  		}
    52  		return b
    53  	}
    54  	max := func(a, b uintptr) uintptr {
    55  		if a > b {
    56  			return a
    57  		}
    58  		return b
    59  	}
    60  	overlapLow := max(aStart, bStart)
    61  	overlapHigh := min(aEnd, bEnd)
    62  
    63  	t.Errorf("Byte slices point to the same underlying byte array:\n"+
    64  		"\ta addresses:\t%d ... %d\n"+
    65  		"\tb addresses:\t%d ... %d\n"+
    66  		"\toverlap:\t%d ... %d",
    67  		aStart, aEnd,
    68  		bStart, bEnd,
    69  		overlapLow, overlapHigh)
    70  
    71  	return false
    72  }
    73  
    74  // EqualBSON asserts that the expected and actual BSON binary values are equal.
    75  // If the values are not equal, it prints both the binary and Extended JSON diff
    76  // of the BSON values. The provided BSON value types must implement the
    77  // fmt.Stringer interface.
    78  func EqualBSON(t TestingT, expected, actual interface{}) bool {
    79  	if h, ok := t.(tHelper); ok {
    80  		h.Helper()
    81  	}
    82  
    83  	return Equal(t,
    84  		expected,
    85  		actual,
    86  		`expected and actual BSON values do not match
    87  As Extended JSON:
    88  Expected: %s
    89  Actual  : %s`,
    90  		expected.(fmt.Stringer).String(),
    91  		actual.(fmt.Stringer).String())
    92  }
    93  
    94  // Soon runs the provided callback and fails the passed-in test if the callback
    95  // does not complete within timeout. The provided callback should respect the
    96  // passed-in context and cease execution when it has expired.
    97  //
    98  // Deprecated: This function will be removed with GODRIVER-2667, use
    99  // assert.Eventually instead.
   100  func Soon(t TestingT, callback func(ctx context.Context), timeout time.Duration) {
   101  	if h, ok := t.(tHelper); ok {
   102  		h.Helper()
   103  	}
   104  
   105  	// Create context to manually cancel callback after Soon assertion.
   106  	callbackCtx, cancel := context.WithCancel(context.Background())
   107  	defer cancel()
   108  
   109  	done := make(chan struct{})
   110  	fullCallback := func() {
   111  		callback(callbackCtx)
   112  		done <- struct{}{}
   113  	}
   114  
   115  	timer := time.NewTimer(timeout)
   116  	defer timer.Stop()
   117  
   118  	go fullCallback()
   119  
   120  	select {
   121  	case <-done:
   122  		return
   123  	case <-timer.C:
   124  		t.Errorf("timed out in %s waiting for callback", timeout)
   125  	}
   126  }
   127  

View as plain text