github.com/joincivil/go-ethereum@v1.8.23/ethdb/database_test.go (about)

     1  // Copyright 2014 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser 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  // The go-ethereum library 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 Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // +build !js
    18  
    19  package ethdb_test
    20  
    21  import (
    22  	"bytes"
    23  	"fmt"
    24  	"io/ioutil"
    25  	"os"
    26  	"strconv"
    27  	"sync"
    28  	"testing"
    29  
    30  	"github.com/ethereum/go-ethereum/ethdb"
    31  )
    32  
    33  func newTestLDB() (*ethdb.LDBDatabase, func()) {
    34  	dirname, err := ioutil.TempDir(os.TempDir(), "ethdb_test_")
    35  	if err != nil {
    36  		panic("failed to create test file: " + err.Error())
    37  	}
    38  	db, err := ethdb.NewLDBDatabase(dirname, 0, 0)
    39  	if err != nil {
    40  		panic("failed to create test database: " + err.Error())
    41  	}
    42  
    43  	return db, func() {
    44  		db.Close()
    45  		os.RemoveAll(dirname)
    46  	}
    47  }
    48  
    49  var test_values = []string{"", "a", "1251", "\x00123\x00"}
    50  
    51  func TestLDB_PutGet(t *testing.T) {
    52  	db, remove := newTestLDB()
    53  	defer remove()
    54  	testPutGet(db, t)
    55  }
    56  
    57  func TestMemoryDB_PutGet(t *testing.T) {
    58  	testPutGet(ethdb.NewMemDatabase(), t)
    59  }
    60  
    61  func testPutGet(db ethdb.Database, t *testing.T) {
    62  	t.Parallel()
    63  
    64  	for _, k := range test_values {
    65  		err := db.Put([]byte(k), nil)
    66  		if err != nil {
    67  			t.Fatalf("put failed: %v", err)
    68  		}
    69  	}
    70  
    71  	for _, k := range test_values {
    72  		data, err := db.Get([]byte(k))
    73  		if err != nil {
    74  			t.Fatalf("get failed: %v", err)
    75  		}
    76  		if len(data) != 0 {
    77  			t.Fatalf("get returned wrong result, got %q expected nil", string(data))
    78  		}
    79  	}
    80  
    81  	_, err := db.Get([]byte("non-exist-key"))
    82  	if err == nil {
    83  		t.Fatalf("expect to return a not found error")
    84  	}
    85  
    86  	for _, v := range test_values {
    87  		err := db.Put([]byte(v), []byte(v))
    88  		if err != nil {
    89  			t.Fatalf("put failed: %v", err)
    90  		}
    91  	}
    92  
    93  	for _, v := range test_values {
    94  		data, err := db.Get([]byte(v))
    95  		if err != nil {
    96  			t.Fatalf("get failed: %v", err)
    97  		}
    98  		if !bytes.Equal(data, []byte(v)) {
    99  			t.Fatalf("get returned wrong result, got %q expected %q", string(data), v)
   100  		}
   101  	}
   102  
   103  	for _, v := range test_values {
   104  		err := db.Put([]byte(v), []byte("?"))
   105  		if err != nil {
   106  			t.Fatalf("put override failed: %v", err)
   107  		}
   108  	}
   109  
   110  	for _, v := range test_values {
   111  		data, err := db.Get([]byte(v))
   112  		if err != nil {
   113  			t.Fatalf("get failed: %v", err)
   114  		}
   115  		if !bytes.Equal(data, []byte("?")) {
   116  			t.Fatalf("get returned wrong result, got %q expected ?", string(data))
   117  		}
   118  	}
   119  
   120  	for _, v := range test_values {
   121  		orig, err := db.Get([]byte(v))
   122  		if err != nil {
   123  			t.Fatalf("get failed: %v", err)
   124  		}
   125  		orig[0] = byte(0xff)
   126  		data, err := db.Get([]byte(v))
   127  		if err != nil {
   128  			t.Fatalf("get failed: %v", err)
   129  		}
   130  		if !bytes.Equal(data, []byte("?")) {
   131  			t.Fatalf("get returned wrong result, got %q expected ?", string(data))
   132  		}
   133  	}
   134  
   135  	for _, v := range test_values {
   136  		err := db.Delete([]byte(v))
   137  		if err != nil {
   138  			t.Fatalf("delete %q failed: %v", v, err)
   139  		}
   140  	}
   141  
   142  	for _, v := range test_values {
   143  		_, err := db.Get([]byte(v))
   144  		if err == nil {
   145  			t.Fatalf("got deleted value %q", v)
   146  		}
   147  	}
   148  }
   149  
   150  func TestLDB_ParallelPutGet(t *testing.T) {
   151  	db, remove := newTestLDB()
   152  	defer remove()
   153  	testParallelPutGet(db, t)
   154  }
   155  
   156  func TestMemoryDB_ParallelPutGet(t *testing.T) {
   157  	testParallelPutGet(ethdb.NewMemDatabase(), t)
   158  }
   159  
   160  func testParallelPutGet(db ethdb.Database, t *testing.T) {
   161  	const n = 8
   162  	var pending sync.WaitGroup
   163  
   164  	pending.Add(n)
   165  	for i := 0; i < n; i++ {
   166  		go func(key string) {
   167  			defer pending.Done()
   168  			err := db.Put([]byte(key), []byte("v"+key))
   169  			if err != nil {
   170  				panic("put failed: " + err.Error())
   171  			}
   172  		}(strconv.Itoa(i))
   173  	}
   174  	pending.Wait()
   175  
   176  	pending.Add(n)
   177  	for i := 0; i < n; i++ {
   178  		go func(key string) {
   179  			defer pending.Done()
   180  			data, err := db.Get([]byte(key))
   181  			if err != nil {
   182  				panic("get failed: " + err.Error())
   183  			}
   184  			if !bytes.Equal(data, []byte("v"+key)) {
   185  				panic(fmt.Sprintf("get failed, got %q expected %q", []byte(data), []byte("v"+key)))
   186  			}
   187  		}(strconv.Itoa(i))
   188  	}
   189  	pending.Wait()
   190  
   191  	pending.Add(n)
   192  	for i := 0; i < n; i++ {
   193  		go func(key string) {
   194  			defer pending.Done()
   195  			err := db.Delete([]byte(key))
   196  			if err != nil {
   197  				panic("delete failed: " + err.Error())
   198  			}
   199  		}(strconv.Itoa(i))
   200  	}
   201  	pending.Wait()
   202  
   203  	pending.Add(n)
   204  	for i := 0; i < n; i++ {
   205  		go func(key string) {
   206  			defer pending.Done()
   207  			_, err := db.Get([]byte(key))
   208  			if err == nil {
   209  				panic("get succeeded")
   210  			}
   211  		}(strconv.Itoa(i))
   212  	}
   213  	pending.Wait()
   214  }