Repository: hyperledger/firefly
Pull request #1004 (2022-08-24 20:18:03)

Ensuring Empty List is Provided for FFDX Init on Zero Peer Nodes
DX's being implemented in languages like Typescript do not treat `null` as a valid, empty JSON array which was causing problems. Core would get a `500` from DX:
```
{"@timestamp":"2022-08-24T17:49:59.714Z","breq":"8CWznOwK","dx":"https","level":"debug","message":"==\u003e POST http://firefly-dx.infra.svc:3000/api/v1/init","pid":"1"}
{"@timestamp":"2022-08-24T17:49:59.720Z","breq":"8CWznOwK","dx":"https","level":"error","message":"\u003c== POST http://firefly-dx.infra.svc:3000/api/v1/init [500] (5.67ms)","pid":"1"}
```
and we'd see DX error with:
```
2022-08-24T17:49:52.646Z [ERROR]: Unexpected token n in JSON at position 0 lib/request-error.ts
```

codecov-commenter: # [Codecov](https://codecov.io/gh/hyperledger/firefly/pull/1004?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hyperledger) Report
> Merging [#1004](https://codecov.io/gh/hyperledger/firefly/pull/1004?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hyperledger) (c338f38) into [main](https://codecov.io/gh/hyperledger/firefly/commit/4108eba0000781fa44bedcd43efa346d4f99b729?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hyperledger) (4108eba) will **not change** coverage.
> The diff coverage is `100.00%`.

> :exclamation: Current head c338f38 differs from pull request most recent head 3e2934f. Consider uploading reports for the commit 3e2934f to get more accurate results

```diff
@@           Coverage Diff           @@
##             main    #1004   +/-   ##
=======================================
  Coverage   99.98%   99.98%           
=======================================
  Files         302      302           
  Lines       19839    19839           
=======================================
  Hits        19837    19837           
  Misses          2        2           
```


| [Impacted Files](https://codecov.io/gh/hyperledger/firefly/pull/1004?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hyperledger) | Coverage Δ | |
|---|---|---|
| [internal/dataexchange/ffdx/ffdx.go](https://codecov.io/gh/hyperledger/firefly/pull/1004/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hyperledger#diff-aW50ZXJuYWwvZGF0YWV4Y2hhbmdlL2ZmZHgvZmZkeC5nbw==) | `100.00% <100.00%> (ø)` | |

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hyperledger). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hyperledger)


Patch:
diff --git a/internal/dataexchange/ffdx/ffdx.go b/internal/dataexchange/ffdx/ffdx.go
index e7e135d50..b2134626d 100644
--- a/internal/dataexchange/ffdx/ffdx.go
+++ b/internal/dataexchange/ffdx/ffdx.go
@@ -221,7 +221,7 @@ func (h *FFDX) beforeConnect(ctx context.Context) error {
 	if h.needsInit {
 		h.initialized = false
 		var status dxStatus
-		var body []fftypes.JSONObject
+		body := make([]fftypes.JSONObject, 0)
 		for _, node := range h.nodes {
 			body = append(body, node.Peer)
 		}


Test patch:
diff --git a/internal/dataexchange/ffdx/ffdx_test.go b/internal/dataexchange/ffdx/ffdx_test.go
index bc59ad54b..6acd3d210 100644
--- a/internal/dataexchange/ffdx/ffdx_test.go
+++ b/internal/dataexchange/ffdx/ffdx_test.go
@@ -678,6 +678,52 @@ func TestWebsocketWithReinit(t *testing.T) {
 	assert.True(t, h.initialized)
 }
 
+func TestWebsocketWithEmptyNodesInit(t *testing.T) {
+	mockedClient := &http.Client{}
+	httpmock.ActivateNonDefault(mockedClient)
+	defer httpmock.DeactivateAndReset()
+
+	_, _, wsURL, cancel := wsclient.NewTestWSServer(nil)
+	defer cancel()
+
+	u, _ := url.Parse(wsURL)
+	u.Scheme = "http"
+	httpURL := u.String()
+	h := &FFDX{}
+
+	coreconfig.Reset()
+	h.InitConfig(utConfig)
+	utConfig.Set(ffresty.HTTPConfigURL, httpURL)
+	utConfig.Set(ffresty.HTTPCustomClient, mockedClient)
+	utConfig.Set(DataExchangeInitEnabled, true)
+
+	httpmock.RegisterResponder("POST", fmt.Sprintf("%s/api/v1/init", httpURL),
+		func(req *http.Request) (*http.Response, error) {
+			var reqNodes []fftypes.JSONObject
+
+			// we want to make sure when theres are no peer nodes, an empty list is being
+			// passed as the req, not "null"
+			err := json.NewDecoder(req.Body).Decode(&reqNodes)
+			assert.NoError(t, err)
+			assert.Empty(t, reqNodes)
+			assert.NotNil(t, reqNodes)
+
+			return httpmock.NewJsonResponse(200, fftypes.JSONObject{
+				"status": "ready",
+			})
+		})
+
+	h.InitConfig(utConfig)
+	err := h.Init(context.Background(), utConfig)
+	assert.NoError(t, err)
+
+	err = h.Start()
+	assert.NoError(t, err)
+
+	assert.Equal(t, 1, httpmock.GetTotalCallCount())
+	assert.True(t, h.initialized)
+}
+
 func TestDXUninitialized(t *testing.T) {
 	h, _, _, _, done := newTestFFDX(t, false)
 	defer done()
diff --git a/test/e2e/multiparty/multi_tenancy.go b/test/e2e/multiparty/multi_tenancy.go
index 35201bcc9..766ff3deb 100644
--- a/test/e2e/multiparty/multi_tenancy.go
+++ b/test/e2e/multiparty/multi_tenancy.go
@@ -108,16 +108,17 @@ func (suite *NamespaceAliasSuite) TestMultiTenancy() {
 	admin1.SetBaseURL(suite.testState.adminHost1 + "/spi/v1")
 	admin2.SetBaseURL(suite.testState.adminHost2 + "/spi/v1")
 
-	// Reset both nodes to pick up the new namespace
-	e2e.ResetFireFly(suite.T(), admin1)
-	e2e.ResetFireFly(suite.T(), admin2)
-	e2e.PollForUp(suite.T(), suite.testState.client1)
-	e2e.PollForUp(suite.T(), suite.testState.client2)
-
 	clientAlice := client.NewFireFly(suite.T(), suite.testState.client1.Hostname, nsAlice)
 	clientBob := client.NewFireFly(suite.T(), suite.testState.client1.Hostname, nsBob)
 	clientCharlie := client.NewFireFly(suite.T(), suite.testState.client2.Hostname, nsCharlie)
 
+	// Reset both nodes to pick up the new namespace
+	e2e.ResetFireFly(suite.T(), admin1)
+	e2e.ResetFireFly(suite.T(), admin2)
+	e2e.PollForUp(suite.T(), clientAlice)
+	e2e.PollForUp(suite.T(), clientBob)
+	e2e.PollForUp(suite.T(), clientCharlie)
+
 	eventNames := "message_confirmed"
 	queryString := fmt.Sprintf("namespace=%s&ephemeral&autoack&filter.events=%s", nsAlice, eventNames)
 	receivedAlice := e2e.WsReader(clientAlice.WebSocket(suite.T(), queryString, nil))