go.dedis.ch/onet/v3@v3.2.11-0.20210930124529-e36530bca7ef/context_test.go (about)

     1  package onet
     2  
     3  import (
     4  	"crypto/sha256"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"os"
     8  	"path"
     9  	"strings"
    10  	"sync"
    11  	"testing"
    12  
    13  	"github.com/stretchr/testify/require"
    14  	"go.dedis.ch/kyber/v3/util/key"
    15  	"go.dedis.ch/onet/v3/log"
    16  	"go.dedis.ch/onet/v3/network"
    17  	bbolt "go.etcd.io/bbolt"
    18  	"golang.org/x/xerrors"
    19  )
    20  
    21  type ContextData struct {
    22  	I int64
    23  	S string
    24  }
    25  
    26  func TestContextSaveLoad(t *testing.T) {
    27  	tmp, err := ioutil.TempDir("", "conode")
    28  	defer os.RemoveAll(tmp)
    29  	os.Setenv("CONODE_SERVICE_PATH", tmp)
    30  	p := dbPathFromEnv()
    31  	require.Equal(t, p, tmp)
    32  
    33  	nbr := 10
    34  	c := make([]*Context, nbr)
    35  	for i := range c {
    36  		c[i] = createContext(t, p)
    37  	}
    38  
    39  	testSaveFailure(t, c[0])
    40  
    41  	var wg sync.WaitGroup
    42  	wg.Add(nbr)
    43  	for i := range c {
    44  		go func(i int) {
    45  			// defer insures the call even on a panic
    46  			defer wg.Done()
    47  			testLoadSave(t, c[i])
    48  		}(i)
    49  	}
    50  	wg.Wait()
    51  	files, err := ioutil.ReadDir(tmp)
    52  	log.ErrFatal(err)
    53  	require.False(t, files[0].IsDir())
    54  	require.True(t, files[0].Mode().IsRegular())
    55  	require.True(t, strings.HasSuffix(files[0].Name(), ".db"))
    56  
    57  	v, err := c[0].LoadVersion()
    58  	require.Nil(t, err)
    59  	require.Equal(t, 0, v)
    60  	err = c[0].SaveVersion(1)
    61  	require.Nil(t, err)
    62  	v, err = c[0].LoadVersion()
    63  	require.Nil(t, err)
    64  	require.Equal(t, 1, v)
    65  }
    66  
    67  func testLoadSave(t *testing.T, c *Context) {
    68  	key := []byte("test")
    69  	cd := &ContextData{42, "meaning of life"}
    70  	network.RegisterMessage(ContextData{})
    71  	require.Nil(t, c.Save(key, cd))
    72  
    73  	msg, err := c.Load(append(key, byte('_')))
    74  	if err != nil || msg != nil {
    75  		log.Fatal("this should not exist")
    76  	}
    77  	cdInt, err := c.Load(key)
    78  	require.Nil(t, err)
    79  	cd2, ok := cdInt.(*ContextData)
    80  	if !ok {
    81  		log.Fatal("contextData should exist")
    82  	}
    83  
    84  	cdBuf, err := c.LoadRaw(key)
    85  	require.Nil(t, err)
    86  	cdBuf2, err := network.Marshal(cd)
    87  	require.EqualValues(t, cdBuf, cdBuf2)
    88  
    89  	if cd.I != cd2.I || cd.S != cd2.S {
    90  		log.Fatal("stored and loaded data should be equal", cd, cd2)
    91  	}
    92  }
    93  
    94  func testSaveFailure(t *testing.T, c *Context) {
    95  	key := []byte("test")
    96  	cd := &ContextData{42, "meaning of life"}
    97  	// should fail because ContextData is not registered
    98  	if c.Save(key, cd) == nil {
    99  		log.Fatal("Save should fail")
   100  	}
   101  }
   102  
   103  func TestContext_GetAdditionalBucket(t *testing.T) {
   104  	tmp, err := ioutil.TempDir("", "conode")
   105  	log.ErrFatal(err)
   106  	defer os.RemoveAll(tmp)
   107  
   108  	c := createContext(t, tmp)
   109  	db, name := c.GetAdditionalBucket([]byte("new"))
   110  	require.NotNil(t, db)
   111  	require.Equal(t, "testService_new", string(name))
   112  	// Need to accept a second run with an existing bucket
   113  	db, name = c.GetAdditionalBucket([]byte("new"))
   114  	require.NotNil(t, db)
   115  	require.Equal(t, "testService_new", string(name))
   116  }
   117  
   118  func TestContext_Path(t *testing.T) {
   119  	tmp, err := ioutil.TempDir("", "conode")
   120  	log.ErrFatal(err)
   121  	defer os.RemoveAll(tmp)
   122  
   123  	c := createContext(t, tmp)
   124  	pub, _ := c.ServerIdentity().Public.MarshalBinary()
   125  	h := sha256.New()
   126  	h.Write(pub)
   127  	dbPath := path.Join(tmp, fmt.Sprintf("%x.db", h.Sum(nil)))
   128  	_, err = os.Stat(dbPath)
   129  	if err != nil {
   130  		t.Error(err)
   131  	}
   132  	os.Remove(dbPath)
   133  
   134  	tmp, err = ioutil.TempDir("", "conode")
   135  	log.ErrFatal(err)
   136  	defer os.RemoveAll(tmp)
   137  
   138  	c = createContext(t, tmp)
   139  
   140  	_, err = os.Stat(tmp)
   141  	log.ErrFatal(err)
   142  	pub, _ = c.ServerIdentity().Public.MarshalBinary()
   143  	h = sha256.New()
   144  	h.Write(pub)
   145  	_, err = os.Stat(path.Join(tmp, fmt.Sprintf("%x.db", h.Sum(nil))))
   146  	log.ErrFatal(err)
   147  }
   148  
   149  // createContext creates the minimum number of things required for the test
   150  func createContext(t *testing.T, dbPath string) *Context {
   151  	kp := key.NewKeyPair(tSuite)
   152  	si := network.NewServerIdentity(kp.Public,
   153  		network.NewAddress(network.Local, "localhost:0"))
   154  	cn := &Server{
   155  		Router: &network.Router{
   156  			ServerIdentity: si,
   157  		},
   158  	}
   159  
   160  	name := "testService"
   161  	RegisterNewService(name, func(c *Context) (Service, error) {
   162  		return nil, nil
   163  	})
   164  
   165  	sm := &serviceManager{
   166  		server: cn,
   167  		dbPath: dbPath,
   168  	}
   169  
   170  	db, err := openDb(sm.dbFileName())
   171  	require.Nil(t, err)
   172  
   173  	err = db.Update(func(tx *bbolt.Tx) error {
   174  		_, err := tx.CreateBucket([]byte(name))
   175  		if err != nil {
   176  			return xerrors.Errorf("creating bucket: %v", err)
   177  		}
   178  		return nil
   179  	})
   180  	require.Nil(t, err)
   181  	sm.db = db
   182  
   183  	return newContext(cn, nil, ServiceFactory.ServiceID(name), sm)
   184  }