github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/utils/reftracker/reftracker_test.go (about)

     1  /*
     2   * Copyright (C) 2021 The "MysteriumNetwork/node" Authors.
     3   *
     4   * This program is free software: you can redistribute it and/or modify
     5   * it under the terms of the GNU General Public License as published by
     6   * the Free Software Foundation, either version 3 of the License, or
     7   * (at your option) any later version.
     8   *
     9   * This program is distributed in the hope that it will be useful,
    10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12   * GNU General Public License for more details.
    13   *
    14   * You should have received a copy of the GNU General Public License
    15   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    16   */
    17  
    18  package reftracker
    19  
    20  import (
    21  	"testing"
    22  	"time"
    23  )
    24  
    25  const testPatrolPeriod = 10 * time.Millisecond
    26  
    27  func TestCollect(t *testing.T) {
    28  	tr := NewRefTracker(testPatrolPeriod)
    29  	defer tr.Close()
    30  
    31  	called := make(chan struct{})
    32  
    33  	tr.Put("1", 100*time.Millisecond, func() {
    34  		close(called)
    35  	})
    36  
    37  	time.Sleep(200 * time.Millisecond)
    38  	select {
    39  	case <-called:
    40  	default:
    41  		t.Error("release callback was not invoked")
    42  	}
    43  }
    44  
    45  func TestUseAndCollect(t *testing.T) {
    46  	tr := NewRefTracker(testPatrolPeriod)
    47  	defer tr.Close()
    48  
    49  	called := make(chan struct{})
    50  
    51  	tr.Put("1", 100*time.Millisecond, func() {
    52  		close(called)
    53  	})
    54  
    55  	time.Sleep(50 * time.Millisecond)
    56  
    57  	select {
    58  	case <-called:
    59  		t.Error("release callback was invoked too early")
    60  		return
    61  	default:
    62  	}
    63  
    64  	err := tr.Incr("1")
    65  	if err != nil {
    66  		t.Errorf("error: %v", err)
    67  		return
    68  	}
    69  
    70  	time.Sleep(200 * time.Millisecond)
    71  
    72  	select {
    73  	case <-called:
    74  		t.Error("release callback was invoked too early")
    75  		return
    76  	default:
    77  	}
    78  
    79  	tr.Decr("1")
    80  
    81  	time.Sleep(200 * time.Millisecond)
    82  	select {
    83  	case <-called:
    84  	default:
    85  		t.Error("release callback was not invoked")
    86  		return
    87  	}
    88  }
    89  
    90  func TestNegativeRefcountPanic(t *testing.T) {
    91  	var failedSuccessfully bool
    92  	tr := NewRefTracker(testPatrolPeriod)
    93  	defer tr.Close()
    94  
    95  	tr.Put("1", 2*time.Second, func() {})
    96  
    97  	func() {
    98  		defer func() {
    99  			if r := recover(); r != nil {
   100  				failedSuccessfully = true
   101  			}
   102  		}()
   103  		tr.Decr("1")
   104  	}()
   105  
   106  	if !failedSuccessfully {
   107  		t.Fail()
   108  	}
   109  }
   110  
   111  func TestPutIdempotent(t *testing.T) {
   112  	tr := NewRefTracker(testPatrolPeriod)
   113  	defer tr.Close()
   114  
   115  	called := make(chan struct{})
   116  
   117  	tr.Put("1", 100*time.Millisecond, func() {
   118  		close(called)
   119  	})
   120  	tr.Put("1", 1*time.Millisecond, func() {
   121  		t.Fail()
   122  	})
   123  
   124  	time.Sleep(200 * time.Millisecond)
   125  	select {
   126  	case <-called:
   127  	default:
   128  		t.Error("release callback was not invoked")
   129  	}
   130  }