From 8d1b9f7139d20f0230a47873098786350657e8ba Mon Sep 17 00:00:00 2001 From: "Ali R. Vahdati" <3798865+kavir1698@users.noreply.github.com> Date: Tue, 30 Apr 2024 13:50:55 +0200 Subject: [PATCH 1/2] Test `CreateJob` --- datasetUtils/createJob.go | 20 ++++++- datasetUtils/createJob_test.go | 99 ++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 datasetUtils/createJob_test.go diff --git a/datasetUtils/createJob.go b/datasetUtils/createJob.go index 1c38591..cea7762 100644 --- a/datasetUtils/createJob.go +++ b/datasetUtils/createJob.go @@ -12,6 +12,23 @@ type Job struct { Id string `json:"id"` } +/* +`CreateJob` creates a new job on the server. It takes in an HTTP client, the API server URL, a user map, a list of datasets, and a pointer to an integer representing the number of tape copies. + +The function constructs a job map with various parameters, including the email of the job initiator, the type of job, the creation time, the job parameters, and the job status message. It also includes a list of datasets. + +The job map is then marshalled into JSON and sent as a POST request to the server. If the server responds with a status code of 200, the function decodes the job ID from the response and returns it. If the server responds with any other status code, the function returns an empty string. + +Parameters: +- client: A pointer to an http.Client instance +- APIServer: A string representing the API server URL +- user: A map with string keys and values representing user information +- datasetList: A slice of strings representing the list of datasets +- tapecopies: A pointer to an integer representing the number of tape copies + +Returns: +- jobId: A string representing the job ID if the job was successfully created, or an empty string otherwise +*/ func CreateJob(client *http.Client, APIServer string, user map[string]string, datasetList []string, tapecopies *int) (jobId string) { // important: define field with capital names and rename fields via 'json' constructs // otherwise the marshaling will omit the fields ! @@ -69,7 +86,8 @@ func CreateJob(client *http.Client, APIServer string, user map[string]string, da var j Job err := decoder.Decode(&j) if err != nil { - log.Fatal("Could not decode id from job:", err) + log.Println("Could not decode id from job:", err) + return "" } return j.Id } else { diff --git a/datasetUtils/createJob_test.go b/datasetUtils/createJob_test.go new file mode 100644 index 0000000..2c8ed25 --- /dev/null +++ b/datasetUtils/createJob_test.go @@ -0,0 +1,99 @@ +package datasetUtils + +import ( + "net/http" + "net/http/httptest" + "testing" +) + +func TestCreateJob(t *testing.T) { + t.Run("successful job creation", func(t *testing.T) { + // Create a mock server + server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + rw.Write([]byte(`{"id": "123"}`)) + })) + defer server.Close() + + // Create a client + client := server.Client() + + // Define the parameters + APIServer := server.URL + user := map[string]string{ + "mail": "test@example.com", + "username": "testuser", + "accessToken": "testtoken", + } + datasetList := []string{"dataset1", "dataset2"} + tapecopies := new(int) + *tapecopies = 1 + + // Call the function + jobId := CreateJob(client, APIServer, user, datasetList, tapecopies) + + // Check the result + if jobId != "123" { + t.Errorf("Expected jobId to be '123', got '%s'", jobId) + } + }) + + t.Run("server returns non-200 status code", func(t *testing.T) { + // Create a mock server + server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + rw.WriteHeader(http.StatusInternalServerError) + })) + defer server.Close() + + // Create a client + client := server.Client() + + // Define the parameters + APIServer := server.URL + user := map[string]string{ + "mail": "test@example.com", + "username": "testuser", + "accessToken": "testtoken", + } + datasetList := []string{"dataset1", "dataset2"} + tapecopies := new(int) + *tapecopies = 1 + + // Call the function + jobId := CreateJob(client, APIServer, user, datasetList, tapecopies) + + // Check the result + if jobId != "" { + t.Errorf("Expected jobId to be '', got '%s'", jobId) + } + }) + + t.Run("server returns invalid JSON", func(t *testing.T) { + // Create a mock server + server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + rw.Write([]byte(`invalid json`)) + })) + defer server.Close() + + // Create a client + client := server.Client() + + // Define the parameters + APIServer := server.URL + user := map[string]string{ + "mail": "test@example.com", + "username": "testuser", + "accessToken": "testtoken", + } + datasetList := []string{"dataset1", "dataset2"} + tapecopies := new(int) + *tapecopies = 1 + + // Call the function + jobId := CreateJob(client, APIServer, user, datasetList, tapecopies) + + // Check the result + if jobId != "" { + t.Errorf("Expected jobId to be '', got '%s'", jobId) + } + }) +} From 9b138601520d2437ce9ae649dce1e4a23cda0635 Mon Sep 17 00:00:00 2001 From: "Ali R. Vahdati" <3798865+kavir1698@users.noreply.github.com> Date: Tue, 21 May 2024 15:30:12 +0200 Subject: [PATCH 2/2] Test `client.Do` called with expected payload --- datasetUtils/createJob_test.go | 66 ++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/datasetUtils/createJob_test.go b/datasetUtils/createJob_test.go index 2c8ed25..ab866e4 100644 --- a/datasetUtils/createJob_test.go +++ b/datasetUtils/createJob_test.go @@ -4,8 +4,20 @@ import ( "net/http" "net/http/httptest" "testing" + "io" + "bytes" + "encoding/json" + "reflect" ) +type MockTransport struct { + RoundTripFunc func(req *http.Request) (*http.Response, error) +} + +func (m *MockTransport) RoundTrip(req *http.Request) (*http.Response, error) { + return m.RoundTripFunc(req) +} + func TestCreateJob(t *testing.T) { t.Run("successful job creation", func(t *testing.T) { // Create a mock server @@ -96,4 +108,58 @@ func TestCreateJob(t *testing.T) { t.Errorf("Expected jobId to be '', got '%s'", jobId) } }) + + t.Run("client.Do called with expected payload", func(t *testing.T) { + // Create a mock server + server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + rw.Write([]byte(`{"id": "123"}`)) + })) + defer server.Close() + + user := map[string]string{ + "mail": "test@example.com", + "username": "testuser", + "accessToken": "testtoken", + } + datasetList := []string{"dataset1", "dataset2"} + tapecopies := new(int) + *tapecopies = 2 + + // Create a mock client + client := &http.Client{ + Transport: &MockTransport{ + RoundTripFunc: func(req *http.Request) (*http.Response, error) { + body, _ := io.ReadAll(req.Body) + + // Parse the actual and expected payloads + var actualPayload, expectedPayload map[string]interface{} + json.Unmarshal(body, &actualPayload) + json.Unmarshal([]byte(`{"creationTime":"2024-05-21T15:25:34+02:00","datasetList":[{"pid":"dataset1","files":[]},{"pid":"dataset2","files":[]}],"emailJobInitiator":"test@example.com","jobParams":{"tapeCopies":"two","username":"testuser"},"jobStatusMessage":"jobSubmitted","type":"archive"}`), &expectedPayload) + + // Ignore the creationTime field + delete(actualPayload, "creationTime") + delete(expectedPayload, "creationTime") + + // Check if the payloads match + if !reflect.DeepEqual(actualPayload, expectedPayload) { + t.Errorf("Expected payload to be '%v', got '%v'", expectedPayload, actualPayload) + } + + // We still need to return a response + return &http.Response{ + StatusCode: 200, + Body: io.NopCloser(bytes.NewBufferString(`{"id": "123"}`)), + }, nil + }, + }, + } + + // Call the function with the mock client + jobId := CreateJob(client, server.URL, user, datasetList, tapecopies) + + // Check the result + if jobId != "123" { + t.Errorf("Expected jobId to be '123', got '%s'", jobId) + } + }) }