Skip to content

Instantly share code, notes, and snippets.

@yanisurbis
Created September 24, 2022 14:47
Show Gist options
  • Save yanisurbis/fc5a4e93024614839e284e8f774eaf60 to your computer and use it in GitHub Desktop.
Save yanisurbis/fc5a4e93024614839e284e8f774eaf60 to your computer and use it in GitHub Desktop.
package main
import (
"bytes"
"fmt"
"log"
"net"
"os"
"strings"
"time"
"sync"
)
// should be enough to receive the header
const CHUNK_SIZE = 1000
const TMP_FILE_PATH = "/tmp/gflib_client"
const ADDRESS = "localhost:8888"
const FILE_PREFIX = "/courses/ud923/filecorpus/"
const HEADER_DIVIDER = "\r\n\r\n"
func check(str string, e error) {
if e != nil {
log.Fatal(str+": ", e)
}
}
func contains(x string, y string) {
if !strings.Contains(x, y) {
log.Fatalf("should contain %s\n", y)
}
}
func printSuccess() {
println("Ok!")
}
type TestCase struct {
path string
expectedStatus string
}
func compareSentAndReceivedFiles_(received []byte, path string) {
bytesSentFile, err := os.ReadFile("../server_root" + path)
if err != nil {
log.Fatal("failed to open a file, ", err)
}
//fmt.Println(bytesSentFile)
//fmt.Println(bytesReceivedFileWithoutZeros)
//fmt.Println(string(bytesSentFile))
//fmt.Println(string(received))
//
//fmt.Println(bytesSentFile)
//fmt.Println(received)
if bytes.Compare(bytesSentFile, received) != 0 {
err = os.Remove(TMP_FILE_PATH)
check("failed to delete a file", err)
f, err := os.Create(TMP_FILE_PATH)
check("failed to create temporary file", err)
_, err = f.Write(received)
check("failed to write to file", err)
f.Sync()
log.Fatalf("Files %s should be equal", path)
}
}
func testFileIsTransferred(id int, tc TestCase) {
filePath := FILE_PREFIX + tc.path
conn, err := net.Dial("tcp", ADDRESS)
conn.SetDeadline(time.Now().Add(2 * time.Second))
if err != nil {
log.Fatal("Failed to dial: ", err)
}
request := fmt.Sprintf("GETFILE GET %s", filePath)
_, err = conn.Write([]byte(request + "\r\n\r\n"))
if err != nil {
log.Fatal("Failed to write: ", err)
}
reply := make([]byte, CHUNK_SIZE)
n, err := conn.Read(reply)
check("failed to read first chunk of data", err)
replyAsStr := string(reply[:n])
parts := strings.Split(replyAsStr, "\r\n\r\n")
header := parts[0]
headerParts := strings.Split(header, " ")
status := headerParts[1]
fileData := []byte(parts[1])
if status == "OK" {
for {
//fmt.Println("inside for", id)
n, err = conn.Read(reply)
if err != nil {
//log.Println("failed to read chunk of data", err)
break
}
if n == 0 {
break
}
fileData = append(fileData, reply[:n]...)
check("failed to write chunk of data", err)
}
compareSentAndReceivedFiles_(fileData, filePath)
}
fmt.Println("Request:", request)
//fmt.Println("Total length: ", len(replyAsStr))
fmt.Println("Header:", header)
contains(status, tc.expectedStatus)
//fmt.Printf("File data: %s\n\n\n", string(fileData))
conn.Close()
}
func main() {
testCases := []TestCase{
{
path: "digits.txt",
expectedStatus: "OK",
},
{
path: "paraglider.jpg",
expectedStatus: "OK",
},
{
path: "road.jpg",
expectedStatus: "OK",
},
{
path: "yellowstone.jpg",
expectedStatus: "OK",
},
{
path: "moranabovejacksonlake.jpg",
expectedStatus: "OK",
},
{
path: "digits123.txt",
expectedStatus: "FILE_NOT_FOUND",
},
}
var wg sync.WaitGroup
start := time.Now()
for _, tc := range testCases {
for i := 0; i < 2; i++ {
wg.Add(1)
saveI := i
go func(tc TestCase) {
defer wg.Done()
testFileIsTransferred(saveI, tc)
}(tc)
}
}
wg.Wait()
elapsed := time.Since(start)
log.Printf("Time: %s", elapsed)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment