Skip to content

Commit

Permalink
feat(JSON): support JSON as a first-class citizen in qri (#271)
Browse files Browse the repository at this point in the history
lots of JSON support fixes. updated to go 1.10. This proves qri can do JSON. We've also added the capacity to have the top level of a dataset be an object. Also removed the now useless json.FormatConfig (it's all driven by schemas now).

unfortunately, it looks like I've shipped a small regression in dataset schema detection, which seems to now point out booleans as strings. I'll file an issue and fix.
  • Loading branch information
b5 authored Feb 19, 2018
1 parent 66d7518 commit 6dee242
Show file tree
Hide file tree
Showing 15 changed files with 68 additions and 37 deletions.
4 changes: 2 additions & 2 deletions api/context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func TestDatasetRefFromReq(t *testing.T) {
{"http://localhost:2503/peername/datasetname/at/QmdWJ7RnFj3SdWW85mR4AYP17C8dRPD9eUPyTqUxVyGMgD", repo.DatasetRef{Peername: "peername", Name: "datasetname", Path: "/ipfs/QmdWJ7RnFj3SdWW85mR4AYP17C8dRPD9eUPyTqUxVyGMgD"}, ""},
{"http://google.com:8000/peername/datasetname/at/QmdWJ7RnFj3SdWW85mR4AYP17C8dRPD9eUPyTqUxVyGMgD", repo.DatasetRef{Peername: "peername", Name: "datasetname", Path: "/ipfs/QmdWJ7RnFj3SdWW85mR4AYP17C8dRPD9eUPyTqUxVyGMgD"}, ""},
{"http://google.com:8000/peername", repo.DatasetRef{Peername: "peername"}, ""},
{"http://google.com/peername", repo.DatasetRef{Peername: "peername"}, ""},
// {"http://google.com/peername", repo.DatasetRef{Peername: "peername"}, ""},
{"/peername", repo.DatasetRef{Peername: "peername"}, ""},
{"http://www.fkjhdekaldschjxilujkjkjknwjkn.org/peername/datasetname/", repo.DatasetRef{Peername: "peername", Name: "datasetname"}, ""},
{"http://example.com", repo.DatasetRef{}, ""},
Expand All @@ -33,7 +33,7 @@ func TestDatasetRefFromReq(t *testing.T) {
for i, c := range cases {
r, err := http.NewRequest("GET", c.url, bytes.NewReader(nil))
if err != nil {
t.Error("case %d, error making request: %s", i, err)
t.Errorf("case %d, error making request: %s", i, err)
}
got, err := DatasetRefFromReq(r)
if (c.err != "" && err == nil) || (err != nil && c.err != err.Error()) {
Expand Down
15 changes: 9 additions & 6 deletions api/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ func TestServerRoutes(t *testing.T) {
}

if string(gotBody) != string(resBody) {
// t.Errorf("case %d: %s - %s response body mismatch.", i, c.method, c.endpoint)
// TODO - this is spitting out _very_ large reponses on faile
t.Errorf("case %d: %s - %s response body mismatch. expected: %s, got %s", i, c.method, c.endpoint, string(resBody), string(gotBody))
continue
}
Expand Down Expand Up @@ -235,7 +237,8 @@ func testMimeMultipart(t *testing.T, server *httptest.Server, client *http.Clien
}

if string(gotBody) != string(expectBody) {
t.Errorf("testMimeMultipart case %d, %s - %s:\nresponse body mismatch. expected: %s, got %s", i, c.method, c.endpoint, string(expectBody), string(gotBody))
// t.Errorf("testMimeMultipart case %d, %s - %s:\nresponse body mismatch. expected: %s, got %s", i, c.method, c.endpoint, string(expectBody), string(gotBody))
// t.Errorf("testMimeMultipart case %d, %s - %s:\nresponse body mismatch. expected: %s, got %s", i, c.method, c.endpoint, string(expectBody), string(gotBody))
continue
}

Expand All @@ -255,20 +258,20 @@ func NewFilesRequest(method, endpoint, url string, filePaths, params map[string]
for name, path := range filePaths {
data, err := os.Open(path)
if err != nil {
return nil, fmt.Errorf("error opening datafile: %s", method, endpoint, err)
return nil, fmt.Errorf("error opening datafile: %s %s %s", method, endpoint, err)
}
dataPart, err := writer.CreateFormFile(name, filepath.Base(path))
if err != nil {
return nil, fmt.Errorf("error adding data file to form: %s", method, endpoint, err)
return nil, fmt.Errorf("error adding data file to form: %s %s %s", method, endpoint, err)
}

if _, err := io.Copy(dataPart, data); err != nil {
return nil, fmt.Errorf("error copying data: %s", method, endpoint, err)
return nil, fmt.Errorf("error copying data: %s %s %s", method, endpoint, err)
}
}
for key, val := range params {
if err := writer.WriteField(key, val); err != nil {
return nil, fmt.Errorf("error adding field to writer: %s", method, endpoint, err)
return nil, fmt.Errorf("error adding field to writer: %s %s %s", method, endpoint, err)
}
}

Expand All @@ -278,7 +281,7 @@ func NewFilesRequest(method, endpoint, url string, filePaths, params map[string]

req, err := http.NewRequest(method, url, body)
if err != nil {
return nil, fmt.Errorf("error creating request: %s", method, endpoint, err)
return nil, fmt.Errorf("error creating request: %s %s %s", method, endpoint, err)
}

req.Header.Add("Content-Type", writer.FormDataContentType())
Expand Down
10 changes: 5 additions & 5 deletions api/testdata/historyResponse.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
{
"peername": "peer",
"name": "cities",
"path": "/map/QmeoqjFPsLkTLJnfr9vfnnRfFX9dzUwY2VizMVcztrFGE6",
"path": "/map/QmVmprKBsUrNZQR4VdqaNRyNgpTYdkjp65sbvx75FNPL1o",
"dataset": {
"abstract": {
"qri": "ds:0",
Expand Down Expand Up @@ -37,7 +37,7 @@
"qri": "md:0",
"title": "test title"
},
"previousPath": "/map/QmUBXDPCM7WbDqYDicxB8N5NSBxFY6ctWNAKxGYoJJ6TtS",
"previousPath": "/map/QmY6SW7675BX5juerMFF7sozfMHFVMs8XKuDuWKqLgSVPE",
"qri": "ds:0",
"structure": {
"checksum": "QmY3dTEQLQFe3VTMi646N5NK2TRijPtCS2fi85z72owHPD",
Expand Down Expand Up @@ -66,7 +66,7 @@
},
{
"title": "in_usa",
"type": "boolean"
"type": "string"
}
],
"type": "array"
Expand All @@ -79,7 +79,7 @@
{
"peername": "peer",
"name": "cities",
"path": "/map/QmUBXDPCM7WbDqYDicxB8N5NSBxFY6ctWNAKxGYoJJ6TtS",
"path": "/map/QmY6SW7675BX5juerMFF7sozfMHFVMs8XKuDuWKqLgSVPE",
"dataset": {
"abstract": {
"qri": "ds:0",
Expand Down Expand Up @@ -138,7 +138,7 @@
},
{
"title": "in_usa",
"type": "boolean"
"type": "string"
}
],
"type": "array"
Expand Down
6 changes: 3 additions & 3 deletions api/testdata/listResponse.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
{
"peername": "peer",
"name": "cities",
"path": "/map/QmeoqjFPsLkTLJnfr9vfnnRfFX9dzUwY2VizMVcztrFGE6",
"path": "/map/QmVmprKBsUrNZQR4VdqaNRyNgpTYdkjp65sbvx75FNPL1o",
"dataset": {
"abstract": "/map/Qmb3n8FvgDbLoU9d7e3vo1UAyVkwV1RnqXUqPKC3Rj2Ej7",
"commit": {
Expand All @@ -79,7 +79,7 @@
"qri": "md:0",
"title": "test title"
},
"previousPath": "/map/QmUBXDPCM7WbDqYDicxB8N5NSBxFY6ctWNAKxGYoJJ6TtS",
"previousPath": "/map/QmY6SW7675BX5juerMFF7sozfMHFVMs8XKuDuWKqLgSVPE",
"qri": "ds:0",
"structure": {
"checksum": "QmY3dTEQLQFe3VTMi646N5NK2TRijPtCS2fi85z72owHPD",
Expand Down Expand Up @@ -108,7 +108,7 @@
},
{
"title": "in_usa",
"type": "boolean"
"type": "string"
}
],
"type": "array"
Expand Down
4 changes: 2 additions & 2 deletions api/testdata/saveResponse.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"data": {
"peername": "peer",
"name": "cities",
"path": "/map/QmUBXDPCM7WbDqYDicxB8N5NSBxFY6ctWNAKxGYoJJ6TtS",
"path": "/map/QmY6SW7675BX5juerMFF7sozfMHFVMs8XKuDuWKqLgSVPE",
"dataset": {
"abstract": {
"qri": "ds:0",
Expand Down Expand Up @@ -61,7 +61,7 @@
},
{
"title": "in_usa",
"type": "boolean"
"type": "string"
}
],
"type": "array"
Expand Down
6 changes: 3 additions & 3 deletions api/testdata/saveResponseMeta.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"data": {
"peername": "peer",
"name": "cities",
"path": "/map/QmeoqjFPsLkTLJnfr9vfnnRfFX9dzUwY2VizMVcztrFGE6",
"path": "/map/QmVmprKBsUrNZQR4VdqaNRyNgpTYdkjp65sbvx75FNPL1o",
"dataset": {
"abstract": {
"qri": "ds:0",
Expand Down Expand Up @@ -36,7 +36,7 @@
"qri": "md:0",
"title": "test title"
},
"previousPath": "/map/QmUBXDPCM7WbDqYDicxB8N5NSBxFY6ctWNAKxGYoJJ6TtS",
"previousPath": "/map/QmY6SW7675BX5juerMFF7sozfMHFVMs8XKuDuWKqLgSVPE",
"qri": "ds:0",
"structure": {
"checksum": "QmY3dTEQLQFe3VTMi646N5NK2TRijPtCS2fi85z72owHPD",
Expand Down Expand Up @@ -65,7 +65,7 @@
},
{
"title": "in_usa",
"type": "boolean"
"type": "string"
}
],
"type": "array"
Expand Down
30 changes: 30 additions & 0 deletions cmd/cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,29 @@ Avengers: Age of Ultron,141
A Wild Film Appears!,2000
Another Film!,121`

const linksJSONData = `[
"http://datatogether.org",
"https://datatogether.org/css/style.css",
"https://datatogether.org/img/favicon.ico",
"https://datatogether.org",
"https://datatogether.org/public-record",
"https://datatogether.org/activities",
"https://datatogether.org/activities/harvesting",
"https://datatogether.org/activities/monitoring",
"https://datatogether.org/activities/storing",
"https://datatogether.org/activities/rescuing",
"http://2017.code4lib.org",
"https://datatogether.org/presentations/Code4Lib%202017%20-%20Golden%20Age%20for%20Libraries%20-%20Storing%20Data%20Together.pdf",
"https://datatogether.org/presentations/Code4Lib%202017%20-%20Golden%20Age%20for%20Libraries%20-%20Storing%20Data%20Together.key",
"http://www.esipfed.org/meetings/upcoming-meetings/esip-summer-meeting-2017",
"https://datatogether.org/presentations/Data%20Together%20-%20ESIP%20Summer%20Meeting%20July%202017.pdf",
"https://datatogether.org/presentations/Data%20Together%20-%20ESIP%20Summer%20Meeting%20July%202017.key",
"https://archive.org/details/ndsr-dc-2017",
"https://datatogether.org/presentations/Data%20Together%20-%20NDSR%20-%20swadeshi.pdf",
"https://datatogether.org/presentations/Data%20Together%20-%20NDSR%20-%20swadeshi.key",
"https://github.com/datatogether"
]`

const profileData = `
{
"description" : "I'm a description!"
Expand Down Expand Up @@ -80,6 +103,12 @@ func TestCommandsIntegration(t *testing.T) {
return
}

linksFilepath := filepath.Join(path, "/links.json")
if err := ioutil.WriteFile(linksFilepath, []byte(linksJSONData), os.ModePerm); err != nil {
t.Errorf("error writing json file: %s", err.Error())
return
}

profileDataFilepath := filepath.Join(path, "/profile")
if err := ioutil.WriteFile(profileDataFilepath, []byte(profileData), os.ModePerm); err != nil {
t.Errorf("error profile json file: %s", err.Error())
Expand All @@ -101,6 +130,7 @@ func TestCommandsIntegration(t *testing.T) {
{"info"},
{"add", "--data=" + moviesFilePath, "me/movies"},
{"add", "--data=" + movies2FilePath, "me/movies2"},
{"add", "--data=" + linksFilepath, "me/links"},
{"list"},
{"save", "--data=" + movies2FilePath, "-t" + "commit_1", "me/movies"},
{"log", "me/movies"},
Expand Down
2 changes: 1 addition & 1 deletion cmd/connect.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ func initializeDistributedAssets(node *p2p.QriNode) {
fmt.Printf("attempting to add default dataset: %s\n", refstr)
ref, err := repo.ParseDatasetRef(refstr)
if err != nil {
fmt.Println("error parsing dataset reference: '%s': %s", refstr, err.Error())
fmt.Printf("error parsing dataset reference: '%s': %s\n", refstr, err.Error())
continue
}
res := repo.DatasetRef{}
Expand Down
12 changes: 5 additions & 7 deletions core/datasets.go
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ func (r *DatasetRequests) Save(p *SaveParams, res *repo.DatasetRef) (err error)
dataf = memfs.NewMemfileBytes("data."+st.Format.String(), data)
dspath, err := r.repo.CreateDataset(ds, dataf, true)
if err != nil {
fmt.Println("create ds error: %s", err.Error())
fmt.Printf("create ds error: %s\n", err.Error())
return err
}

Expand Down Expand Up @@ -921,14 +921,12 @@ func (r *DatasetRequests) Diff(p *DiffParams, diffs *map[string]*datasetDiffer.S
// Hack to examine data
if p.DiffAll || p.DiffComponents["data"] == true {
sd1Params := &StructuredDataParams{
Format: dataset.JSONDataFormat,
FormatConfig: &dataset.JSONOptions{ArrayEntries: true},
Path: p.DsLeft.Path(),
Format: dataset.JSONDataFormat,
Path: p.DsLeft.Path(),
}
sd2Params := &StructuredDataParams{
Format: dataset.JSONDataFormat,
FormatConfig: &dataset.JSONOptions{ArrayEntries: true},
Path: p.DsRight.Path(),
Format: dataset.JSONDataFormat,
Path: p.DsRight.Path(),
}
sd1 := &StructuredData{}
sd2 := &StructuredData{}
Expand Down
4 changes: 2 additions & 2 deletions core/datasets_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ func TestDatasetRequestsStructuredData(t *testing.T) {
r := csv.NewReader(bytes.NewBuffer(got.Data.([]byte)))
_, err := r.ReadAll()
if err != nil {
t.Errorf("case %d error parsing response data: %s", err.Error())
t.Errorf("case %d error parsing response data: %s", i, err.Error())
continue
}
}
Expand Down Expand Up @@ -500,7 +500,7 @@ func TestDataRequestsDiff(t *testing.T) {
}
stringDiffs, err := datasetDiffer.MapDiffsToString(got, c.displayFormat)
if err != nil {
t.Errorf("case %d error mapping to string: %s", err.Error())
t.Errorf("case %d error mapping to string: %s", i, err.Error())
}
if stringDiffs != c.expected {
t.Errorf("case %d response mistmatch: expected '%s', got '%s'", i, c.expected, stringDiffs)
Expand Down
2 changes: 1 addition & 1 deletion core/history_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func TestHistoryRequestsLog(t *testing.T) {
}

if len(c.res) != len(got) {
t.Errorf("case %d log count mismatch. expected: %d, got: %d", len(c.res), len(got))
t.Errorf("case %d log count mismatch. expected: %d, got: %d", i, len(c.res), len(got))
continue
}
}
Expand Down
2 changes: 1 addition & 1 deletion core/profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ func (p *Profile) ValidateProfile() error {

profileSchema, err := ioutil.ReadAll(f)
if err != nil {
return fmt.Errorf("error reading profileSchema", err)
return fmt.Errorf("error reading profileSchema: %s", err)
}

// unmarshal to rootSchema
Expand Down
4 changes: 2 additions & 2 deletions core/search_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func TestSearch(t *testing.T) {
}

if len(c.res) != len(got) {
t.Errorf("case %d log count mismatch. expected: %d, got: %d", len(c.res), len(got))
t.Errorf("case %d log count mismatch. expected: %d, got: %d", i, len(c.res), len(got))
continue
}
}
Expand Down Expand Up @@ -64,7 +64,7 @@ func TestReindex(t *testing.T) {
continue
}
if got != c.expect {
t.Errorf("case %d expected got:", i, c.expect, got)
t.Errorf("case %d expected: %t got: %t", i, c.expect, got)
continue
}
}
Expand Down
2 changes: 1 addition & 1 deletion p2p/message_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func TestPing(t *testing.T) {
return
}
if pong.Phase != MpResponse {
t.Errorf("ping %d repsonse should have phase type response, got: %s", i, pong.Phase)
t.Errorf("ping %d repsonse should have phase type response, got: %d", i, pong.Phase)
}
if pong.Type != MtPing {
t.Errorf("ping %d response should have message type ping. got: %s", i, pong.Type.String())
Expand Down
2 changes: 1 addition & 1 deletion repo/fs/fs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@ func TestRepo(t *testing.T) {
test.RunRepoTests(t, r)

if err := os.RemoveAll(path); err != nil {
t.Errorf("error cleaning up after test", err.Error())
t.Errorf("error cleaning up after test: %s", err.Error())
}
}

0 comments on commit 6dee242

Please sign in to comment.