Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
FROM golang:1.11

COPY ./src/server/server /go/src/server
COPY ./src/client/client /go/src/client
RUN go get -u golang.org/x/lint/golint
RUN go get golang.org/x/tools/cmd/goimports
RUN go get github.com/golang/go/src/cmd/vet

WORKDIR /go/src/
RUN go build /go/src/server.go
ENTRYPOINT ["/go/src/server"]
EXPOSE 9090
38 changes: 38 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
SERVER_PATH = ./src/server
SERVER_BIN = server

CLIENT_PATH = ./src/client
CLIENT_BIN = client

SEARCH_GOFILES := $(shell find -type f -name "*.go")

build: clean client server docker

.PHONY: test
test:
go test -coverprofile=coverage.out $(SERVER_PATH)

.PHONY: check
check:
goimports -e -l $(SEARCH_GOFILES)
golint -set_exit_status $(SEARCH_GOFILES)
go vet $(SERVER_PATH)
go vet $(CLIENT_PATH)

.PHONY: run
run: build
sudo docker run -d gohomework

clean:
rm -rf $(SERVER_PATH)/$(SERVER_BIN)
rm -rf $(CLIENT_PATH)/$(CLIENT_BIN)

client:
go build -o $(CLIENT_PATH)/$(CLIENT_BIN) $(CLIENT_PATH)/client.go

server:
go build -o $(SERVER_PATH)/$(SERVER_BIN) $(SERVER_PATH)/server.go

.PHONY: docker
docker: server client
sudo docker build -t "gohomework" .
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Redis like database
Small Redis like database in Go.
Supported commands: SET, GET, DEL, KEYS
# Installation Instructions
Type `make` to build everything necessary
Use `src/server/server` for server and `src/client/client` for client.
Server must be run first.
# Running Redis like database in Docker
Run `docker build -t "gohomework" .` to build docker image.
Run `docker run gohomework` to run the server.

1 change: 1 addition & 0 deletions VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1.0
40 changes: 40 additions & 0 deletions src/client/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package main

import (
"bufio"
"flag"
"fmt"
"net"
"os"
)

const DEFAULT_PORT = "9090"
const DEFAULT_HOST = "127.0.0.1"

func main() {
var connectPort string
var connectHost string
flag.StringVar(&connectPort, "port", DEFAULT_PORT, "Port to listen on.")
flag.StringVar(&connectPort, "p", DEFAULT_PORT, "Port to listen on.")
flag.StringVar(&connectHost, "host", DEFAULT_HOST, "Host to listen on.")
flag.StringVar(&connectHost, "h", DEFAULT_HOST, "Host to listen on.")
flag.Parse()
fmt.Print("Sending commands on port:" + connectPort + "\n")
fmt.Print("To host:" + connectHost + "\n")

conn, conn_err := net.Dial("tcp", connectHost+":"+connectPort)
if conn_err != nil {
fmt.Println(conn_err)
}
for {
reader := bufio.NewReader(os.Stdin)
fmt.Print("> ")
text, err := reader.ReadString('\n')
if err != nil {
fmt.Println(err)
}
conn.Write([]byte(text))
response, _ := bufio.NewReader(conn).ReadString('\n')
fmt.Print("Response: " + response)
}
}
89 changes: 89 additions & 0 deletions src/server/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// server_main.go
package main

import (
"bufio"
"flag"
"fmt"
"net"
"strings"
)

const DEFAULT_PORT = "9090"
const DEFAULT_HOST = "127.0.0.1"

var database = make(map[string]string)

func main() {
var listenPort string
var listenHost string
flag.StringVar(&listenPort, "port", DEFAULT_PORT, "Port to listen on.")
flag.StringVar(&listenPort, "p", DEFAULT_PORT, "Port to listen on.")
flag.StringVar(&listenHost, "host", DEFAULT_HOST, "Host to listen on.")
flag.StringVar(&listenHost, "h", DEFAULT_HOST, "Host to listen on.")
flag.Parse()
fmt.Print("Listening on port:" + listenPort + "\n")
fmt.Print("Listening on host:" + listenHost + "\n")

//fmt.Println(listenHost)
//fmt.Println(listenPort)
listener, err := net.Listen("tcp", listenHost+":"+listenPort)
if err != nil {
fmt.Println(err)
}
for {
conn, err := listener.Accept()
if err != nil {
fmt.Println(err)
}
go handleRequest(conn)
}

}

