From b3e88af281a5c18f17af7fd06088f5bd5186be38 Mon Sep 17 00:00:00 2001 From: Jack Ding Date: Fri, 6 Sep 2024 11:33:57 -0400 Subject: [PATCH] add O-RAN v3.0 API compliance tests Signed-off-by: Jack Ding --- v2/server_test.go | 225 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 156 insertions(+), 69 deletions(-) diff --git a/v2/server_test.go b/v2/server_test.go index 3bde7b7..9d8b5f5 100644 --- a/v2/server_test.go +++ b/v2/server_test.go @@ -46,28 +46,34 @@ import ( var ( server *restapi.Server - eventOutCh chan *channel.DataChan - closeCh chan struct{} - wg sync.WaitGroup - port = 8990 - apHost = "localhost" - apPath = "/api/ocloudNotifications/v2/" - resource = "/test/test" - resourceNoneSubscribed = "/test/nonesubscribed" - storePath = "." - ObjSub pubsub.PubSub - ObjPub pubsub.PubSub + eventOutCh chan *channel.DataChan + closeCh chan struct{} + wg sync.WaitGroup + port = 8990 + apHost = "localhost" + apPath = "/api/ocloudNotifications/v2/" + resource = "/cluster/node/mynode.example.com/example-status" + resourceInvalid = "/cluster/node/mynode.example.com/invalid" + storePath = "." + ObjSub pubsub.PubSub + ObjPub pubsub.PubSub + dummySource = "dummySource" + dummyType = "dummyType" ) -func onReceiveOverrideFn(_ cloudevents.Event, d *channel.DataChan) error { +func onReceiveOverrideFn(e cloudevents.Event, d *channel.DataChan) error { + if e.Source() != resource { + return fmt.Errorf("could not find any events for requested resource type %s", e.Source()) + } + data := &event.Data{ Version: event.APISchemaVersion, Values: []event.DataValue{}, } ce := cloudevents.NewEvent(cloudevents.VersionV1) ce.SetTime(types.Timestamp{Time: time.Now().UTC()}.Time) - ce.SetType("dummyType") - ce.SetSource("dummySource") + ce.SetType(dummyType) + ce.SetSource(dummySource) ce.SetSpecVersion(cloudevents.VersionV1) ce.SetID(uuid.New().String()) ce.SetData("", *data) //nolint:errcheck @@ -97,9 +103,9 @@ func TestMain(m *testing.M) { cneEvent.SetTime(types.Timestamp{Time: time.Now().UTC()}.Time) cneEvent.SetDataContentType(event.ApplicationJSON) data := event.Data{ - Version: "event", + Version: "v1.0", Values: []event.DataValue{{ - Resource: "test", + Resource: resource, DataType: event.NOTIFICATION, ValueType: event.ENUMERATION, Value: ptp.ACQUIRING_SYNC, @@ -125,7 +131,7 @@ func TestMain(m *testing.M) { log.Errorf("error on close channel") } }() - if d.Address == resourceNoneSubscribed { + if d.Address == resourceInvalid { d.StatusChan <- &channel.StatusChan{ ID: "123", ClientID: clientID, @@ -167,6 +173,55 @@ func TestServer_Health(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) } +// O-RAN.WG6.O-CLOUD-CONF-Test-R003-v02.00 +// TC5.3.1 Create a subscription resource 5.3.1.5 (2) +func TestServer_CreateSubscription_BadReq(t *testing.T) { + /// create new subscription without message body + ctx := context.Background() + ctx, cancel := context.WithCancel(ctx) + defer cancel() + req, err := http.NewRequestWithContext(ctx, "POST", fmt.Sprintf("http://localhost:%d%s%s", port, apPath, "subscriptions"), bytes.NewBuffer(nil)) + assert.Nil(t, err) + req.Header.Set("Content-Type", "application/json") + resp, err := server.HTTPClient.Do(req) + assert.Nil(t, err) + defer resp.Body.Close() + bodyBytes, err := io.ReadAll(resp.Body) + assert.Nil(t, err) + bodyString := string(bodyBytes) + log.Print(bodyString) + assert.Equal(t, http.StatusBadRequest, resp.StatusCode) +} + +// O-RAN.WG6.O-CLOUD-CONF-Test-R003-v02.00 +// TC5.3.1 Create a subscription resource 5.3.1.5 (3) +func TestServer_CreateSubscription_Resource_Not_Avail(t *testing.T) { + // create subscription + sub := api.NewPubSub( + &types.URI{URL: url.URL{Scheme: "http", Host: fmt.Sprintf("localhost:%d", port), Path: fmt.Sprintf("%s%s", apPath, "dummy")}}, + "resourceNotExist", "2.0") + data, err := json.Marshal(&sub) + assert.Nil(t, err) + assert.NotNil(t, data) + /// create new subscription + ctx := context.Background() + ctx, cancel := context.WithCancel(ctx) + defer cancel() + req, err := http.NewRequestWithContext(ctx, "POST", fmt.Sprintf("http://localhost:%d%s%s", port, apPath, "subscriptions"), bytes.NewBuffer(data)) + assert.Nil(t, err) + req.Header.Set("Content-Type", "application/json") + resp, err := server.HTTPClient.Do(req) + assert.Nil(t, err) + defer resp.Body.Close() + bodyBytes, err := io.ReadAll(resp.Body) + assert.Nil(t, err) + bodyString := string(bodyBytes) + log.Print(bodyString) + assert.Equal(t, http.StatusNotFound, resp.StatusCode) +} + +// O-RAN.WG6.O-CLOUD-CONF-Test-R003-v02.00 +// TC5.3.1 Create a subscription resource 5.3.1.5 (1) func TestServer_CreateSubscription(t *testing.T) { // create subscription sub := api.NewPubSub( @@ -200,6 +255,8 @@ func TestServer_CreateSubscription(t *testing.T) { log.Infof("Subscription:\n%s", ObjSub.String()) } +// O-RAN.WG6.O-CLOUD-CONF-Test-R003-v02.00 +// TC5.3.1 Create a subscription resource 5.3.1.5 (4) func TestServer_CreateSubscriptionConflict(t *testing.T) { // create subscription sub := api.NewPubSub( @@ -225,6 +282,31 @@ func TestServer_CreateSubscriptionConflict(t *testing.T) { assert.Equal(t, http.StatusConflict, resp.StatusCode) } +// O-RAN.WG6.O-CLOUD-CONF-Test-R003-v02.00 +// TC5.3.2 Get a list of subscription resources +func TestServer_ListSubscriptions(t *testing.T) { + // Get All Subscriptions + ctx := context.Background() + ctx, cancel := context.WithCancel(ctx) + defer cancel() + req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("http://localhost:%d%s%s", port, apPath, "subscriptions"), nil) + assert.Nil(t, err) + req.Header.Set("Content-Type", "application/json") + resp, err := server.HTTPClient.Do(req) + assert.Nil(t, err) + defer resp.Body.Close() // Close body only if response non-nil + bodyBytes, err := io.ReadAll(resp.Body) + assert.Nil(t, err) + assert.Equal(t, http.StatusOK, resp.StatusCode) + var subList []pubsub.PubSub + log.Printf("TestServer_ListSubscriptions :%s\n", string(bodyBytes)) + err = json.Unmarshal(bodyBytes, &subList) + assert.Nil(t, err) + assert.Greater(t, len(subList), 0) +} + +// O-RAN.WG6.O-CLOUD-CONF-Test-R003-v02.00 +// TC5.3.3 Get Detail of individual subscription resource 5.3.3.5 (1) func TestServer_GetSubscription(t *testing.T) { // Get Just Created Subscription req, err := http.NewRequest("GET", fmt.Sprintf("http://localhost:%d%s%s/%s", port, apPath, "subscriptions", ObjSub.ID), nil) @@ -232,6 +314,7 @@ func TestServer_GetSubscription(t *testing.T) { req.Header.Set("Content-Type", "application/json") resp, err := server.HTTPClient.Do(req) assert.Nil(t, err) + assert.Equal(t, http.StatusOK, resp.StatusCode) defer resp.Body.Close() bodyBytes, err := io.ReadAll(resp.Body) assert.Nil(t, err) @@ -244,6 +327,19 @@ func TestServer_GetSubscription(t *testing.T) { assert.Equal(t, rSub.ID, ObjSub.ID) } +// O-RAN.WG6.O-CLOUD-CONF-Test-R003-v02.00 +// TC5.3.3 Get Detail of individual subscription resource 5.3.3.5 (2) +func TestServer_GetSubscription_Not_Avail(t *testing.T) { + // Get Just Created Subscription + req, err := http.NewRequest("GET", fmt.Sprintf("http://localhost:%d%s%s/%s", port, apPath, "subscriptions", "InvalidId"), nil) + assert.Nil(t, err) + req.Header.Set("Content-Type", "application/json") + resp, err := server.HTTPClient.Do(req) + assert.Nil(t, err) + defer resp.Body.Close() + assert.Equal(t, http.StatusNotFound, resp.StatusCode) +} + func TestServer_CreatePublisher(t *testing.T) { pub := pubsub.PubSub{ ID: "", @@ -275,42 +371,64 @@ func TestServer_CreatePublisher(t *testing.T) { log.Infof("publisher \n%s", ObjPub.String()) } -func TestServer_GetPublisher(t *testing.T) { - // Get Just created Publisher - req, err := http.NewRequest("GET", fmt.Sprintf("http://localhost:%d%s%s/%s", port, apPath, "publishers", ObjPub.ID), nil) +// O-RAN.WG6.O-CLOUD-CONF-Test-R003-v02.00 +// TC5.3.6 Event pull status notification 5.3.6.5 (1) +func TestServer_GetCurrentState_withSubscription(t *testing.T) { + ctx := context.Background() + req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("http://localhost:%d%s%s/%s", port, apPath, ObjSub.Resource, "CurrentState"), nil) assert.Nil(t, err) req.Header.Set("Content-Type", "application/json") resp, err := server.HTTPClient.Do(req) assert.Nil(t, err) defer resp.Body.Close() - pubBodyBytes, err := io.ReadAll(resp.Body) - assert.Nil(t, err) - var rPub pubsub.PubSub - log.Printf("the data %s", string(pubBodyBytes)) - err = json.Unmarshal(pubBodyBytes, &rPub) - assert.Equal(t, resp.StatusCode, http.StatusOK) + s, err2 := io.ReadAll(resp.Body) + assert.Nil(t, err2) + log.Infof("tedt %s ", string(s)) + var e cloudevents.Event + err = json.Unmarshal(s, &e) assert.Nil(t, err) - assert.Equal(t, ObjPub.ID, rPub.ID) + assert.Equal(t, dummySource, e.Context.GetSource()) + assert.Equal(t, dummyType, e.Context.GetType()) + assert.Equal(t, http.StatusOK, resp.StatusCode) } -func TestServer_ListSubscriptions(t *testing.T) { - // Get All Subscriptions +// O-RAN.WG6.O-CLOUD-CONF-Test-R003-v02.00 +// TC5.3.6 Event pull status notification 5.3.6.5 (2) +func TestServer_GetCurrentState_withoutSubscription(t *testing.T) { ctx := context.Background() ctx, cancel := context.WithCancel(ctx) defer cancel() - req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("http://localhost:%d%s%s", port, apPath, "subscriptions"), nil) + + // try getting event + time.Sleep(2 * time.Second) + req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("http://localhost:%d%s%s/%s", port, apPath, resourceInvalid, "CurrentState"), nil) assert.Nil(t, err) req.Header.Set("Content-Type", "application/json") resp, err := server.HTTPClient.Do(req) assert.Nil(t, err) - defer resp.Body.Close() // Close body only if response non-nil - bodyBytes, err := io.ReadAll(resp.Body) + defer resp.Body.Close() + s, err2 := io.ReadAll(resp.Body) + assert.Nil(t, err2) + log.Infof("tedt %s ", string(s)) + assert.Equal(t, http.StatusNotFound, resp.StatusCode) +} + +func TestServer_GetPublisher(t *testing.T) { + // Get Just created Publisher + req, err := http.NewRequest("GET", fmt.Sprintf("http://localhost:%d%s%s/%s", port, apPath, "publishers", ObjPub.ID), nil) assert.Nil(t, err) - var subList []pubsub.PubSub - log.Printf("TestServer_ListSubscriptions :%s\n", string(bodyBytes)) - err = json.Unmarshal(bodyBytes, &subList) + req.Header.Set("Content-Type", "application/json") + resp, err := server.HTTPClient.Do(req) assert.Nil(t, err) - assert.Greater(t, len(subList), 0) + defer resp.Body.Close() + pubBodyBytes, err := io.ReadAll(resp.Body) + assert.Nil(t, err) + var rPub pubsub.PubSub + log.Printf("the data %s", string(pubBodyBytes)) + err = json.Unmarshal(pubBodyBytes, &rPub) + assert.Equal(t, resp.StatusCode, http.StatusOK) + assert.Nil(t, err) + assert.Equal(t, ObjPub.ID, rPub.ID) } func TestServer_ListPublishers(t *testing.T) { @@ -333,39 +451,6 @@ func TestServer_ListPublishers(t *testing.T) { assert.Greater(t, len(pubList), 0) } -func TestServer_GetCurrentState_withSubscription(t *testing.T) { - ctx := context.Background() - req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("http://localhost:%d%s%s/%s", port, apPath, ObjSub.Resource, "CurrentState"), nil) - assert.Nil(t, err) - req.Header.Set("Content-Type", "application/json") - resp, err := server.HTTPClient.Do(req) - assert.Nil(t, err) - defer resp.Body.Close() - s, err2 := io.ReadAll(resp.Body) - assert.Nil(t, err2) - log.Infof("tedt %s ", string(s)) - assert.Equal(t, http.StatusOK, resp.StatusCode) -} - -func TestServer_GetCurrentState_withoutSubscription(t *testing.T) { - ctx := context.Background() - ctx, cancel := context.WithCancel(ctx) - defer cancel() - - // try getting event - time.Sleep(2 * time.Second) - req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("http://localhost:%d%s%s/%s", port, apPath, resourceNoneSubscribed, "CurrentState"), nil) - assert.Nil(t, err) - req.Header.Set("Content-Type", "application/json") - resp, err := server.HTTPClient.Do(req) - assert.Nil(t, err) - defer resp.Body.Close() - s, err2 := io.ReadAll(resp.Body) - assert.Nil(t, err2) - log.Infof("tedt %s ", string(s)) - assert.Equal(t, http.StatusNotFound, resp.StatusCode) -} - func TestServer_TestPingStatusStatusCode(t *testing.T) { req, err := http.NewRequest("PUT", fmt.Sprintf("http://localhost:%d%s%s%s", port, apPath, "subscriptions/status/", ObjSub.ID), nil) assert.Nil(t, err) @@ -376,6 +461,8 @@ func TestServer_TestPingStatusStatusCode(t *testing.T) { assert.Equal(t, http.StatusBadRequest, resp.StatusCode) } +// O-RAN.WG6.O-CLOUD-CONF-Test-R003-v02.00 +// TC5.3.4 Delete individual subscription resources func TestServer_DeleteSubscription(t *testing.T) { clientIDs := server.GetSubscriberAPI().GetClientIDByResource(ObjSub.Resource) ctx := context.Background()