예제 #1
0
func TestGetFirstRangeDescriptor(t *testing.T) {
	n := gossip.NewSimulationNetwork(3, "unix", gossip.DefaultTestGossipInterval)
	kv := NewDistKV(n.Nodes[0].Gossip)
	if _, err := kv.getFirstRangeDescriptor(); err == nil {
		t.Errorf("expected not to find first range descriptor")
	}
	expectedDesc := &proto.RangeDescriptor{}
	expectedDesc.StartKey = engine.Key("a")
	expectedDesc.EndKey = engine.Key("c")

	// Add first RangeDescriptor to a node different from the node for this kv
	// and ensure that this kv has the information within a given time.
	n.Nodes[1].Gossip.AddInfo(
		gossip.KeyFirstRangeMetadata, *expectedDesc, time.Hour)
	maxCycles := 10
	n.SimulateNetwork(func(cycle int, network *gossip.SimulationNetwork) bool {
		desc, err := kv.getFirstRangeDescriptor()
		if err != nil {
			if cycle >= maxCycles {
				t.Errorf("could not get range descriptor after %d cycles", cycle)
				return false
			}
			return true
		}
		if !bytes.Equal(desc.StartKey, expectedDesc.StartKey) ||
			!bytes.Equal(desc.EndKey, expectedDesc.EndKey) {
			t.Errorf("expected first range descriptor %v, instead was %v",
				expectedDesc, desc)
		}
		return false
	})
	n.Stop()
}
예제 #2
0
func main() {
	// Seed the random number generator for non-determinism across
	// multiple runs.
	rand.Seed(time.Now().UTC().UnixNano())

	if f := flag.Lookup("alsologtostderr"); f != nil {
		fmt.Println("Starting simulation. Add -alsologtostderr to see progress.")
	}
	flag.Parse()

	dirName, err := ioutil.TempDir("", "gossip-simulation-")
	if err != nil {
		log.Fatalf("could not create temporary directory for gossip simulation output: %s", err)
	}

	// Simulation callbacks to run the simulation for cycleCount
	// cycles. At each cycle % outputEvery, a dot file showing the
	// state of the network graph is output.
	nodeCount := 3
	gossipInterval := simGossipInterval
	numCycles := 10
	outputEvery := 1
	switch *size {
	case "tiny":
		// Use default parameters.
	case "small":
		nodeCount = 10
	case "medium":
		nodeCount = 25
	case "large":
		nodeCount = 50
		gossipInterval = time.Millisecond * 250
	case "huge":
		nodeCount = 100
		gossipInterval = time.Second
		numCycles = 20
		outputEvery = 2
	case "ginormous":
		nodeCount = 250
		gossipInterval = time.Second * 3
		numCycles = 20
		outputEvery = 2
	default:
		log.Fatalf("unknown simulation size: %s", *size)
	}

	edgeSet := make(map[string]edge)

	n := gossip.NewSimulationNetwork(nodeCount, *networkType, gossipInterval)
	n.SimulateNetwork(
		func(cycle int, network *gossip.SimulationNetwork) bool {
			if cycle == numCycles {
				return false
			}
			// Update infos.
			nodes := network.Nodes
			for i := 0; i < len(nodes); i++ {
				node := nodes[i].Gossip
				if err := node.AddInfo(nodes[i].Addr.String(), int64(cycle), time.Hour); err != nil {
					log.Infof("error updating infos addr: %s cycle: %v: %s",
						nodes[i].Addr.String(), cycle, err)
				}
			}
			// Output dot graph periodically.
			if (cycle+1)%outputEvery == 0 {
				dotFN := fmt.Sprintf("%s/sim-cycle-%d.dot", dirName, cycle)
				outputDotFile(dotFN, cycle, network, edgeSet)
			}

			return true
		})
	n.Stop()

	// Output instructions for viewing graphs.
	fmt.Printf("To view simulation graph output run (you must install graphviz):\n\nfor f in %s/*.dot ; do circo $f -Tpng -o $f.png ; echo $f.png ; done\n", dirName)
}
예제 #3
0
func TestVerifyPermissions(t *testing.T) {
	n := gossip.NewSimulationNetwork(1, "unix", gossip.DefaultTestGossipInterval)
	kv := NewDistKV(n.Nodes[0].Gossip)
	config1 := &proto.PermConfig{
		Read:  []string{"read1", "readAll", "rw", "rwAll"},
		Write: []string{"write1", "writeAll", "rw", "rwAll"}}
	config2 := &proto.PermConfig{
		Read:  []string{"read2", "readAll", "rw2", "rwAll"},
		Write: []string{"write2", "writeAll", "rw2", "rwAll"}}
	configs := []*storage.PrefixConfig{
		{engine.KeyMin, nil, config1},
		{engine.Key("a"), nil, config2},
	}
	configMap, err := storage.NewPrefixConfigMap(configs)
	if err != nil {
		t.Fatalf("failed to make prefix config map, err: %s", err.Error())
	}
	kv.gossip.AddInfo(gossip.KeyConfigPermission, configMap, time.Hour)

	readMethods := storage.ReadMethods
	writeMethods := storage.WriteMethods
	readOnlyMethods := make([]string, 0, len(readMethods))
	writeOnlyMethods := make([]string, 0, len(writeMethods))
	readWriteMethods := make([]string, 0, len(readMethods)+len(writeMethods))
	for _, readM := range readMethods {
		if storage.IsReadOnly(readM) {
			readOnlyMethods = append(readOnlyMethods, readM)
		} else {
			readWriteMethods = append(readWriteMethods, readM)
		}
	}
	for _, writeM := range writeMethods {
		if !storage.NeedReadPerm(writeM) {
			writeOnlyMethods = append(writeOnlyMethods, writeM)
		}
	}

	testData := []struct {
		// Permission-based db methods from the storage package.
		methods          []string
		user             string
		startKey, endKey engine.Key
		hasPermission    bool
	}{
		// Test permissions within a single range
		{readOnlyMethods, "read1", engine.KeyMin, engine.KeyMin, true},
		{readOnlyMethods, "rw", engine.KeyMin, engine.KeyMin, true},
		{readOnlyMethods, "write1", engine.KeyMin, engine.KeyMin, false},
		{readOnlyMethods, "random", engine.KeyMin, engine.KeyMin, false},
		{readWriteMethods, "rw", engine.KeyMin, engine.KeyMin, true},
		{readWriteMethods, "read1", engine.KeyMin, engine.KeyMin, false},
		{readWriteMethods, "write1", engine.KeyMin, engine.KeyMin, false},
		{writeOnlyMethods, "write1", engine.KeyMin, engine.KeyMin, true},
		{writeOnlyMethods, "rw", engine.KeyMin, engine.KeyMin, true},
		{writeOnlyMethods, "read1", engine.KeyMin, engine.KeyMin, false},
		{writeOnlyMethods, "random", engine.KeyMin, engine.KeyMin, false},
		// Test permissions across both ranges
		{readOnlyMethods, "readAll", engine.KeyMin, engine.Key("b"), true},
		{readOnlyMethods, "read1", engine.KeyMin, engine.Key("b"), false},
		{readOnlyMethods, "read2", engine.KeyMin, engine.Key("b"), false},
		{readOnlyMethods, "random", engine.KeyMin, engine.Key("b"), false},
		{readWriteMethods, "rwAll", engine.KeyMin, engine.Key("b"), true},
		{readWriteMethods, "rw", engine.KeyMin, engine.Key("b"), false},
		{readWriteMethods, "random", engine.KeyMin, engine.Key("b"), false},
		{writeOnlyMethods, "writeAll", engine.KeyMin, engine.Key("b"), true},
		{writeOnlyMethods, "write1", engine.KeyMin, engine.Key("b"), false},
		{writeOnlyMethods, "write2", engine.KeyMin, engine.Key("b"), false},
		{writeOnlyMethods, "random", engine.KeyMin, engine.Key("b"), false},
		// Test permissions within and around the boundaries of a range,
		// representatively using rw methods.
		{readWriteMethods, "rw2", engine.Key("a"), engine.Key("b"), true},
		{readWriteMethods, "rwAll", engine.Key("a"), engine.Key("b"), true},
		{readWriteMethods, "rw2", engine.Key("a"), engine.Key("a"), true},
		{readWriteMethods, "rw2", engine.Key("a"), engine.Key("a1"), true},
		{readWriteMethods, "rw2", engine.Key("a"), engine.Key("b1"), false},
		{readWriteMethods, "rw2", engine.Key("a3"), engine.Key("a4"), true},
		{readWriteMethods, "rw2", engine.Key("a3"), engine.Key("b1"), false},
	}

	for _, test := range testData {
		for _, method := range test.methods {
			err := kv.verifyPermissions(
				method,
				&proto.RequestHeader{
					User: test.user, Key: test.startKey, EndKey: test.endKey})
			if err != nil && test.hasPermission {
				t.Errorf("user: %s should have had permission to %s, err: %s",
					test.user, method, err.Error())
			} else if err == nil && !test.hasPermission {
				t.Errorf("user: %s should not have had permission to %s",
					test.user, method)
			}
		}
	}
	n.Stop()
}