package client_test import ( "bytes" "context" "fmt" "io" "net" "strings" "testing" "time" "git.t-juice.club/torjus/gpaste" "git.t-juice.club/torjus/gpaste/api" "git.t-juice.club/torjus/gpaste/client" "git.t-juice.club/torjus/gpaste/files" "git.t-juice.club/torjus/gpaste/users" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" ) func TestClient(t *testing.T) { listener, err := net.Listen("tcp", ":0") if err != nil { panic(err) } port := listener.Addr().(*net.TCPAddr).Port cfg := &gpaste.ServerConfig{ LogLevel: "ERROR", URL: fmt.Sprintf("http://localhost:%d", port), SigningSecret: "TEST", Store: &gpaste.ServerStoreConfig{Type: "memory"}, } srv := api.NewHTTPServer(cfg) go func() { srv.Serve(listener) }() t.Cleanup(func() { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() srv.Shutdown(ctx) listener.Close() }) // Add users username := "admin" password := "admin" user := &users.User{ Username: username, Role: users.RoleAdmin, } if err := user.SetPassword(password); err != nil { t.Fatalf("Error setting password: %s", err) } if err := srv.Users.Store(user); err != nil { t.Fatalf("Error storing user: %s", err) } t.Run("Login", func(t *testing.T) { client := client.Client{BaseURL: cfg.URL} ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() if err := client.Login(ctx, username, password); err != nil { t.Fatalf("Error logging in: %s", err) } claims, err := srv.Auth.ValidateToken(client.AuthToken) if err != nil { t.Errorf("unable to get claims from token: %s", err) } if claims.Role != user.Role { t.Errorf("Claims have wrong role: %s", cmp.Diff(claims.Role, user.Role)) } if claims.Subject != username { t.Errorf("Claims have wrong role: %s", cmp.Diff(claims.Subject, username)) } t.Run("UserCreate", func(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() username := "user" password := "user" if err := client.UserCreate(ctx, username, password); err != nil { t.Fatalf("Error creating user: %s", err) } user, err := srv.Users.Get(username) if err != nil { t.Fatalf("Error getting new user: %s", err) } if user.Username != username { t.Errorf("Username does not match.") } if err := user.ValidatePassword(password); err != nil { t.Errorf("Unable to validate password: %s", err) } }) }) t.Run("Upload", func(t *testing.T) { client := client.Client{BaseURL: cfg.URL} ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() fileContents := "this is the test file" fileBody := io.NopCloser(strings.NewReader(fileContents)) file := &files.File{ OriginalFilename: "filename.txt", Body: fileBody, } resp, err := client.Upload(ctx, file) if err != nil { t.Fatalf("Error uploading: %s", err) } retrieved, err := srv.Files.Get(resp.Files[0].ID) if err != nil { t.Fatalf("Error getting uploaded file from store: %s", err) } defer retrieved.Body.Close() buf := new(strings.Builder) if _, err := io.Copy(buf, retrieved.Body); err != nil { t.Fatalf("error reading body from store: %s", err) } if buf.String() != fileContents { t.Errorf("File contents does not match: %s", cmp.Diff(buf.String(), fileContents)) } }) t.Run("Download", func(t *testing.T) { client := client.Client{BaseURL: cfg.URL} ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() fileContents := "this is the test file" fileBody := io.NopCloser(strings.NewReader(fileContents)) file := &files.File{ ID: uuid.NewString(), OriginalFilename: "filename.txt", Body: fileBody, } if err := srv.Files.Store(file); err != nil { t.Fatalf("Error putting file in store: %s", err) } body, err := client.Download(ctx, file.ID) if err != nil { t.Fatalf("Error uploading: %s", err) } defer body.Close() buf := new(strings.Builder) if _, err := io.Copy(buf, body); err != nil { t.Fatalf("error reading body from store: %s", err) } if buf.String() != fileContents { t.Errorf("File contents does not match: %s", cmp.Diff(buf.String(), fileContents)) } }) t.Run("Save", func(t *testing.T) { c := client.Client{BaseURL: "http://example.org/gpaste", AuthToken: "tokenpls"} expectedConfig := "{\"baseUrl\":\"http://example.org/gpaste\",\"authToken\":\"tokenpls\"}\n" buf := new(bytes.Buffer) err := c.WriteConfigToWriter(buf) if err != nil { t.Fatalf("Error writing config: %s", err) } if diff := cmp.Diff(buf.String(), expectedConfig); diff != "" { t.Errorf("Written config does not match expected: %s", diff) } }) t.Run("Load", func(t *testing.T) { c := client.Client{} config := "{\"baseUrl\":\"http://pasta.example.org\",\"authToken\":\"tokenpls\"}\n" expectedClient := client.Client{BaseURL: "http://pasta.example.org", AuthToken: "tokenpls"} sr := strings.NewReader(config) if err := c.LoadConfigFromReader(sr); err != nil { t.Fatalf("Error reading config: %s", err) } if diff := cmp.Diff(c, expectedClient, cmpopts.IgnoreUnexported(client.Client{})); diff != "" { t.Errorf("Client does not match expected: %s", diff) } }) }