| 
									
										
										
										
											2019-02-07 18:40:26 +01:00
										 |  |  | // Copyright 2018 The go-ethereum Authors | 
					
						
							|  |  |  | // This file is part of the go-ethereum library. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  | // it under the terms of the GNU Lesser General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							|  |  |  | // GNU Lesser General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU Lesser General Public License | 
					
						
							|  |  |  | // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package localstore | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"io/ioutil" | 
					
						
							|  |  |  | 	"math/rand" | 
					
						
							|  |  |  | 	"os" | 
					
						
							|  |  |  | 	"testing" | 
					
						
							|  |  |  | 	"time" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-26 16:09:32 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/swarm/chunk" | 
					
						
							| 
									
										
										
										
											2019-02-07 18:40:26 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // TestDB_collectGarbageWorker tests garbage collection runs | 
					
						
							|  |  |  | // by uploading and syncing a number of chunks. | 
					
						
							|  |  |  | func TestDB_collectGarbageWorker(t *testing.T) { | 
					
						
							|  |  |  | 	testDB_collectGarbageWorker(t) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // TestDB_collectGarbageWorker_multipleBatches tests garbage | 
					
						
							|  |  |  | // collection runs by uploading and syncing a number of | 
					
						
							|  |  |  | // chunks by having multiple smaller batches. | 
					
						
							|  |  |  | func TestDB_collectGarbageWorker_multipleBatches(t *testing.T) { | 
					
						
							|  |  |  | 	// lower the maximal number of chunks in a single | 
					
						
							|  |  |  | 	// gc batch to ensure multiple batches. | 
					
						
							| 
									
										
										
										
											2019-03-09 00:06:39 +01:00
										 |  |  | 	defer func(s uint64) { gcBatchSize = s }(gcBatchSize) | 
					
						
							| 
									
										
										
										
											2019-02-07 18:40:26 +01:00
										 |  |  | 	gcBatchSize = 2 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	testDB_collectGarbageWorker(t) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // testDB_collectGarbageWorker is a helper test function to test | 
					
						
							|  |  |  | // garbage collection runs by uploading and syncing a number of chunks. | 
					
						
							|  |  |  | func testDB_collectGarbageWorker(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2019-02-20 22:57:42 +01:00
										 |  |  | 	t.Helper() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-07 18:40:26 +01:00
										 |  |  | 	chunkCount := 150 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	db, cleanupFunc := newTestDB(t, &Options{ | 
					
						
							|  |  |  | 		Capacity: 100, | 
					
						
							|  |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2019-03-09 00:06:39 +01:00
										 |  |  | 	testHookCollectGarbageChan := make(chan uint64) | 
					
						
							|  |  |  | 	defer setTestHookCollectGarbage(func(collectedCount uint64) { | 
					
						
							| 
									
										
										
										
											2019-03-04 22:19:57 +01:00
										 |  |  | 		select { | 
					
						
							|  |  |  | 		case testHookCollectGarbageChan <- collectedCount: | 
					
						
							|  |  |  | 		case <-db.close: | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	})() | 
					
						
							| 
									
										
										
										
											2019-02-07 18:40:26 +01:00
										 |  |  | 	defer cleanupFunc() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	uploader := db.NewPutter(ModePutUpload) | 
					
						
							|  |  |  | 	syncer := db.NewSetter(ModeSetSync) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-26 16:09:32 +01:00
										 |  |  | 	addrs := make([]chunk.Address, 0) | 
					
						
							| 
									
										
										
										
											2019-02-07 18:40:26 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// upload random chunks | 
					
						
							|  |  |  | 	for i := 0; i < chunkCount; i++ { | 
					
						
							| 
									
										
										
										
											2019-02-26 16:09:32 +01:00
										 |  |  | 		chunk := generateTestRandomChunk() | 
					
						
							| 
									
										
										
										
											2019-02-07 18:40:26 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		err := uploader.Put(chunk) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		err = syncer.Set(chunk.Address()) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		addrs = append(addrs, chunk.Address()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	gcTarget := db.gcTarget() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		select { | 
					
						
							|  |  |  | 		case <-testHookCollectGarbageChan: | 
					
						
							|  |  |  | 		case <-time.After(10 * time.Second): | 
					
						
							|  |  |  | 			t.Error("collect garbage timeout") | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-09 00:06:39 +01:00
										 |  |  | 		gcSize, err := db.gcSize.Get() | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-02-07 18:40:26 +01:00
										 |  |  | 		if gcSize == gcTarget { | 
					
						
							|  |  |  | 			break | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("pull index count", newItemsCountTest(db.pullIndex, int(gcTarget))) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("gc index count", newItemsCountTest(db.gcIndex, int(gcTarget))) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("gc size", newIndexGCSizeTest(db)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// the first synced chunk should be removed | 
					
						
							|  |  |  | 	t.Run("get the first synced chunk", func(t *testing.T) { | 
					
						
							|  |  |  | 		_, err := db.NewGetter(ModeGetRequest).Get(addrs[0]) | 
					
						
							| 
									
										
										
										
											2019-02-26 16:09:32 +01:00
										 |  |  | 		if err != chunk.ErrChunkNotFound { | 
					
						
							|  |  |  | 			t.Errorf("got error %v, want %v", err, chunk.ErrChunkNotFound) | 
					
						
							| 
									
										
										
										
											2019-02-07 18:40:26 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// last synced chunk should not be removed | 
					
						
							|  |  |  | 	t.Run("get most recent synced chunk", func(t *testing.T) { | 
					
						
							|  |  |  | 		_, err := db.NewGetter(ModeGetRequest).Get(addrs[len(addrs)-1]) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // TestDB_collectGarbageWorker_withRequests is a helper test function | 
					
						
							|  |  |  | // to test garbage collection runs by uploading, syncing and | 
					
						
							|  |  |  | // requesting a number of chunks. | 
					
						
							|  |  |  | func TestDB_collectGarbageWorker_withRequests(t *testing.T) { | 
					
						
							|  |  |  | 	db, cleanupFunc := newTestDB(t, &Options{ | 
					
						
							|  |  |  | 		Capacity: 100, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	defer cleanupFunc() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	uploader := db.NewPutter(ModePutUpload) | 
					
						
							|  |  |  | 	syncer := db.NewSetter(ModeSetSync) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-09 00:06:39 +01:00
										 |  |  | 	testHookCollectGarbageChan := make(chan uint64) | 
					
						
							|  |  |  | 	defer setTestHookCollectGarbage(func(collectedCount uint64) { | 
					
						
							| 
									
										
										
										
											2019-02-07 18:40:26 +01:00
										 |  |  | 		testHookCollectGarbageChan <- collectedCount | 
					
						
							|  |  |  | 	})() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-26 16:09:32 +01:00
										 |  |  | 	addrs := make([]chunk.Address, 0) | 
					
						
							| 
									
										
										
										
											2019-02-07 18:40:26 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// upload random chunks just up to the capacity | 
					
						
							|  |  |  | 	for i := 0; i < int(db.capacity)-1; i++ { | 
					
						
							| 
									
										
										
										
											2019-02-26 16:09:32 +01:00
										 |  |  | 		chunk := generateTestRandomChunk() | 
					
						
							| 
									
										
										
										
											2019-02-07 18:40:26 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		err := uploader.Put(chunk) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		err = syncer.Set(chunk.Address()) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		addrs = append(addrs, chunk.Address()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-26 16:09:32 +01:00
										 |  |  | 	// set update gc test hook to signal when | 
					
						
							|  |  |  | 	// update gc goroutine is done by closing | 
					
						
							|  |  |  | 	// testHookUpdateGCChan channel | 
					
						
							|  |  |  | 	testHookUpdateGCChan := make(chan struct{}) | 
					
						
							|  |  |  | 	resetTestHookUpdateGC := setTestHookUpdateGC(func() { | 
					
						
							|  |  |  | 		close(testHookUpdateGCChan) | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-07 18:40:26 +01:00
										 |  |  | 	// request the latest synced chunk | 
					
						
							|  |  |  | 	// to prioritize it in the gc index | 
					
						
							|  |  |  | 	// not to be collected | 
					
						
							|  |  |  | 	_, err := db.NewGetter(ModeGetRequest).Get(addrs[0]) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-26 16:09:32 +01:00
										 |  |  | 	// wait for update gc goroutine to finish for garbage | 
					
						
							|  |  |  | 	// collector to be correctly triggered after the last upload | 
					
						
							|  |  |  | 	select { | 
					
						
							|  |  |  | 	case <-testHookUpdateGCChan: | 
					
						
							|  |  |  | 	case <-time.After(10 * time.Second): | 
					
						
							|  |  |  | 		t.Fatal("updateGC was not called after getting chunk with ModeGetRequest") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// no need to wait for update gc hook anymore | 
					
						
							|  |  |  | 	resetTestHookUpdateGC() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-07 18:40:26 +01:00
										 |  |  | 	// upload and sync another chunk to trigger | 
					
						
							|  |  |  | 	// garbage collection | 
					
						
							| 
									
										
										
										
											2019-02-26 16:09:32 +01:00
										 |  |  | 	ch := generateTestRandomChunk() | 
					
						
							|  |  |  | 	err = uploader.Put(ch) | 
					
						
							| 
									
										
										
										
											2019-02-07 18:40:26 +01:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-02-26 16:09:32 +01:00
										 |  |  | 	err = syncer.Set(ch.Address()) | 
					
						
							| 
									
										
										
										
											2019-02-07 18:40:26 +01:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-02-26 16:09:32 +01:00
										 |  |  | 	addrs = append(addrs, ch.Address()) | 
					
						
							| 
									
										
										
										
											2019-02-07 18:40:26 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// wait for garbage collection | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	gcTarget := db.gcTarget() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-09 00:06:39 +01:00
										 |  |  | 	var totalCollectedCount uint64 | 
					
						
							| 
									
										
										
										
											2019-02-07 18:40:26 +01:00
										 |  |  | 	for { | 
					
						
							|  |  |  | 		select { | 
					
						
							|  |  |  | 		case c := <-testHookCollectGarbageChan: | 
					
						
							|  |  |  | 			totalCollectedCount += c | 
					
						
							|  |  |  | 		case <-time.After(10 * time.Second): | 
					
						
							|  |  |  | 			t.Error("collect garbage timeout") | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-09 00:06:39 +01:00
										 |  |  | 		gcSize, err := db.gcSize.Get() | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-02-07 18:40:26 +01:00
										 |  |  | 		if gcSize == gcTarget { | 
					
						
							|  |  |  | 			break | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-09 00:06:39 +01:00
										 |  |  | 	wantTotalCollectedCount := uint64(len(addrs)) - gcTarget | 
					
						
							| 
									
										
										
										
											2019-02-07 18:40:26 +01:00
										 |  |  | 	if totalCollectedCount != wantTotalCollectedCount { | 
					
						
							|  |  |  | 		t.Errorf("total collected chunks %v, want %v", totalCollectedCount, wantTotalCollectedCount) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("pull index count", newItemsCountTest(db.pullIndex, int(gcTarget))) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("gc index count", newItemsCountTest(db.gcIndex, int(gcTarget))) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("gc size", newIndexGCSizeTest(db)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// requested chunk should not be removed | 
					
						
							|  |  |  | 	t.Run("get requested chunk", func(t *testing.T) { | 
					
						
							|  |  |  | 		_, err := db.NewGetter(ModeGetRequest).Get(addrs[0]) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// the second synced chunk should be removed | 
					
						
							|  |  |  | 	t.Run("get gc-ed chunk", func(t *testing.T) { | 
					
						
							|  |  |  | 		_, err := db.NewGetter(ModeGetRequest).Get(addrs[1]) | 
					
						
							| 
									
										
										
										
											2019-02-26 16:09:32 +01:00
										 |  |  | 		if err != chunk.ErrChunkNotFound { | 
					
						
							|  |  |  | 			t.Errorf("got error %v, want %v", err, chunk.ErrChunkNotFound) | 
					
						
							| 
									
										
										
										
											2019-02-07 18:40:26 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// last synced chunk should not be removed | 
					
						
							|  |  |  | 	t.Run("get most recent synced chunk", func(t *testing.T) { | 
					
						
							|  |  |  | 		_, err := db.NewGetter(ModeGetRequest).Get(addrs[len(addrs)-1]) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // TestDB_gcSize checks if gcSize has a correct value after | 
					
						
							|  |  |  | // database is initialized with existing data. | 
					
						
							|  |  |  | func TestDB_gcSize(t *testing.T) { | 
					
						
							|  |  |  | 	dir, err := ioutil.TempDir("", "localstore-stored-gc-size") | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	defer os.RemoveAll(dir) | 
					
						
							|  |  |  | 	baseKey := make([]byte, 32) | 
					
						
							|  |  |  | 	if _, err := rand.Read(baseKey); err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	db, err := New(dir, baseKey, nil) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	uploader := db.NewPutter(ModePutUpload) | 
					
						
							|  |  |  | 	syncer := db.NewSetter(ModeSetSync) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	count := 100 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for i := 0; i < count; i++ { | 
					
						
							| 
									
										
										
										
											2019-02-26 16:09:32 +01:00
										 |  |  | 		chunk := generateTestRandomChunk() | 
					
						
							| 
									
										
										
										
											2019-02-07 18:40:26 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		err := uploader.Put(chunk) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		err = syncer.Set(chunk.Address()) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-09 00:06:39 +01:00
										 |  |  | 	if err := db.Close(); err != nil { | 
					
						
							| 
									
										
										
										
											2019-02-07 18:40:26 +01:00
										 |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	db, err = New(dir, baseKey, nil) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-02-22 23:19:09 +01:00
										 |  |  | 	defer db.Close() | 
					
						
							| 
									
										
										
										
											2019-02-07 18:40:26 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("gc index size", newIndexGCSizeTest(db)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // setTestHookCollectGarbage sets testHookCollectGarbage and | 
					
						
							|  |  |  | // returns a function that will reset it to the | 
					
						
							|  |  |  | // value before the change. | 
					
						
							| 
									
										
										
										
											2019-03-09 00:06:39 +01:00
										 |  |  | func setTestHookCollectGarbage(h func(collectedCount uint64)) (reset func()) { | 
					
						
							| 
									
										
										
										
											2019-02-07 18:40:26 +01:00
										 |  |  | 	current := testHookCollectGarbage | 
					
						
							|  |  |  | 	reset = func() { testHookCollectGarbage = current } | 
					
						
							|  |  |  | 	testHookCollectGarbage = h | 
					
						
							|  |  |  | 	return reset | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // TestSetTestHookCollectGarbage tests if setTestHookCollectGarbage changes | 
					
						
							|  |  |  | // testHookCollectGarbage function correctly and if its reset function | 
					
						
							|  |  |  | // resets the original function. | 
					
						
							|  |  |  | func TestSetTestHookCollectGarbage(t *testing.T) { | 
					
						
							|  |  |  | 	// Set the current function after the test finishes. | 
					
						
							| 
									
										
										
										
											2019-03-09 00:06:39 +01:00
										 |  |  | 	defer func(h func(collectedCount uint64)) { testHookCollectGarbage = h }(testHookCollectGarbage) | 
					
						
							| 
									
										
										
										
											2019-02-07 18:40:26 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// expected value for the unchanged function | 
					
						
							|  |  |  | 	original := 1 | 
					
						
							|  |  |  | 	// expected value for the changed function | 
					
						
							|  |  |  | 	changed := 2 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// this variable will be set with two different functions | 
					
						
							|  |  |  | 	var got int | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// define the original (unchanged) functions | 
					
						
							| 
									
										
										
										
											2019-03-09 00:06:39 +01:00
										 |  |  | 	testHookCollectGarbage = func(_ uint64) { | 
					
						
							| 
									
										
										
										
											2019-02-07 18:40:26 +01:00
										 |  |  | 		got = original | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// set got variable | 
					
						
							|  |  |  | 	testHookCollectGarbage(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// test if got variable is set correctly | 
					
						
							|  |  |  | 	if got != original { | 
					
						
							|  |  |  | 		t.Errorf("got hook value %v, want %v", got, original) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// set the new function | 
					
						
							| 
									
										
										
										
											2019-03-09 00:06:39 +01:00
										 |  |  | 	reset := setTestHookCollectGarbage(func(_ uint64) { | 
					
						
							| 
									
										
										
										
											2019-02-07 18:40:26 +01:00
										 |  |  | 		got = changed | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// set got variable | 
					
						
							|  |  |  | 	testHookCollectGarbage(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// test if got variable is set correctly to changed value | 
					
						
							|  |  |  | 	if got != changed { | 
					
						
							|  |  |  | 		t.Errorf("got hook value %v, want %v", got, changed) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// set the function to the original one | 
					
						
							|  |  |  | 	reset() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// set got variable | 
					
						
							|  |  |  | 	testHookCollectGarbage(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// test if got variable is set correctly to original value | 
					
						
							|  |  |  | 	if got != original { | 
					
						
							|  |  |  | 		t.Errorf("got hook value %v, want %v", got, original) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |