blob: 5021c8506815c4dd49341004665f0eb81dbd0d91 [file] [log] [blame]
// 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 global
import (
"fmt"
"testing"
"time"
"v.io/v23"
"v.io/v23/discovery"
"v.io/v23/options"
"v.io/v23/security"
"v.io/x/ref/lib/discovery/testutil"
_ "v.io/x/ref/runtime/factories/generic"
"v.io/x/ref/services/mounttable/mounttablelib"
"v.io/x/ref/test"
"v.io/x/ref/test/timekeeper"
)
const testPath = "a/b/c"
func TestBasic(t *testing.T) {
ctx, shutdown := test.V23InitWithMounttable()
defer shutdown()
ads := []discovery.Advertisement{
{
Id: discovery.AdId{1, 2, 3},
InterfaceName: "foo/bar/baz",
Addresses: []string{"/h1:123/x", "/h2:123/y"},
Attributes: discovery.Attributes{"k": "v"},
},
{
InterfaceName: "foo/bar/baz",
Addresses: []string{"/h1:123/x", "/h2:123/z"},
},
}
d1, err := New(ctx, testPath)
if err != nil {
t.Fatal(err)
}
var stops []func()
for i, _ := range ads {
stop, err := testutil.Advertise(ctx, d1, nil, &ads[i])
if err != nil {
t.Fatal(err)
}
stops = append(stops, stop)
}
// Make sure none of advertisements are discoverable by the same discovery instance.
if err := testutil.ScanAndMatch(ctx, d1, ``); err != nil {
t.Error(err)
}
// Create a new discovery instance. All advertisements should be discovered with that.
d2, err := NewWithTTL(ctx, testPath, 0, 1*time.Millisecond)
if err != nil {
t.Fatal(err)
}
if err := testutil.ScanAndMatch(ctx, d2, `k="01020300000000000000000000000000"`, ads[0]); err != nil {
t.Error(err)
}
if err := testutil.ScanAndMatch(ctx, d2, fmt.Sprintf(`k="%s"`, ads[1].Id), ads[1]); err != nil {
t.Error(err)
}
if err := testutil.ScanAndMatch(ctx, d2, ``, ads...); err != nil {
t.Error(err)
}
if err := testutil.ScanAndMatch(ctx, d2, `k="not_exist"`); err != nil {
t.Error(err)
}
// Open a new scan channel and consume expected advertisements first.
scanCh, scanStop, err := testutil.Scan(ctx, d2, fmt.Sprintf(`k="%s"`, ads[0].Id))
if err != nil {
t.Fatal(err)
}
defer scanStop()
update := <-scanCh
if !testutil.MatchFound(ctx, []discovery.Update{update}, ads[0]) {
t.Errorf("unexpected scan: %v", update)
}
// Make sure scan returns the lost advertisement when advertising is stopped.
stops[0]()
update = <-scanCh
if !testutil.MatchLost(ctx, []discovery.Update{update}, ads[0]) {
t.Errorf("unexpected scan: %v", update)
}
// Also it shouldn't affect the other.
if err := testutil.ScanAndMatch(ctx, d2, fmt.Sprintf(`k="%s"`, ads[1].Id), ads[1]); err != nil {
t.Error(err)
}
// Stop advertising the remaining one; Shouldn't discover any service.
stops[1]()
if err := testutil.ScanAndMatch(ctx, d2, ``); err != nil {
t.Error(err)
}
}
func TestVisibility(t *testing.T) {
ctx, shutdown := test.V23InitWithMounttable()
defer shutdown()
ad := discovery.Advertisement{
InterfaceName: "foo/bar/baz",
Addresses: []string{"/h1:123/x"},
}
visibility := []security.BlessingPattern{
security.BlessingPattern("test-blessing:bob"),
security.BlessingPattern("test-blessing:alice").MakeNonExtendable(),
}
d1, _ := New(ctx, testPath)
mectx, _ := testutil.WithPrincipal(ctx, "me")
stop, _ := testutil.Advertise(mectx, d1, visibility, &ad)
defer stop()
d2, _ := NewWithTTL(ctx, testPath, 0, 1*time.Millisecond)
// Bob and his friend should discover the advertisement.
bobctx, _ := testutil.WithPrincipal(ctx, "bob")
if err := testutil.ScanAndMatch(bobctx, d2, ``, ad); err != nil {
t.Error(err)
}
bobfriendctx, _ := testutil.WithPrincipal(ctx, "bob:friend")
if err := testutil.ScanAndMatch(bobfriendctx, d2, ``, ad); err != nil {
t.Error(err)
}
// Alice should discover the advertisement, but her friend shouldn't.
alicectx, _ := testutil.WithPrincipal(ctx, "alice")
if err := testutil.ScanAndMatch(alicectx, d2, ``, ad); err != nil {
t.Error(err)
}
alicefriendctx, _ := testutil.WithPrincipal(ctx, "alice:friend")
if err := testutil.ScanAndMatch(alicefriendctx, d2, ``); err != nil {
t.Error(err)
}
// Other people shouldn't discover the advertisement.
carolctx, _ := testutil.WithPrincipal(ctx, "carol")
if err := testutil.ScanAndMatch(carolctx, d2, ``); err != nil {
t.Error(err)
}
}
func TestDuplicates(t *testing.T) {
ctx, shutdown := test.V23InitWithMounttable()
defer shutdown()
ad := discovery.Advertisement{
InterfaceName: "foo/bar/baz",
Addresses: []string{"/h1:123/x"},
}
d, _ := New(ctx, testPath)
stop, _ := testutil.Advertise(ctx, d, nil, &ad)
defer stop()
if _, err := testutil.Advertise(ctx, d, nil, &ad); err == nil {
t.Error("expect an error; but got none")
}
}
func TestRefresh(t *testing.T) {
ctx, shutdown := test.V23Init()
defer shutdown()
clock := timekeeper.NewManualTime()
mt, err := mounttablelib.NewMountTableDispatcherWithClock(ctx, "", "", "", clock)
if err != nil {
t.Fatal(err)
}
_, mtserver, err := v23.WithNewDispatchingServer(ctx, "", mt, options.ServesMountTable(true))
if err != nil {
t.Fatal(err)
}
ns := v23.GetNamespace(ctx)
ns.SetRoots(mtserver.Status().Endpoints[0].Name())
ad := discovery.Advertisement{
InterfaceName: "foo/bar/baz",
Addresses: []string{"/h1:123/x"},
}
const mountTTL = 10 * time.Second
d1, _ := newWithClock(ctx, testPath, mountTTL, 0, clock)
stop, _ := testutil.Advertise(ctx, d1, nil, &ad)
defer stop()
d2, _ := NewWithTTL(ctx, testPath, 0, 1*time.Millisecond)
if err := testutil.ScanAndMatch(ctx, d2, ``, ad); err != nil {
t.Error(err)
}
// Make sure that the advertisement are refreshed on every ttl time.
for i := 0; i < 5; i++ {
<-clock.Requests()
clock.AdvanceTime(mountTTL * 2)
if err := testutil.ScanAndMatch(ctx, d2, ``, ad); err != nil {
t.Error(err)
}
}
}