func handleRequest(conn net.Conn) {
defer conn.Close()
connReader := bufio.NewReader(conn)
for {
request, err := connReader.ReadString('\n')
if err != nil {
fmt.Println(err)
return
}

command := strings.Split(request[:len(request)-1], " ")
fmt.Println(command[0])
switch command[0] {
case "SET":
if len(command) == 3 {
database[command[1]] = command[2]
conn.Write([]byte("SET successful" + "\n"))
} else {
conn.Write([]byte("Error in command syntax. Syntax: set [key] [value]" + "\n"))
}
case "GET":
if len(command) == 2 {
conn.Write([]byte(database[command[1]] + "\n"))
} else {
conn.Write([]byte("Error in command syntax. Syntax: get [key]" + "\n"))
}
case "DEL":
if len(command) == 2 {
delete(database, command[1])
conn.Write([]byte("DEL successful" + "\n"))
} else {
conn.Write([]byte("Error in command syntax. Syntax: del [key]" + "\n"))
}
case "KEYS":
all_key := []string{}
for key, _ := range database {
all_key = append(all_key, key)
}
conn.Write([]byte(strings.Join(all_key, " ") + "\n"))

default:
conn.Write([]byte("Unsupported command: " + "\n"))
}
}

}
60 changes: 60 additions & 0 deletions src/server/server_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package main

import (
"bufio"
"net"
"testing"
"time"
)

// var TEST_PAIRS = map[string]string{
// "UNSUPPORTED" + "\n": "Unsupported command: " + "\n",
// "SET" + "\n": "Error in command syntax. Syntax: set [key] [value]" + "\n",
// "GET" + "\n": "Error in command syntax. Syntax: get [key]" + "\n",
// "DEL" + "\n": "Error in command syntax. Syntax: del [key]" + "\n",
// "SET key1 val1" + "\n": "SET successful" + "\n",
// "SET key2 val2" + "\n": "SET successful" + "\n",
// "GET key2" + "\n": "val2" + "\n",
// "DEL key2" + "\n": "DEL successful" + "\n",
// "KEYS" + "\n": "key1 val1" + "\n",
// }

var test_pairs = []struct {
test_case string
test_result string
}{

{"UNSUPPORTED" + "\n", "Unsupported command: " + "\n"},
{"SET" + "\n", "Error in command syntax. Syntax: set [key] [value]" + "\n"},
{"GET" + "\n", "Error in command syntax. Syntax: get [key]" + "\n"},
{"DEL" + "\n", "Error in command syntax. Syntax: del [key]" + "\n"},
{"SET key1 val1" + "\n", "SET successful" + "\n"},
{"SET key2 val2" + "\n", "SET successful" + "\n"},
{"GET key2" + "\n", "val2" + "\n"},
{"DEL key2" + "\n", "DEL successful" + "\n"},
{"KEYS" + "\n", "key1" + "\n"},
}

func TestServer(t *testing.T) {
go main()
time.Sleep(100 * time.Millisecond)

conn, conn_err := net.Dial("tcp", "127.0.0.1:9090")
if conn_err != nil {
t.Error(conn_err)
}
for _, test_pair := range test_pairs {
test_case := test_pair.test_case
test_result := test_pair.test_result

conn.Write([]byte(test_case))

response, _ := bufio.NewReader(conn).ReadString('\n')
//fmt.Print("Response: " + response)
//fmt.Print("Result: " + test_result)
if response != test_result {
t.Errorf("Test failed, expected: '%s', got: '%s'", test_result, response)
}
}

}