Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 0 additions & 22 deletions .github/workflows/codespell.yml

This file was deleted.

57 changes: 33 additions & 24 deletions datatype/neuronjson/fields.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,42 +83,51 @@ func removeReservedFields(data NeuronJSON, showFields Fields) NeuronJSON {
return out
}

// Return a subset of fields from the NeuronJSON
// Return a subset of fields from the NeuronJSON where fieldMap is a map of field names to include.
func selectFields(data NeuronJSON, fieldMap map[string]struct{}, showUser, showTime bool) NeuronJSON {
out := data.copy()
out := NeuronJSON{}

// Always include bodyid if it exists.
if v, ok := data["bodyid"]; ok {
out["bodyid"] = v
}

if len(fieldMap) > 0 {
for field := range data {
if field == "bodyid" {
for key := range fieldMap {
// Skip "bodyid", already copied.
if key == "bodyid" {
continue
}
if _, found := fieldMap[field]; found {
if !showUser {
delete(out, field+"_user")
// Add the primary field if present.
if v, ok := data[key]; ok {
out[key] = v
}
// Optionally include accompanying _user and _time fields.
if showUser {
if v, ok := data[key+"_user"]; ok {
out[key+"_user"] = v
}
if !showTime {
delete(out, field+"_time")
}
if showTime {
if v, ok := data[key+"_time"]; ok {
out[key+"_time"] = v
}
} else {
delete(out, field)
delete(out, field+"_time")
delete(out, field+"_user")
}
}
} else {
if !showUser {
for field := range data {
if strings.HasSuffix(field, "_user") {
delete(out, field)
}
// No fieldMap provided, copy all keys except suppressed ones.
for key, v := range data {
// If we're not showing user info, skip fields ending in _user.
if !showUser && strings.HasSuffix(key, "_user") {
continue
}
}
if !showTime {
for field := range data {
if strings.HasSuffix(field, "_time") {
delete(out, field)
}
// If we're not showing time info, skip fields ending in _time.
if !showTime && strings.HasSuffix(key, "_time") {
continue
}
out[key] = v
}
}

return out
}
75 changes: 75 additions & 0 deletions datatype/neuronjson/fields_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package neuronjson

import (
"testing"
)

func TestSelectFields(t *testing.T) {
data := NeuronJSON{
"bodyid": 123,
"name": "neuron1",
"name_user": "user1",
"name_time": "2023-01-01T00:00:00Z",
"type": "X1",
"type_user": "user2",
"type_time": "2023-01-02T00:00:00Z",
}

tests := []struct {
name string
fieldMap map[string]struct{}
showUser bool
showTime bool
expected NeuronJSON
}{
{
name: "Show all fields",
fieldMap: map[string]struct{}{},
showUser: true,
showTime: true,
expected: data,
},
{
name: "Show only bodyid",
fieldMap: map[string]struct{}{"bodyid": {}},
showUser: true,
showTime: true,
expected: NeuronJSON{"bodyid": 123},
},
{
name: "Show name without user and time",
fieldMap: map[string]struct{}{"name": {}},
showUser: false,
showTime: false,
expected: NeuronJSON{"bodyid": 123, "name": "neuron1"},
},
{
name: "Show type with user but not time",
fieldMap: map[string]struct{}{"type": {}},
showUser: true,
showTime: false,
expected: NeuronJSON{"bodyid": 123, "type": "X1", "type_user": "user2"},
},
{
name: "Show type_user but not type",
fieldMap: map[string]struct{}{"type_user": {}},
showUser: true,
showTime: false,
expected: NeuronJSON{"bodyid": 123, "type_user": "user2"},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := selectFields(data, tt.fieldMap, tt.showUser, tt.showTime)
if len(result) != len(tt.expected) {
t.Errorf("expected %v, got %v", tt.expected, result)
}
for k, v := range tt.expected {
if result[k] != v {
t.Errorf("expected %v for key %s, got %v", v, k, result[k])
}
}
})
}
}
49 changes: 49 additions & 0 deletions datatype/neuronjson/neuronjson_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1383,6 +1383,55 @@ func TestAll(t *testing.T) {
}
}

func TestAllWithUser(t *testing.T) {
if err := server.OpenTest(); err != nil {
t.Fatalf("can't open test server: %v\n", err)
}
defer server.CloseTest()

uuid, _ := initTestRepo()

payload := bytes.NewBufferString(`{"typename": "neuronjson", "dataname": "neurons"}`)
apiStr := fmt.Sprintf("%srepo/%s/instance", server.WebAPIPath, uuid)
server.TestHTTP(t, "POST", apiStr, payload)

allNeurons := make(ListNeuronJSON, len(testData))
var keyreq = make([]string, len(testData))
for i := 0; i < len(testData); i++ {
keyreq[i] = fmt.Sprintf("%snode/%s/neurons/key/%s?u=tester", server.WebAPIPath, uuid, testData[i].key)
server.TestHTTP(t, "POST", keyreq[i], strings.NewReader(testData[i].val))
if err := json.Unmarshal([]byte(testData[i].val), &(allNeurons[i])); err != nil {
t.Fatalf("Unable to parse test annotation %d: %v\n", i, err)
}
}

// Get all neuronjson with only baz_user selected as field.
expectedVal := ListNeuronJSON{
NeuronJSON{
"bodyid": uint64(1000),
"baz_user": "tester",
},
NeuronJSON{
"bodyid": uint64(2000),
"baz_user": "tester",
},
NeuronJSON{
"bodyid": uint64(4000),
"baz_user": "tester",
},
}
allreq := fmt.Sprintf("%snode/%s/neurons/all?show=user&fields=baz_user", server.WebAPIPath, uuid)
returnValue := server.TestHTTP(t, "GET", allreq, nil)
var neurons ListNeuronJSON
if err := json.Unmarshal(returnValue, &neurons); err != nil {
t.Fatalf("Unable to parse return from /all request: %v\n", err)
}
sort.Sort(&neurons)
if !reflect.DeepEqual(neurons, expectedVal) {
t.Fatalf("Response to /all is incorrect. Expected: %v, Got: %v\n", expectedVal, neurons)
}
}

func TestDeleteWithNull(t *testing.T) {
if err := server.OpenTest(); err != nil {
t.Fatalf("can't open test server: %v\n", err)
Expand Down