internal/postgres: test upsertPaths concurrently

Add a test that looks for problems executing upsertPaths concurrently.

Change-Id: Ifb18f81b937ad115a248ef57cd76c86bb1e5ac40
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/296552
Trust: Jonathan Amsterdam <jba@google.com>
Run-TryBot: Jonathan Amsterdam <jba@google.com>
TryBot-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Jamal Carvalho <jamal@golang.org>
Reviewed-by: Julie Qiu <julie@golang.org>
diff --git a/internal/postgres/path_test.go b/internal/postgres/path_test.go
index 9ce6497..f169f87 100644
--- a/internal/postgres/path_test.go
+++ b/internal/postgres/path_test.go
@@ -8,6 +8,7 @@
 	"context"
 	"database/sql"
 	"errors"
+	"fmt"
 	"strconv"
 	"strings"
 	"testing"
@@ -165,6 +166,45 @@
 	}
 }
 
+func TestUpsertPathsConcurrently(t *testing.T) {
+	// Verify that we get no constraint violations or other errors when
+	// the same set of paths is upserted multiple times concurrently.
+	t.Parallel()
+	testDB, release := acquire(t)
+	defer release()
+	ctx := context.Background()
+
+	const n = 10
+	paths := make([]string, 100)
+	for i := 0; i < len(paths); i++ {
+		paths[i] = fmt.Sprintf("p%d", i)
+	}
+	errc := make(chan error, n)
+	for i := 0; i < n; i++ {
+		i := i
+		go func() {
+			start := (10 * i) % len(paths)
+			end := start + 50
+			if end > len(paths) {
+				end = len(paths)
+			}
+			sub := paths[start:end]
+			got, err := upsertPathsInTx(ctx, testDB.db, sub)
+			if err == nil {
+				checkPathMap(t, got, sub)
+
+			}
+			errc <- err
+		}()
+
+	}
+	for i := 0; i < n; i++ {
+		if err := <-errc; err != nil {
+			t.Fatal(err)
+		}
+	}
+}
+
 func upsertPathsInTx(ctx context.Context, db *database.DB, paths []string) (map[string]int, error) {
 	var m map[string]int
 	err := db.Transact(ctx, sql.LevelRepeatableRead, func(tx *database.DB) error {