Skip to content

Commit

Permalink
test: add more tests and document test cases
Browse files Browse the repository at this point in the history
  • Loading branch information
yuryfirebolt committed Jul 8, 2022
1 parent a77cc26 commit 023b496
Show file tree
Hide file tree
Showing 11 changed files with 262 additions and 117 deletions.
16 changes: 7 additions & 9 deletions auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ package fireboltgosdk
import (
"encoding/json"
"fmt"
"log"
)

// AuthenticationResponse definition of the authentication response
type AuthenticationResponse struct {
AccessToken string `json:"access_token"`
ExpiresIn int `json:"expires_in"`
TokenType string `json:"token_type"`
Scope string `json:"scope"`
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
ExpiresIn int `json:"expires_in"`
TokenType string `json:"token_type"`
Scope string `json:"scope"`
}

// Authenticate sends an authentication request, and returns a newly constructed client object
Expand All @@ -22,15 +22,13 @@ func Authenticate(username, password string) (*Client, error) {

resp, err := request("", "POST", HostNameURL+LoginUrl, nil, string(jsonData))
if err != nil {
log.Fatal(err)
return nil, fmt.Errorf("authentication request failed: %v", err)
}

var authResp AuthenticationResponse
err = json.Unmarshal(resp, &authResp)
err = jsonStrictUnmarshall(resp, &authResp)
if err != nil {
log.Fatal(err)
return nil, fmt.Errorf("failed to unmarhal authenication response: %v", err)
return nil, fmt.Errorf("failed to unmarhal authenication response: %s", resp)
}

return &Client{AccessToken: authResp.AccessToken}, nil
Expand Down
32 changes: 32 additions & 0 deletions auth_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package fireboltgosdk

import (
"testing"
)

// TestAuthHappyPath tests normal authentication, and that the access token is actually set
func TestAuthHappyPath(t *testing.T) {
markIntegrationTest(t)

if len(clientMock.AccessToken) == 0 {
t.Errorf("Token is not set properly")
}
}

// TestAuthWrongCredential checks that authentication with wrong credentials returns an error
func TestAuthWrongCredential(t *testing.T) {
markIntegrationTest(t)

if _, err := Authenticate(usernameMock, "wrong_password"); err == nil {
t.Errorf("Authentication with wrong credentials didn't return an error")
}
}

// TestAuthEmptyCredential checks that authentication with empty password returns an error
func TestAuthEmptyCredential(t *testing.T) {
markIntegrationTest(t)

if _, err := Authenticate(usernameMock, ""); err == nil {
t.Errorf("Authentication with empty password didn't return an error")
}
}
9 changes: 9 additions & 0 deletions client.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package fireboltgosdk

import (
"bytes"
"encoding/json"
"errors"
"fmt"
Expand Down Expand Up @@ -214,3 +215,11 @@ func request(accessToken string, method string, url string, params map[string]st

return body, nil
}

// jsonStrictUnmarshall unmarshalls json into object, and returns an error
// if some fields are missing, or extra fields are present
func jsonStrictUnmarshall(data []byte, v any) error {
decoder := json.NewDecoder(bytes.NewReader(data))
decoder.DisallowUnknownFields()
return decoder.Decode(v)
}
102 changes: 55 additions & 47 deletions client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,67 +4,42 @@ import (
"testing"
)

func TestAuthHappyPath(t *testing.T) {
if testing.Short() {
t.Skip()
}
config, _ := ParseDSNString(dsn)
client, err := Authenticate(config.username, config.password)
if err != nil {
t.Errorf("Authentication failed with: %s", err)
}
if len(client.AccessToken) == 0 {
t.Errorf("Token is not set properly")
}
}

// TestGetAccountId test getting account ID with existing and not existing accounts
func TestGetAccountId(t *testing.T) {
if testing.Short() {
t.Skip()
}
config, _ := ParseDSNString(dsn)
client, err := Authenticate(config.username, config.password)
if err != nil {
t.Errorf("Authentication failed with: %s", err)
}
accountId, err := client.GetAccountIdByName("firebolt")
markIntegrationTest(t)

accountId, err := clientMock.GetAccountIdByName("firebolt")
if err != nil {
t.Errorf("GetAccountIdByName failed with: %s", err)
}
if len(accountId) == 0 {
t.Errorf("returned empty accountId")
}

_, err = client.GetAccountIdByName("firebolt_not_existing_account")
_, err = clientMock.GetAccountIdByName("firebolt_not_existing_account")
if err == nil {
t.Errorf("GetAccountIdByName didn't failed with not-existing account")
}
}

func TestGetEngineUrlByName(t *testing.T) {
if testing.Short() {
t.Skip()
}
config, _ := ParseDSNString(dsn)
client, err := Authenticate(config.username, config.password)
if err != nil {
t.Errorf("Authentication failed with: %s", err)
}
// TestGetEnginePropsByName test getting engine url by name step by step
func TestGetEnginePropsByName(t *testing.T) {
markIntegrationTest(t)

accountId, err := client.GetAccountIdByName("firebolt")
accountId, err := clientMock.GetAccountIdByName("firebolt")
if err != nil {
t.Errorf("GetAccountIdByName failed with: %s", err)
}

engineId, err := client.GetEngineIdByName(config.engineName, accountId)
engineId, err := clientMock.GetEngineIdByName(engineNameMock, accountId)
if err != nil {
t.Errorf("GetEngineIdByName failed with: %s", err)
}
if len(engineId) == 0 {
t.Errorf("GetEngineIdByName succeed but returned a zero length account id")
}

engineUrl, err := client.GetEngineUrlById(engineId, accountId)
engineUrl, err := clientMock.GetEngineUrlById(engineId, accountId)
if err != nil {
t.Errorf("GetEngineUrlById failed with: %s", err)
}
Expand All @@ -73,21 +48,54 @@ func TestGetEngineUrlByName(t *testing.T) {
}
}

func TestGetEngineUrlByDatabase(t *testing.T) {
if testing.Short() {
t.Skip()
}
config, _ := ParseDSNString(dsn)
client, err := Authenticate(config.username, config.password)
// TestGetEngineUrlByName test GetEngineUrlByName function and its failure scenarios
func TestGetEngineUrlByName(t *testing.T) {
markIntegrationTest(t)

engineUrl, err := clientMock.GetEngineUrlByName(engineNameMock, accountNameMock)
if err != nil {
t.Errorf("Authentication failed with: %s", err)
t.Errorf("GetEngineUrlByName returned an error: %v", err)
}
if makeCanonicalUrl(engineUrl) != makeCanonicalUrl(engineUrlMock) {
t.Errorf("Returned engine url is not equal to a mocked engine url %s != %s", engineUrl, engineUrlMock)
}
if _, err = clientMock.GetEngineUrlByName("not_existing_engine", accountNameMock); err == nil {
t.Errorf("GetEngineUrlByName didn't return an error with not existing engine")
}
if _, err = clientMock.GetEngineUrlByName(engineNameMock, "not_existing_account"); err == nil {
t.Errorf("GetEngineUrlByName didn't return an error with not existing account")
}
}

engineUrl, err := client.GetEngineUrlByDatabase(config.database, config.accountName)
// TestGetEngineUrlByDatabase checks, that the url of the default engine returns properly
func TestGetEngineUrlByDatabase(t *testing.T) {
markIntegrationTest(t)

engineUrl, err := clientMock.GetEngineUrlByDatabase(databaseMock, accountNameMock)
if err != nil {
t.Errorf("GetEngineUrlByDatabase failed with: %v, %s", err, config.accountName)
t.Errorf("GetEngineUrlByDatabase failed with: %v, %s", err, accountNameMock)
}
if len(engineUrl) == 0 {
t.Errorf("GetEngineUrlById succeed but returned a zero length account id")
if makeCanonicalUrl(engineUrl) != makeCanonicalUrl(engineUrlMock) {
t.Errorf("Returned engine url is not equal to a mocked engine url %s != %s", engineUrl, engineUrlMock)
}

if _, err = clientMock.GetEngineUrlByDatabase("not_existing_database", accountNameMock); err == nil {
t.Errorf("GetEngineUrlByDatabase didn't return an error with not existing database")
}
if _, err = clientMock.GetEngineUrlByDatabase(databaseMock, "not_existing_account"); err == nil {
t.Errorf("GetEngineUrlByDatabase didn't return an error with not existing account")
}
}

// TestQuery tests simple query
func TestQuery(t *testing.T) {
markIntegrationTest(t)

var queryResponse QueryResponse
if err := clientMock.Query(engineUrlMock, databaseMock, "SELECT 1", &queryResponse); err != nil {
t.Errorf("Query returned an error: %v", err)
}
if queryResponse.Rows != 1 {
t.Errorf("Query response has an invalid number of rows %d != %d", queryResponse.Rows, 1)
}
}
30 changes: 30 additions & 0 deletions connection_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package fireboltgosdk

import "testing"

// TestConnectionPrepareStatement, tests that prepare statement doesn't result into an error
func TestConnectionPrepareStatement(t *testing.T) {
emptyClient := Client{}
fireboltConnection := fireboltConnection{&emptyClient, "database_name", "engine_url"}

queryMock := "SELECT 1"
_, err := fireboltConnection.Prepare(queryMock)
if err != nil {
t.Errorf("Prepare failed, but it shouldn't: %v", err)
}
}

// TestConnectionClose, tests that connection close doesn't result an error
// and prepare statement on closed connection is not possible
func TestConnectionClose(t *testing.T) {
emptyClient := Client{}
fireboltConnection := fireboltConnection{&emptyClient, databaseMock, engineUrlMock}
if err := fireboltConnection.Close(); err != nil {
t.Errorf("Close failed with an err: %v", err)
}

_, err := fireboltConnection.Prepare("SELECT 1")
if err == nil {
t.Errorf("Prepare on closed connection didn't fail, but it should")
}
}
Loading

0 comments on commit 023b496

Please sign in to comment.