databricks-cli/libs/sync/event_test.go

131 lines
4.0 KiB
Go
Raw Permalink Normal View History

Add optional JSON output for sync command (#230) JSON output makes it easy to process synchronization progress information in downstream tools (e.g. the vscode extension). This changes introduces a `sync.Event` interface type for progress events as well as an `sync.EventNotifier` that lets the sync code pass along progress events to calling code. Example output in text mode (default, this uses the existing logger calls): ```text 2023/03/03 14:07:17 [INFO] Remote file sync location: /Repos/pieter.noordhuis@databricks.com/... 2023/03/03 14:07:18 [INFO] Initial Sync Complete 2023/03/03 14:07:22 [INFO] Action: PUT: foo 2023/03/03 14:07:23 [INFO] Uploaded foo 2023/03/03 14:07:23 [INFO] Complete 2023/03/03 14:07:25 [INFO] Action: DELETE: foo 2023/03/03 14:07:25 [INFO] Deleted foo 2023/03/03 14:07:25 [INFO] Complete ``` Example output in JSON mode: ```json {"timestamp":"2023-03-03T14:08:15.459439+01:00","seq":0,"type":"start"} {"timestamp":"2023-03-03T14:08:15.459461+01:00","seq":0,"type":"complete"} {"timestamp":"2023-03-03T14:08:18.459821+01:00","seq":1,"type":"start","put":["foo"]} {"timestamp":"2023-03-03T14:08:18.459867+01:00","seq":1,"type":"progress","action":"put","path":"foo","progress":0} {"timestamp":"2023-03-03T14:08:19.418696+01:00","seq":1,"type":"progress","action":"put","path":"foo","progress":1} {"timestamp":"2023-03-03T14:08:19.421397+01:00","seq":1,"type":"complete","put":["foo"]} {"timestamp":"2023-03-03T14:08:22.459238+01:00","seq":2,"type":"start","delete":["foo"]} {"timestamp":"2023-03-03T14:08:22.459268+01:00","seq":2,"type":"progress","action":"delete","path":"foo","progress":0} {"timestamp":"2023-03-03T14:08:22.686413+01:00","seq":2,"type":"progress","action":"delete","path":"foo","progress":1} {"timestamp":"2023-03-03T14:08:22.688989+01:00","seq":2,"type":"complete","delete":["foo"]} ``` --------- Co-authored-by: shreyas-goenka <88374338+shreyas-goenka@users.noreply.github.com>
2023-03-08 09:27:19 +00:00
package sync
import (
"encoding/json"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func jsonEqual(t *testing.T, expected string, e Event) {
var expected_, e_ map[string]any
buf, err := json.Marshal(e)
require.NoError(t, err)
err = json.Unmarshal([]byte(expected), &expected_)
require.NoError(t, err)
delete(expected_, "timestamp")
err = json.Unmarshal(buf, &e_)
require.NoError(t, err)
delete(e_, "timestamp")
assert.Equal(t, expected_, e_)
}
func TestEventStart(t *testing.T) {
var e Event
e = newEventStart(0, []string{"put"}, []string{"delete"})
assert.Equal(t, "Action: PUT: put, DELETE: delete", e.String())
e = newEventStart(1, []string{"put"}, []string{})
assert.Equal(t, "Action: PUT: put", e.String())
e = newEventStart(2, []string{}, []string{"delete"})
assert.Equal(t, "Action: DELETE: delete", e.String())
e = newEventStart(3, []string{}, []string{})
assert.Equal(t, "", e.String())
}
func TestEventStartJSON(t *testing.T) {
var e Event
e = newEventStart(0, []string{"put"}, []string{"delete"})
jsonEqual(t, `{"seq": 0, "type": "start", "put": ["put"], "delete": ["delete"]}`, e)
e = newEventStart(1, []string{"put"}, []string{})
jsonEqual(t, `{"seq": 1, "type": "start", "put": ["put"]}`, e)
e = newEventStart(2, []string{}, []string{"delete"})
jsonEqual(t, `{"seq": 2, "type": "start", "delete": ["delete"]}`, e)
e = newEventStart(3, []string{}, []string{})
jsonEqual(t, `{"seq": 3, "type": "start"}`, e)
}
func TestEventProgress(t *testing.T) {
var e Event
// Empty string if no progress has been made.
e = newEventProgress(0, EventActionPut, "path", 0.0)
assert.Equal(t, "", e.String())
e = newEventProgress(1, EventActionPut, "path", 1.0)
assert.Equal(t, "Uploaded path", e.String())
// Empty string if no progress has been made.
e = newEventProgress(2, EventActionDelete, "path", 0.0)
assert.Equal(t, "", e.String())
e = newEventProgress(3, EventActionDelete, "path", 1.0)
assert.Equal(t, "Deleted path", e.String())
}
func TestEventProgressJSON(t *testing.T) {
var e Event
e = newEventProgress(0, EventActionPut, "path", 0.0)
jsonEqual(t, `{"seq": 0, "type": "progress", "action": "put", "path": "path", "progress": 0.0}`, e)
e = newEventProgress(0, EventActionPut, "path", 0.5)
jsonEqual(t, `{"seq": 0, "type": "progress", "action": "put", "path": "path", "progress": 0.5}`, e)
e = newEventProgress(1, EventActionPut, "path", 1.0)
jsonEqual(t, `{"seq": 1, "type": "progress", "action": "put", "path": "path", "progress": 1.0}`, e)
e = newEventProgress(2, EventActionDelete, "path", 0.0)
jsonEqual(t, `{"seq": 2, "type": "progress", "action": "delete", "path": "path", "progress": 0.0}`, e)
e = newEventProgress(2, EventActionDelete, "path", 0.5)
jsonEqual(t, `{"seq": 2, "type": "progress", "action": "delete", "path": "path", "progress": 0.5}`, e)
e = newEventProgress(3, EventActionDelete, "path", 1.0)
jsonEqual(t, `{"seq": 3, "type": "progress", "action": "delete", "path": "path", "progress": 1.0}`, e)
}
func TestEventComplete(t *testing.T) {
var e Event
e = newEventComplete(0, []string{"put"}, []string{"delete"})
assert.Equal(t, "Initial Sync Complete", e.String())
e = newEventComplete(1, []string{"put"}, []string{})
assert.Equal(t, "Complete", e.String())
e = newEventComplete(2, []string{}, []string{"delete"})
assert.Equal(t, "Complete", e.String())
e = newEventComplete(3, []string{}, []string{})
assert.Equal(t, "", e.String())
}
func TestEventCompleteJSON(t *testing.T) {
var e Event
e = newEventComplete(0, []string{"put"}, []string{"delete"})
jsonEqual(t, `{"seq": 0, "type": "complete", "put": ["put"], "delete": ["delete"]}`, e)
e = newEventComplete(1, []string{"put"}, []string{})
jsonEqual(t, `{"seq": 1, "type": "complete", "put": ["put"]}`, e)
e = newEventComplete(2, []string{}, []string{"delete"})
jsonEqual(t, `{"seq": 2, "type": "complete", "delete": ["delete"]}`, e)
e = newEventComplete(3, []string{}, []string{})
jsonEqual(t, `{"seq": 3, "type": "complete"}`, e)
}