github.com/wostzone/hub/auth@v0.0.0-20220118060317-7bb375743b17/pkg/unpwstore/PasswordFileStore_test.go (about)

     1  package unpwstore_test
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path"
     7  	"sync"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/sirupsen/logrus"
    12  	"github.com/stretchr/testify/assert"
    13  	"github.com/wostzone/hub/auth/pkg/unpwstore"
    14  	"github.com/wostzone/hub/lib/client/pkg/config"
    15  )
    16  
    17  const unpwFileName = "testunpwstore.passwd"
    18  
    19  var unpwFilePath string
    20  
    21  var configFolder string
    22  
    23  // TestMain for all auth tests, setup of default folders and filenames
    24  func TestMain(m *testing.M) {
    25  	config.SetLogging("info", "")
    26  	cwd, _ := os.Getwd()
    27  	homeFolder := path.Join(cwd, "../../test")
    28  	configFolder = path.Join(homeFolder, "config")
    29  
    30  	// Make sure ACL and password files exist
    31  	unpwFilePath = path.Join(configFolder, unpwFileName)
    32  	fp, _ := os.Create(unpwFilePath)
    33  	fp.Close()
    34  
    35  	res := m.Run()
    36  	os.Exit(res)
    37  }
    38  
    39  func TestOpenClosePWFile(t *testing.T) {
    40  	fp, _ := os.Create(unpwFilePath)
    41  	fp.Close()
    42  	unpwStore := unpwstore.NewPasswordFileStore(unpwFilePath, "TestOpenClosePWFile")
    43  	err := unpwStore.Open()
    44  	assert.NoError(t, err)
    45  	time.Sleep(time.Second * 1)
    46  	assert.NoError(t, err)
    47  	unpwStore.Close()
    48  }
    49  
    50  func TestSetPasswordTwoStores(t *testing.T) {
    51  	const user1 = "user1"
    52  	const user2 = "user2"
    53  	const hash1 = "hash1"
    54  	const hash2 = "hash2"
    55  	fp, _ := os.Create(unpwFilePath)
    56  	fp.Close()
    57  	// create 2 separate stores
    58  	pwStore1 := unpwstore.NewPasswordFileStore(unpwFilePath, "TestSetPasswordTwoStores-store1")
    59  	err := pwStore1.Open()
    60  	assert.NoError(t, err)
    61  	pwStore2 := unpwstore.NewPasswordFileStore(unpwFilePath, "TestSetPasswordTwoStores-Store2")
    62  	err = pwStore2.Open()
    63  	assert.NoError(t, err)
    64  
    65  	// set hash in store 1, should appear in store 2
    66  	err = pwStore1.SetPasswordHash(user1, hash1)
    67  	assert.NoError(t, err)
    68  	// wait for reload
    69  	time.Sleep(time.Second * 1)
    70  	// check mode of pw file
    71  	info, err := os.Stat(unpwFilePath)
    72  	assert.NoError(t, err)
    73  	mode := info.Mode()
    74  	assert.Equal(t, 0600, int(mode), "file mode not 0600")
    75  
    76  	// read back
    77  	// force reload. Don't want to wait
    78  	pwStore2.Reload()
    79  	hash := pwStore2.GetPasswordHash(user1)
    80  	assert.Equal(t, hash1, hash)
    81  
    82  	// do it again but in reverse
    83  	logrus.Infof("- do it again in reverse -")
    84  	err = pwStore2.SetPasswordHash(user2, hash2)
    85  	assert.NoError(t, err)
    86  	time.Sleep(time.Second * 2)
    87  	hash = pwStore1.GetPasswordHash(user2)
    88  	assert.Equal(t, hash2, hash)
    89  	// time.Sleep(time.Second * 1)
    90  
    91  	assert.NoError(t, err)
    92  	time.Sleep(time.Second * 1)
    93  	pwStore1.Close()
    94  	pwStore2.Close()
    95  }
    96  
    97  func TestNoPasswordFile(t *testing.T) {
    98  	pwFile := path.Join(configFolder, "missingpasswordfile")
    99  	pwStore := unpwstore.NewPasswordFileStore(pwFile, "TestNoPasswordFile")
   100  	err := pwStore.Open()
   101  	assert.Error(t, err)
   102  
   103  	pwStore.Close()
   104  }
   105  
   106  // Load test if one writer with second reader
   107  func TestConcurrentReadWrite(t *testing.T) {
   108  	var wg sync.WaitGroup
   109  	var i int
   110  
   111  	// start with empty file
   112  	fp, _ := os.Create(unpwFilePath)
   113  	fp.Close()
   114  
   115  	// two stores in parallel
   116  	pwStore1 := unpwstore.NewPasswordFileStore(unpwFilePath, "TestConcurrentReadWrite-store1 (writer)")
   117  	err := pwStore1.Open()
   118  	assert.NoError(t, err)
   119  	pwStore2 := unpwstore.NewPasswordFileStore(unpwFilePath, "TestConcurrentReadWrite-store2 (reader)")
   120  	err = pwStore2.Open()
   121  	assert.NoError(t, err)
   122  
   123  	wg.Add(1)
   124  	go func() {
   125  		for i = 0; i < 30; i++ {
   126  			thingID := fmt.Sprintf("thing-%d", i)
   127  			err2 := pwStore1.SetPasswordHash(thingID, "hash1")
   128  			time.Sleep(time.Millisecond * 1)
   129  			if err2 != nil {
   130  				assert.NoError(t, err2)
   131  			}
   132  		}
   133  		wg.Done()
   134  	}()
   135  	wg.Wait()
   136  	// time to catch up the file watcher debouncing
   137  	time.Sleep(time.Second * 2)
   138  
   139  	// both stores should be fully up to date
   140  	assert.Equal(t, i, pwStore1.Count())
   141  	assert.Equal(t, i, pwStore2.Count())
   142  
   143  	//
   144  	pwStore1.Close()
   145  	pwStore2.Close()
   146  }
   147  
   148  func TestWritePwToTempFail(t *testing.T) {
   149  	pws := make(map[string]string)
   150  	pwStore1 := unpwstore.NewPasswordFileStore(unpwFilePath, "TestWritePwToTempFail")
   151  	err := pwStore1.Open()
   152  	assert.NoError(t, err)
   153  	_, err = unpwstore.WritePasswordsToTempFile("/badfolder", pws)
   154  	assert.Error(t, err)
   155  	pwStore1.Close()
   156  }