github.com/matrixorigin/matrixone@v1.2.0/pkg/txn/clock/hlc_test.go (about)

     1  // Copyright 2022 Matrix Origin
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  // http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package clock
    16  
    17  import (
    18  	"context"
    19  	"testing"
    20  	"time"
    21  
    22  	"github.com/matrixorigin/matrixone/pkg/pb/timestamp"
    23  	"github.com/stretchr/testify/assert"
    24  )
    25  
    26  type Timestamp = timestamp.Timestamp
    27  
    28  func TestToMicrosecond(t *testing.T) {
    29  	assert.Equal(t, int64(1), toMicrosecond(1000))
    30  }
    31  
    32  func TestPhysicalClockReturnsNanoseconds(t *testing.T) {
    33  	v1 := physicalClock()
    34  	time.Sleep(1 * time.Microsecond)
    35  	v2 := physicalClock()
    36  	assert.True(t, v2-v1 >= 1e3)
    37  }
    38  
    39  func TestSkipClockUncertainityPeriodOnRestart(t *testing.T) {
    40  	ctx, cancel := context.WithCancel(context.Background())
    41  	defer cancel()
    42  	// maxOffset below has to be set to a relatively large value, we repeatedly
    43  	// saw cpu starvations of several milliseconds in tests running on github
    44  	// actions.
    45  	c := NewUnixNanoHLCClock(ctx, 500*time.Millisecond)
    46  	v1 := physicalClock()
    47  	SkipClockUncertainityPeriodOnRestart(ctx, c)
    48  	v2 := physicalClock()
    49  	assert.True(t, v2-v1 >= 500*1e6)
    50  }
    51  
    52  func TestNewHLCClock(t *testing.T) {
    53  	c := NewHLCClock(physicalClock, time.Second)
    54  	assert.Equal(t, time.Second, c.maxOffset)
    55  }
    56  
    57  func TestNewUnixNanoHLCClock(t *testing.T) {
    58  	v := physicalClock()
    59  	ctx, cancel := context.WithCancel(context.Background())
    60  	defer cancel()
    61  	c := NewUnixNanoHLCClock(ctx, 500*time.Millisecond)
    62  	result, _ := c.Now()
    63  	assert.True(t, v < result.PhysicalTime)
    64  }
    65  
    66  func TestMaxClockForwardOffset(t *testing.T) {
    67  	c := NewHLCClock(physicalClock, 2*time.Second)
    68  	assert.Equal(t, time.Second, c.maxClockForwardOffset())
    69  }
    70  
    71  func TestKeepPhysicalClock(t *testing.T) {
    72  	c := NewHLCClock(physicalClock, time.Second)
    73  	c.mu.maxLearnedPhysicalTime = 1234
    74  	result := c.keepPhysicalClock(1233)
    75  	assert.Equal(t, int64(1234), result)
    76  	assert.Equal(t, int64(1234), c.mu.maxLearnedPhysicalTime)
    77  
    78  	result = c.keepPhysicalClock(1235)
    79  	assert.Equal(t, int64(1234), result)
    80  	assert.Equal(t, int64(1235), c.mu.maxLearnedPhysicalTime)
    81  }
    82  
    83  func TestGetPhysicalClock(t *testing.T) {
    84  	pc := func() int64 {
    85  		return 200
    86  	}
    87  	c := NewHLCClock(pc, time.Second)
    88  	c.mu.maxLearnedPhysicalTime = 123
    89  	result := c.getPhysicalClock()
    90  	assert.Equal(t, int64(200), result)
    91  	assert.Equal(t, int64(200), c.mu.maxLearnedPhysicalTime)
    92  
    93  	c.mu.maxLearnedPhysicalTime = 300
    94  	result = c.getPhysicalClock()
    95  	assert.Equal(t, int64(200), result)
    96  	assert.Equal(t, int64(300), c.mu.maxLearnedPhysicalTime)
    97  }
    98  
    99  func TestNow(t *testing.T) {
   100  	pc := func() int64 {
   101  		return 200
   102  	}
   103  	c := NewHLCClock(pc, time.Second)
   104  
   105  	c.mu.ts = Timestamp{PhysicalTime: 100, LogicalTime: 10}
   106  	result, _ := c.Now()
   107  	assert.Equal(t, Timestamp{PhysicalTime: 200}, result)
   108  
   109  	c.mu.ts = Timestamp{PhysicalTime: 300, LogicalTime: 10}
   110  	result, _ = c.Now()
   111  	assert.Equal(t, Timestamp{PhysicalTime: 300, LogicalTime: 11}, result)
   112  
   113  	result, upperBound := c.Now()
   114  	assert.Equal(t, result.PhysicalTime+int64(c.MaxOffset()), upperBound.PhysicalTime)
   115  	assert.Equal(t, uint32(0), upperBound.LogicalTime)
   116  }
   117  
   118  func TestUpdate(t *testing.T) {
   119  	pc := func() int64 {
   120  		return 200
   121  	}
   122  	c := NewHLCClock(pc, time.Second)
   123  
   124  	// pt is the max
   125  	c.mu.ts = Timestamp{PhysicalTime: 100, LogicalTime: 10}
   126  	c.Update(Timestamp{PhysicalTime: 120})
   127  	assert.Equal(t, Timestamp{PhysicalTime: 200}, c.mu.ts)
   128  
   129  	c.physicalClock = func() int64 { return 50 }
   130  	// m has the same physical time and greater logical time
   131  	c.mu.ts = Timestamp{PhysicalTime: 100, LogicalTime: 10}
   132  	c.Update(Timestamp{PhysicalTime: 100, LogicalTime: 100})
   133  	assert.Equal(t, Timestamp{PhysicalTime: 100, LogicalTime: 100}, c.mu.ts)
   134  
   135  	// m has the largest physical time
   136  	c.mu.ts = Timestamp{PhysicalTime: 100, LogicalTime: 10}
   137  	m := Timestamp{PhysicalTime: 120, LogicalTime: 100}
   138  	c.Update(m)
   139  	assert.Equal(t, m, c.mu.ts)
   140  
   141  	// m has smaller physical time
   142  	c.mu.ts = Timestamp{PhysicalTime: 100, LogicalTime: 10}
   143  	old := c.mu.ts
   144  	c.Update(Timestamp{PhysicalTime: 99, LogicalTime: 100})
   145  	assert.Equal(t, old, c.mu.ts)
   146  }