...

Source file src/go.mongodb.org/mongo-driver/internal/uuid/uuid_test.go

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

     1  // Copyright (C) MongoDB, Inc. 2022-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  package uuid
     8  
     9  import (
    10  	"sync"
    11  	"testing"
    12  
    13  	"go.mongodb.org/mongo-driver/internal/israce"
    14  	"go.mongodb.org/mongo-driver/internal/require"
    15  )
    16  
    17  // GODRIVER-2349
    18  // Test that initializing many package-global UUID sources concurrently never leads to any duplicate
    19  // UUIDs being generated.
    20  func TestGlobalSource(t *testing.T) {
    21  	t.Parallel()
    22  
    23  	t.Run("exp rand 1 UUID x 1,000,000 goroutines using a global source", func(t *testing.T) {
    24  		t.Parallel()
    25  
    26  		if israce.Enabled {
    27  			t.Skip("skipping as race detector is enabled and test exceeds 8128 goroutine limit")
    28  		}
    29  
    30  		// Read a UUID from each of 1,000,000 goroutines and assert that there is never a duplicate value.
    31  		const iterations = 1e6
    32  		uuids := new(sync.Map)
    33  		var wg sync.WaitGroup
    34  		wg.Add(iterations)
    35  		for i := 0; i < iterations; i++ {
    36  			go func(i int) {
    37  				defer wg.Done()
    38  				uuid, err := New()
    39  				require.NoError(t, err, "new() error")
    40  				_, ok := uuids.Load(uuid)
    41  				require.Falsef(t, ok, "New returned a duplicate UUID on iteration %d: %v", i, uuid)
    42  				uuids.Store(uuid, true)
    43  			}(i)
    44  		}
    45  		wg.Wait()
    46  	})
    47  	t.Run("exp rand 1 UUID x 1,000,000 goroutines each initializing a new source", func(t *testing.T) {
    48  		t.Parallel()
    49  
    50  		if israce.Enabled {
    51  			t.Skip("skipping as race detector is enabled and test exceeds 8128 goroutine limit")
    52  		}
    53  
    54  		// Read a UUID from each of 1,000,000 goroutines and assert that there is never a duplicate value.
    55  		// The goal is to emulate many separate Go driver processes starting at the same time and
    56  		// initializing the uuid package at the same time.
    57  		const iterations = 1e6
    58  		uuids := new(sync.Map)
    59  		var wg sync.WaitGroup
    60  		wg.Add(iterations)
    61  		for i := 0; i < iterations; i++ {
    62  			go func(i int) {
    63  				defer wg.Done()
    64  				s := newSource()
    65  				uuid, err := s.new()
    66  				require.NoError(t, err, "new() error")
    67  				_, ok := uuids.Load(uuid)
    68  				require.Falsef(t, ok, "New returned a duplicate UUID on iteration %d: %v", i, uuid)
    69  				uuids.Store(uuid, true)
    70  			}(i)
    71  		}
    72  		wg.Wait()
    73  	})
    74  	t.Run("exp rand 1,000 UUIDs x 1,000 goroutines each initializing a new source", func(t *testing.T) {
    75  		t.Parallel()
    76  
    77  		// Read 1,000 UUIDs from each goroutine and assert that there is never a duplicate value, either
    78  		// from the same goroutine or from separate goroutines.
    79  		const iterations = 1000
    80  		uuids := new(sync.Map)
    81  		var wg sync.WaitGroup
    82  		wg.Add(iterations)
    83  		for i := 0; i < iterations; i++ {
    84  			go func(i int) {
    85  				defer wg.Done()
    86  				s := newSource()
    87  				for j := 0; j < iterations; j++ {
    88  					uuid, err := s.new()
    89  					require.NoError(t, err, "new() error")
    90  					_, ok := uuids.Load(uuid)
    91  					require.Falsef(t, ok, "goroutine %d returned a duplicate UUID on iteration %d: %v", i, j, uuid)
    92  					uuids.Store(uuid, true)
    93  				}
    94  			}(i)
    95  		}
    96  		wg.Wait()
    97  	})
    98  }
    99  
   100  func BenchmarkUuidGeneration(b *testing.B) {
   101  	for i := 0; i < b.N; i++ {
   102  		_, err := New()
   103  		if err != nil {
   104  			panic(err)
   105  		}
   106  	}
   107  }
   108  

View as plain text