godev/internal/storage: skip TestGCStore when there is no network

And let gcsemu.NewServer bind to an any open port instead of assuming
a specific port 8081 is available.

godev/internal/testenv is a partial copy of
golang.org/x/tools/internal/testenv.

Fixes golang/go#60533
Fixes golang/go#60534

Change-Id: I715b4b73094e6ebddb8be6a8279a73669d54ec11
Reviewed-on: https://go-review.googlesource.com/c/telemetry/+/499596
Run-TryBot: Hyang-Ah Hana Kim <hyangah@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Bryan Mills <bcmills@google.com>
Auto-Submit: Hyang-Ah Hana Kim <hyangah@gmail.com>
diff --git a/godev/internal/storage/storage_test.go b/godev/internal/storage/storage_test.go
index 74a6692..c0bf2f9 100644
--- a/godev/internal/storage/storage_test.go
+++ b/godev/internal/storage/storage_test.go
@@ -13,6 +13,7 @@
 
 	"github.com/fullstorydev/emulators/storage/gcsemu"
 	"github.com/google/go-cmp/cmp"
+	"golang.org/x/telemetry/godev/internal/testenv"
 )
 
 type jsondata struct {
@@ -28,17 +29,19 @@
 }
 
 func TestGCStore(t *testing.T) {
-	err := os.Setenv("STORAGE_EMULATOR_HOST", "localhost:8081")
-	if err != nil {
-		t.Fatal(err)
-	}
+	testenv.NeedsLocalhostNet(t)
 
-	server, err := gcsemu.NewServer("localhost:8081", gcsemu.Options{})
+	server, err := gcsemu.NewServer("localhost:0", gcsemu.Options{})
 	if err != nil {
 		t.Fatal(err)
 	}
 	defer server.Close()
 
+	addr := server.Addr
+	if err := os.Setenv("STORAGE_EMULATOR_HOST", addr); err != nil {
+		t.Fatal(err)
+	}
+
 	ctx := context.Background()
 	s, err := NewGCStore(ctx, "go-test-project", "test-bucket")
 	if err != nil {
diff --git a/godev/internal/testenv/testenv.go b/godev/internal/testenv/testenv.go
new file mode 100644
index 0000000..bd56ac0
--- /dev/null
+++ b/godev/internal/testenv/testenv.go
@@ -0,0 +1,21 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package testenv contains helper functions for skipping tests
+// based on which tools are present in the environment.
+package testenv
+
+import (
+	"runtime"
+	"testing"
+)
+
+// NeedsLocalhostNet skips t if networking does not work for ports opened
+// with "localhost".
+func NeedsLocalhostNet(t testing.TB) {
+	switch runtime.GOOS {
+	case "js", "wasip1":
+		t.Skipf(`Listening on "localhost" fails on %s; see https://go.dev/issue/59718`, runtime.GOOS)
+	}
+}