Exemple #1
0
func TestJoinUpdatesExistingPeers(t *testing.T) {
	test := quiz.Test(t)

	nodeA := testNode()
	defer nodeA.Close()
	nodeB := testNode()
	defer nodeB.Close()
	nodeC := testNode()
	defer nodeC.Close()

	httpclient.Put(nodeA.URL+"/peers/join", nodeB.URL)
	httpclient.Put(nodeA.URL+"/peers/join", nodeC.URL)

	var statusCode int
	var body string

	statusCode, body = httpclient.Get(nodeA.URL+"/peers", "")
	test.Expect(statusCode).ToEqual(200)
	test.Expect(body).ToContain(nodeB.URL)
	test.Expect(body).ToContain(nodeC.URL)

	statusCode, body = httpclient.Get(nodeB.URL+"/peers", "")
	test.Expect(statusCode).ToEqual(200)
	test.Expect(body).ToContain(nodeA.URL)
	test.Expect(body).ToContain(nodeC.URL)

	statusCode, body = httpclient.Get(nodeC.URL+"/peers", "")
	test.Expect(statusCode).ToEqual(200)
	test.Expect(body).ToContain(nodeA.URL)
	test.Expect(body).ToContain(nodeB.URL)
}
Exemple #2
0
func TestResizeCleansUpReplicas(t *testing.T) {
	test := quiz.Test(t)

	serverA := testServer()
	defer serverA.Close()
	serverB := testServer()
	defer serverB.Close()
	serverC := testServer()
	defer serverC.Close()
	serverD := testServer()
	defer serverD.Close()

	httpclient.Put(serverA.URL+"/peers/join", serverB.URL)
	httpclient.Put(serverA.URL+"/peers/join", serverC.URL)
	httpclient.Put(serverA.URL+"/settings/n", "1")

	// this key will be owned by c before and after d joins
	// however it's replicas will first by a then d
	key := "a"

	httpclient.Put(serverA.URL+"/data/"+key, "foo")
	httpclient.Put(serverA.URL+"/peers/join", serverD.URL)

	_, aHasKey := serverA.node.values[key]
	_, cHasKey := serverC.node.values[key]
	_, dHasKey := serverD.node.values[key]

	test.Expect(aHasKey).ToBeFalse()
	test.Expect(cHasKey).ToBeTrue()
	test.Expect(dHasKey).ToBeTrue()
}
Exemple #3
0
func TestFetchesAcrossNodes(t *testing.T) {
	test := quiz.Test(t)

	serverA := testServer()
	defer serverA.Close()
	serverB := testServer()
	defer serverB.Close()

	httpclient.Put(serverA.URL+"/peers/join", serverB.URL)

	// "a"'s hash will be stored on serverB
	key := "a"

	var statusCode int
	var body string

	statusCode, _ = httpclient.Put(serverA.URL+"/data/"+key, "bar")
	test.Expect(statusCode).ToEqual(201)

	statusCode, body = httpclient.Get(serverB.URL+"/data/"+key, "")
	test.Expect(statusCode).ToEqual(200)
	test.Expect(body).ToEqual("bar")

	statusCode, body = httpclient.Get(serverA.URL+"/data/"+key, "")
	test.Expect(statusCode).ToEqual(200)
	test.Expect(body).ToEqual("bar")
}
Exemple #4
0
func TestNodeSetNValueUpdatesPeersOnJoin(t *testing.T) {
	test := quiz.Test(t)

	nodeA := testNode()
	defer nodeA.Close()
	nodeB := testNode()
	defer nodeB.Close()
	nodeC := testNode()
	defer nodeC.Close()

	httpclient.Put(nodeA.URL+"/peers/join", nodeB.URL)

	statusCode, _ := httpclient.Put(nodeA.URL+"/settings/n", "1")
	test.Expect(statusCode).ToEqual(201)

	httpclient.Put(nodeA.URL+"/peers/join", nodeC.URL)

	_, body := httpclient.Get(nodeA.URL+"/stats", "")
	test.Expect(body).ToContain(`"nValue":1`)

	_, body = httpclient.Get(nodeB.URL+"/stats", "")
	test.Expect(body).ToContain(`"nValue":1`)

	_, body = httpclient.Get(nodeC.URL+"/stats", "")
	test.Expect(body).ToContain(`"nValue":1`)
}
Exemple #5
0
func TestUpdateKey(t *testing.T) {
	test := quiz.Test(t)

	server := testServer()
	defer server.Close()

	httpclient.Put(server.URL+"/data/mykey", "bar")
	httpclient.Put(server.URL+"/data/mykey", "baz")
	statusCode, body := httpclient.Get(server.URL+"/data/mykey", "")

	test.Expect(statusCode).ToEqual(200)
	test.Expect(body).ToEqual("baz")
}
Exemple #6
0
func TestGetMultiplePeers(t *testing.T) {
	test := quiz.Test(t)

	node := testNode()
	defer node.Close()

	httpclient.Put(node.URL+"/peers", "peer1.url")
	httpclient.Put(node.URL+"/peers", "peer2.url")

	statusCode, body := httpclient.Get(node.URL+"/peers", "")

	test.Expect(statusCode).ToEqual(200)
	test.Expect(body).ToEqual(`{"peers":["peer1.url","peer2.url"]}`)
}
Exemple #7
0
func TestAddPeerFailsOnMultipleCalls(t *testing.T) {
	test := quiz.Test(t)

	node := testNode()
	defer node.Close()

	var statusCode int

	statusCode, _ = httpclient.Put(node.URL+"/peers", "peer.url")
	test.Expect(statusCode).ToEqual(201)

	statusCode, _ = httpclient.Put(node.URL+"/peers", "peer.url")
	test.Expect(statusCode).ToEqual(409)
}
Exemple #8
0
func TestFailedWriteUpdatesPeerList(t *testing.T) {
	test := quiz.Test(t)

	serverA := testServer()
	defer serverA.Close()
	serverB := testServer()
	peerURL := serverB.URL

	key := "a"

	httpclient.Put(serverA.URL+"/peers/join", serverB.URL)
	serverB.Close()
	httpclient.Put(serverA.URL+"/data/"+key, "foo")

	_, body := httpclient.Get(serverA.URL+"/peers", "")
	test.Expect(body).ToContain("dead:" + peerURL)
}
Exemple #9
0
func (server *Server) handoffKey(address string, key string, value string) {
	server.logger.Printf("Passing off '%s'->'%s' to %s", key, value, address)

	statusCode, _ := httpclient.Put(address+"/set/"+key, value)
	if statusCode == 0 {
		server.NotifyDown(address)
	}
}
Exemple #10
0
func TestErrorOnNGreaterThanTotalPeers(t *testing.T) {
	test := quiz.Test(t)

	nodeA := testNode()
	defer nodeA.Close()

	statusCode, _ := httpclient.Put(nodeA.URL+"/settings/n", "5")
	test.Expect(statusCode).ToEqual(422)
}
Exemple #11
0
func TestErrorOnNonIntForNValue(t *testing.T) {
	test := quiz.Test(t)

	nodeA := testNode()
	defer nodeA.Close()

	statusCode, _ := httpclient.Put(nodeA.URL+"/settings/n", "notint")
	test.Expect(statusCode).ToEqual(422)
}
Exemple #12
0
func (peer *Peer) evaluateKeyOwnership() {
	for key, value := range peer.values {
		owner := peer.ring.NodeForKey(key)
		if owner.GetName() != peer.url {
			httpclient.Put(owner.GetName()+"/data/"+key, value)
			delete(peer.values, key)
		}
	}
}
Exemple #13
0
func TestNodeSetRing(t *testing.T) {
	test := quiz.Test(t)

	node := testNode()
	defer node.Close()

	statusCode, _ := httpclient.Put(node.URL+"/ring", `{"ring":["`+node.URL+`","b","c"]}`)
	test.Expect(statusCode).ToEqual(201)

	_, body := httpclient.Get(node.URL+"/stats", "")
	test.Expect(body).ToContain(`"ring":["` + node.URL + `","b","c"]`)
}
Exemple #14
0
func (peer *Peer) join(newPeer string) {
	for _, p := range peer.Peers {
		httpclient.Put(p+"/peers", newPeer)
		httpclient.Put(newPeer+"/peers", p)
	}

	peer.addPeer(newPeer)
	peer.ring.AddNode(newPeer)
	httpclient.Put(newPeer+"/peers", peer.url)

	nValue := strconv.Itoa(peer.ring.GetNValue())
	httpclient.Put(newPeer+"/settings/set/n", nValue)

	for _, p := range peer.Peers {
		nodes := httpclient.JsonData{
			"ring": peer.ring.GetNodes(),
		}
		httpclient.Put(p+"/ring", nodes.Encode())
	}

	peer.evaluateKeyOwnership()
}
Exemple #15
0
func TestStatsKeys(t *testing.T) {
	test := quiz.Test(t)

	server := testServer()
	defer server.Close()

	httpclient.Put(server.URL+"/data/mykey", "bar")
	statusCode, body := httpclient.Get(server.URL+"/stats/keys", "")

	test.Expect(statusCode).ToEqual(200)
	test.Expect(body).ToContain(`"count":1`)
	test.Expect(body).ToContain(`"data":{"mykey":"bar"}`)
}
Exemple #16
0
func TestReplicationOnPut(t *testing.T) {
	test := quiz.Test(t)

	serverA := testServer()
	defer serverA.Close()
	serverB := testServer()
	defer serverB.Close()

	httpclient.Put(serverA.URL+"/peers/join", serverB.URL)
	httpclient.Put(serverA.URL+"/settings/n", "1")

	// "a"'s hash will be stored on serverB
	key := "a"

	httpclient.Put(serverA.URL+"/data/"+key, "bar")

	_, aHasKey := serverA.node.values["a"]
	_, bHasKey := serverB.node.values["a"]

	test.Expect(aHasKey).ToBeTrue()
	test.Expect(bHasKey).ToBeTrue()
}
Exemple #17
0
func TestAddPeer(t *testing.T) {
	test := quiz.Test(t)

	node := testNode()
	defer node.Close()

	statusCode, _ := httpclient.Put(node.URL+"/peers", "peer.url")
	test.Expect(statusCode).ToEqual(201)

	statusCode, body := httpclient.Get(node.URL+"/peers", "")
	test.Expect(statusCode).ToEqual(200)
	test.Expect(body).ToEqual(`{"peers":["peer.url"]}`)
}
Exemple #18
0
func TestMoveKeys(t *testing.T) {
	test := quiz.Test(t)

	serverA := testServer()
	defer serverA.Close()
	serverB := testServer()
	defer serverB.Close()
	serverC := testServer()
	defer serverC.Close()

	httpclient.Put(serverA.URL+"/peers/join", serverB.URL)

	// this key will first be on server B then will be on server C
	key := "b"

	httpclient.Put(serverA.URL+"/data/"+key, "foo")
	httpclient.Put(serverA.URL+"/peers/join", serverC.URL)

	_, bHasKey := serverB.node.values[key]
	_, cHasKey := serverC.node.values[key]

	test.Expect(bHasKey).ToBeFalse()
	test.Expect(cHasKey).ToBeTrue()
}
Exemple #19
0
func TestJoinCallsBack(t *testing.T) {
	test := quiz.Test(t)

	nodeA := testNode()
	defer nodeA.Close()
	nodeB := testNode()
	defer nodeB.Close()

	httpclient.Put(nodeA.URL+"/peers/join", nodeB.URL)

	var statusCode int
	var body string

	statusCode, body = httpclient.Get(nodeA.URL+"/peers", "")
	test.Expect(statusCode).ToEqual(200)
	test.Expect(body).ToEqual(`{"peers":["` + nodeB.URL + `"]}`)

	statusCode, body = httpclient.Get(nodeB.URL+"/peers", "")
	test.Expect(statusCode).ToEqual(200)
	test.Expect(body).ToEqual(`{"peers":["` + nodeA.URL + `"]}`)
}
Exemple #20
0
func TestAddNodeUpdatesRing(t *testing.T) {
	test := quiz.Test(t)
	var statusCode int
	var body string

	nodeA := testNode()
	defer nodeA.Close()

	nodeB := testNode()
	defer nodeB.Close()

	httpclient.Put(nodeA.URL+"/peers/join", nodeB.URL)

	statusCode, body = httpclient.Get(nodeA.URL+"/stats", "")
	test.Expect(statusCode).ToEqual(200)
	test.Expect(body).ToContain(`"vnodeCount":512`)
	test.Expect(body).ToContain(`"vnodeStart":0`)

	statusCode, body = httpclient.Get(nodeB.URL+"/stats", "")
	test.Expect(statusCode).ToEqual(200)
	test.Expect(body).ToContain(`"vnodeCount":512`)
	test.Expect(body).ToContain(`"vnodeStart":2147483137`)
}
Exemple #21
0
func (peer *Peer) Handler(m *pat.PatternServeMux) {
	m.Get("/stats", http.HandlerFunc(func(w http.ResponseWriter, request *http.Request) {
		stats := httpclient.JsonData{
			"ring":       peer.ring.GetNodes(),
			"vnodeCount": peer.node.VnodeCount(),
			"vnodeSize":  peer.node.VnodeSize(),
			"vnodeStart": peer.node.VnodeStart(),
			"nValue":     peer.ring.GetNValue(),
		}

		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(200)
		io.WriteString(w, stats.Encode())
	}))

	m.Put("/ring", http.HandlerFunc(func(w http.ResponseWriter, request *http.Request) {
		body, _ := ioutil.ReadAll(request.Body)
		data := map[string][]string{}
		json.Unmarshal(body, &data)

		peer.ring.SetNodes(data["ring"])
		peer.node = peer.ring.Get(peer.url)

		peer.evaluateKeyOwnership()

		w.WriteHeader(201)
	}))

	m.Put("/settings/set/n", http.HandlerFunc(func(w http.ResponseWriter, request *http.Request) {
		body, _ := ioutil.ReadAll(request.Body)
		n, err := strconv.Atoi(string(body))

		if err == nil {
			peer.ring.SetNValue(n)
			w.WriteHeader(201)
		} else {
			w.WriteHeader(422)
		}
	}))

	m.Put("/settings/n", http.HandlerFunc(func(w http.ResponseWriter, request *http.Request) {
		body, _ := ioutil.ReadAll(request.Body)
		n, err := strconv.Atoi(string(body))

		if err == nil && n < peer.peerCount() {
			peer.ring.SetNValue(n)
			for _, p := range peer.Peers {
				httpclient.Put(p+"/settings/set/n", string(body))
			}
			w.WriteHeader(201)
		} else {
			w.WriteHeader(422)
		}
	}))

	m.Put("/peers", http.HandlerFunc(func(w http.ResponseWriter, request *http.Request) {
		body, _ := ioutil.ReadAll(request.Body)
		newPeerURL := string(body)

		if peer.peerExists(newPeerURL) {
			w.WriteHeader(409)
		} else {
			peer.addPeer(newPeerURL)
			w.WriteHeader(201)
		}
	}))

	m.Put("/peers/join", http.HandlerFunc(func(w http.ResponseWriter, request *http.Request) {
		body, _ := ioutil.ReadAll(request.Body)
		newPeerURL := string(body)

		peer.logger.Printf("%s requesting to join", newPeerURL)

		if peer.peerExists(newPeerURL) {
			w.WriteHeader(409)
		} else {
			peer.join(newPeerURL)
			w.WriteHeader(201)
		}
	}))

	m.Get("/peers", http.HandlerFunc(func(w http.ResponseWriter, request *http.Request) {
		if peer.HasPeer() {
			w.Header().Set("Content-Type", "application/json")
			w.WriteHeader(200)
			io.WriteString(w, httpclient.JsonData{"peers": peer.Peers}.Encode())
		} else {
			w.WriteHeader(404)
		}
	}))
}