From 57849844ae7d12373c9e91d1a39b70c773cccd71 Mon Sep 17 00:00:00 2001 From: Matt Joiner Date: Tue, 26 Jun 2018 19:54:48 +1000 Subject: [PATCH] Rework status export in tests to allow count > 1 without a server for every test --- .circleci/config.yml | 2 +- client_test.go | 22 +++++------ fs/torrentfs_test.go | 2 +- internal/testutil/status_writer.go | 63 +++++++++++++++--------------- 4 files changed, 43 insertions(+), 46 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d01aafdc..464d417e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -22,7 +22,7 @@ jobs: - run: sudo apt-get update - run: sudo apt install fuse pv - run: go get -t -d -v -race $PROJECT_GO_PACKAGE/... - - run: go test -v -race $PROJECT_GO_PACKAGE/... + - run: go test -v -race $PROJECT_GO_PACKAGE/... -count 2 - run: go test -bench . $PROJECT_GO_PACKAGE/... - run: CGO_ENABLED=0 go get -t -d -v $PROJECT_GO_PACKAGE/... - run: set +e; CGO_ENABLED=0 go test -v $PROJECT_GO_PACKAGE/...; true diff --git a/client_test.go b/client_test.go index 7921f90c..76893d73 100644 --- a/client_test.go +++ b/client_test.go @@ -311,7 +311,7 @@ func testClientTransfer(t *testing.T, ps testClientTransferParams) { seeder, err := NewClient(cfg) require.NoError(t, err) if ps.ExportClientStatus { - testutil.ExportStatusWriter(seeder, "s") + defer testutil.ExportStatusWriter(seeder, "s")() } seederTorrent, _, _ := seeder.AddTorrentSpec(TorrentSpecFromMetaInfo(mi)) // Run a Stats right after Closing the Client. This will trigger the Stats @@ -337,7 +337,7 @@ func testClientTransfer(t *testing.T, ps testClientTransferParams) { require.NoError(t, err) defer leecher.Close() if ps.ExportClientStatus { - testutil.ExportStatusWriter(leecher, "l") + defer testutil.ExportStatusWriter(leecher, "l")() } leecherTorrent, new, err := leecher.AddTorrentSpec(func() (ret *TorrentSpec) { ret = TorrentSpecFromMetaInfo(mi) @@ -396,7 +396,7 @@ func TestSeedAfterDownloading(t *testing.T) { seeder, err := NewClient(cfg) require.NoError(t, err) defer seeder.Close() - testutil.ExportStatusWriter(seeder, "s") + defer testutil.ExportStatusWriter(seeder, "s")() seederTorrent, ok, err := seeder.AddTorrentSpec(TorrentSpecFromMetaInfo(mi)) require.NoError(t, err) assert.True(t, ok) @@ -410,7 +410,7 @@ func TestSeedAfterDownloading(t *testing.T) { leecher, err := NewClient(cfg) require.NoError(t, err) defer leecher.Close() - testutil.ExportStatusWriter(leecher, "l") + defer testutil.ExportStatusWriter(leecher, "l")() cfg = TestingConfig() cfg.Seed = false @@ -420,7 +420,7 @@ func TestSeedAfterDownloading(t *testing.T) { leecherLeecher, _ := NewClient(cfg) require.NoError(t, err) defer leecherLeecher.Close() - testutil.ExportStatusWriter(leecherLeecher, "ll") + defer testutil.ExportStatusWriter(leecherLeecher, "ll")() leecherGreeting, ok, err := leecher.AddTorrentSpec(func() (ret *TorrentSpec) { ret = TorrentSpecFromMetaInfo(mi) ret.ChunkSize = 2 @@ -769,7 +769,7 @@ func testDownloadCancel(t *testing.T, ps testDownloadCancelParams) { seeder, err := NewClient(cfg) require.NoError(t, err) defer seeder.Close() - testutil.ExportStatusWriter(seeder, "s") + defer testutil.ExportStatusWriter(seeder, "s")() seederTorrent, _, _ := seeder.AddTorrentSpec(TorrentSpecFromMetaInfo(mi)) seederTorrent.VerifyData() leecherDataDir, err := ioutil.TempDir("", "") @@ -784,7 +784,7 @@ func testDownloadCancel(t *testing.T, ps testDownloadCancelParams) { cfg.DataDir = leecherDataDir leecher, _ := NewClient(cfg) defer leecher.Close() - testutil.ExportStatusWriter(leecher, "l") + defer testutil.ExportStatusWriter(leecher, "l")() leecherGreeting, new, err := leecher.AddTorrentSpec(func() (ret *TorrentSpec) { ret = TorrentSpecFromMetaInfo(mi) ret.ChunkSize = 2 @@ -930,8 +930,6 @@ func totalConns(tts []*Torrent) (ret int) { } func TestSetMaxEstablishedConn(t *testing.T) { - ss := testutil.NewStatusServer(t) - defer ss.Close() var tts []*Torrent ih := testutil.GreetingMetaInfo().HashInfoBytes() cfg := TestingConfig() @@ -943,7 +941,7 @@ func TestSetMaxEstablishedConn(t *testing.T) { defer cl.Close() tt, _ := cl.AddTorrentInfoHash(ih) tt.SetMaxEstablishedConns(2) - ss.HandleStatusWriter(cl, fmt.Sprintf("/%d", i)) + defer testutil.ExportStatusWriter(cl, fmt.Sprintf("%d", i))() tts = append(tts, tt) } addPeers := func() { @@ -1007,7 +1005,7 @@ func TestMultipleTorrentsWithEncryption(t *testing.T) { server, err := NewClient(cfg) require.NoError(t, err) defer server.Close() - testutil.ExportStatusWriter(server, "s") + defer testutil.ExportStatusWriter(server, "s")() magnet1 := makeMagnet(t, server, cfg.DataDir, "test1") makeMagnet(t, server, cfg.DataDir, "test2") cfg = TestingConfig() @@ -1017,7 +1015,7 @@ func TestMultipleTorrentsWithEncryption(t *testing.T) { client, err := NewClient(cfg) require.NoError(t, err) defer client.Close() - testutil.ExportStatusWriter(client, "c") + defer testutil.ExportStatusWriter(client, "c")() tr, err := client.AddMagnet(magnet1) require.NoError(t, err) tr.AddClientPeer(server) diff --git a/fs/torrentfs_test.go b/fs/torrentfs_test.go index 8ac69bb7..fb326cc5 100644 --- a/fs/torrentfs_test.go +++ b/fs/torrentfs_test.go @@ -174,7 +174,7 @@ func TestDownloadOnDemand(t *testing.T) { seeder, err := torrent.NewClient(cfg) require.NoError(t, err) defer seeder.Close() - testutil.ExportStatusWriter(seeder, "s") + defer testutil.ExportStatusWriter(seeder, "s")() // Just to mix things up, the seeder starts with the data, but the leecher // starts with the metainfo. seederTorrent, err := seeder.AddMagnet(fmt.Sprintf("magnet:?xt=urn:btih:%s", layout.Metainfo.HashInfoBytes().HexString())) diff --git a/internal/testutil/status_writer.go b/internal/testutil/status_writer.go index 0266e3eb..5ce66c61 100644 --- a/internal/testutil/status_writer.go +++ b/internal/testutil/status_writer.go @@ -3,51 +3,50 @@ package testutil import ( "fmt" "io" - "log" - "net" "net/http" - "testing" + "sync" "github.com/anacrolix/missinggo" - "github.com/stretchr/testify/require" ) type StatusWriter interface { WriteStatus(io.Writer) } -// Use StatusServer instead to allow -count > 1 when testing. -func ExportStatusWriter(sw StatusWriter, path string) { +// The key is the route pattern. The value is nil when the resource is +// released. +var ( + mu sync.Mutex + sws = map[string]StatusWriter{} +) + +func ExportStatusWriter(sw StatusWriter, path string) (release func()) { + pattern := fmt.Sprintf("/%s/%s", missinggo.GetTestName(), path) + release = func() { + mu.Lock() + defer mu.Unlock() + sws[pattern] = nil + } + mu.Lock() + defer mu.Unlock() + if curSw, ok := sws[pattern]; ok { + if curSw != nil { + panic(fmt.Sprintf("%q still in use", pattern)) + } + sws[pattern] = sw + return + } http.HandleFunc( - fmt.Sprintf("/%s/%s", missinggo.GetTestName(), path), + pattern, func(w http.ResponseWriter, r *http.Request) { + sw := sws[pattern] + if sw == nil { + http.NotFound(w, r) + return + } sw.WriteStatus(w) }, ) -} - -type StatusServer struct { - sm http.ServeMux - l net.Listener -} - -func NewStatusServer(t *testing.T) (ret *StatusServer) { - l, err := net.Listen("tcp", "localhost:0") - require.NoError(t, err) - ret = &StatusServer{ - l: l, - } - log.Printf("serving status at %q", l.Addr()) - go http.Serve(l, &ret.sm) + sws[pattern] = sw return } - -func (me *StatusServer) HandleStatusWriter(sw StatusWriter, path string) { - me.sm.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) { - sw.WriteStatus(w) - }) -} - -func (me StatusServer) Close() { - me.l.Close() -} -- 2.44.0