// Copyright 2015 The Vanadium 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 benchmark

import (
	"testing"
	"time"

	"v.io/v23"
	"v.io/v23/naming"
	"v.io/v23/options"
	"v.io/v23/security"

	_ "v.io/x/ref/runtime/factories/static"
	"v.io/x/ref/runtime/internal/rpc/stream/manager"
	"v.io/x/ref/runtime/internal/rpc/stream/vc"
	"v.io/x/ref/test"
	"v.io/x/ref/test/benchmark"
	"v.io/x/ref/test/testutil"
)

// benchmarkDialVC measures VC creation time over the underlying VIF.
func benchmarkDialVC(b *testing.B, mode options.SecurityLevel) {
	ctx, shutdown := test.V23Init()
	defer shutdown()

	stats := benchmark.AddStats(b, 16)

	server := manager.InternalNew(ctx, naming.FixedRoutingID(0x5))
	client := manager.InternalNew(ctx, naming.FixedRoutingID(0xc))
	var (
		principal security.Principal
		blessings security.Blessings
	)
	if mode == securityDefault {
		principal = testutil.NewPrincipal("test")
		blessings = principal.BlessingStore().Default()
		ctx, _ = v23.WithPrincipal(ctx, principal)
	}

	_, ep, err := server.Listen(ctx, "tcp", "127.0.0.1:0", blessings)

	if err != nil {
		b.Fatal(err)
	}

	// Create one VC to prevent the underlying VIF from being closed.
	_, err = client.Dial(ctx, ep, vc.IdleTimeout{0})
	if err != nil {
		b.Fatal(err)
	}

	b.ResetTimer() // Exclude setup time from measurement.

	for i := 0; i < b.N; i++ {
		b.StartTimer()
		start := time.Now()

		VC, err := client.Dial(ctx, ep)
		if err != nil {
			b.Fatal(err)
		}

		duration := time.Since(start)
		b.StopTimer()

		stats.Add(duration)

		VC.Close(nil)
	}

	client.Shutdown()
	server.Shutdown()
}
