git.sr.ht/~pingoo/stdx@v0.0.0-20240218134121-094174641f6e/singleinstance/singleinstance_unix_test.go (about)

     1  //go:build !windows
     2  
     3  package singleinstance_test
     4  
     5  import (
     6  	"os"
     7  	"syscall"
     8  	"testing"
     9  
    10  	"git.sr.ht/~pingoo/stdx/singleinstance"
    11  	"github.com/stretchr/testify/assert"
    12  	"github.com/stretchr/testify/require"
    13  )
    14  
    15  func TestSingle(t *testing.T) {
    16  	s := singleinstance.New("unittest")
    17  	require.NotNil(t, s)
    18  
    19  	t.Logf("Lockfile: %s", s.Lockfile())
    20  
    21  	err := s.Lock()
    22  	assert.NoError(t, err)
    23  
    24  	assert.EqualError(t, checkLock(s), singleinstance.ErrAlreadyRunning.Error())
    25  
    26  	err = s.Unlock()
    27  	assert.NoError(t, err)
    28  }
    29  
    30  func checkLock(s *singleinstance.SingleInstance) error {
    31  	f, err := os.OpenFile(s.Lockfile(), os.O_RDONLY, 0600)
    32  	if err != nil {
    33  		return err
    34  	}
    35  
    36  	// try to obtain an exclusive lock with the PPID
    37  
    38  	flock := syscall.Flock_t{
    39  		Type: syscall.F_WRLCK,
    40  		Pid:  int32(os.Getppid()),
    41  	}
    42  
    43  	if err := syscall.FcntlFlock(f.Fd(), syscall.F_SETLK, &flock); err != nil {
    44  		return singleinstance.ErrAlreadyRunning
    45  	}
    46  
    47  	return nil
    48  }