Skip to content

Commit

Permalink
Merge pull request #904 from go-kivik/revTests
Browse files Browse the repository at this point in the history
Improve rev tests & stop storing literal _deleted key in doc JSON
  • Loading branch information
flimzy authored Mar 17, 2024
2 parents 8f37f8e + 9d33612 commit d0fff7c
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 91 deletions.
9 changes: 5 additions & 4 deletions x/sqlite/delete_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package sqlite
import (
"context"
"net/http"
"regexp"
"testing"

"gitlab.com/flimzy/testy"
Expand Down Expand Up @@ -56,7 +57,7 @@ func TestDBDelete(t *testing.T) {
db: dbc,
id: "foo",
options: kivik.Rev(rev),
wantRev: "2-df2a4fe30cde39c357c8d1105748d1b9",
wantRev: "2-.*",
check: func(t *testing.T, d driver.DB) {
var deleted bool
err := d.(*db).db.QueryRow(`
Expand Down Expand Up @@ -109,7 +110,7 @@ func TestDBDelete(t *testing.T) {
db: db,
id: "foo",
options: kivik.Rev(rev2),
wantRev: "3-df2a4fe30cde39c357c8d1105748d1b9",
wantRev: "3-.*",
}
})
tests.Add("delete without rev", func(t *testing.T) interface{} {
Expand Down Expand Up @@ -147,7 +148,7 @@ func TestDBDelete(t *testing.T) {
db: db,
id: "foo",
options: kivik.Rev("1-aaa"),
wantRev: "2-df2a4fe30cde39c357c8d1105748d1b9",
wantRev: "2-.*",
}
})
tests.Add("invalid rev format", test{
Expand Down Expand Up @@ -181,7 +182,7 @@ func TestDBDelete(t *testing.T) {
if err != nil {
return
}
if rev != tt.wantRev {
if !regexp.MustCompile(tt.wantRev).MatchString(rev) {
t.Errorf("Unexpected rev: %s", rev)
}
if tt.check != nil {
Expand Down
5 changes: 3 additions & 2 deletions x/sqlite/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,9 @@ func (d *db) Get(ctx context.Context, id string, options driver.Options) (*drive
}

toMerge := fullDoc{
ID: id,
Rev: r.String(),
ID: id,
Rev: r.String(),
Deleted: deleted,
}

var (
Expand Down
8 changes: 5 additions & 3 deletions x/sqlite/get_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package sqlite

import (
"bytes"
"context"
"encoding/json"
"io"
Expand Down Expand Up @@ -184,7 +185,7 @@ func TestDBGet(t *testing.T) {
return test{
db: db,
id: "foo",
options: kivik.Rev("2-df2a4fe30cde39c357c8d1105748d1b9"),
options: kivik.Rev(rev),
wantDoc: map[string]interface{}{
"_id": "foo",
"_rev": rev,
Expand All @@ -202,7 +203,7 @@ func TestDBGet(t *testing.T) {
return test{
db: db,
id: "foo",
options: kivik.Rev("1-6872a0fc474ada5c46ce054b92897063"),
options: kivik.Rev(rev),
wantDoc: map[string]interface{}{
"_id": "foo",
"_rev": rev,
Expand Down Expand Up @@ -1175,8 +1176,9 @@ func TestDBGet(t *testing.T) {
if err != nil {
return
}
body, _ := io.ReadAll(doc.Body)
var gotDoc interface{}
if err := json.NewDecoder(doc.Body).Decode(&gotDoc); err != nil {
if err := json.NewDecoder(bytes.NewReader(body)).Decode(&gotDoc); err != nil {
t.Fatal(err)
}
if d := testy.DiffAsJSON(tt.wantDoc, gotDoc); d != nil {
Expand Down
16 changes: 12 additions & 4 deletions x/sqlite/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,11 @@ func prepareDoc(docID string, doc interface{}) (*docData, error) {
if err := json.Unmarshal(tmpJSON, &data); err != nil {
return nil, &internal.Error{Status: http.StatusBadRequest, Err: err}
}
for key := range tmp {
if strings.HasPrefix(key, "_") {
delete(tmp, key)
}
}
if !data.Deleted {
delete(tmp, "_deleted")
}
Expand Down Expand Up @@ -191,6 +196,7 @@ type fullDoc struct {
Revisions *revsInfo `json:"_revisions,omitempty"`
LocalSeq int `json:"_local_seq,omitempty"`
Attachments map[string]attachment `json:"_attachments,omitempty"`
Deleted bool `json:"_deleted,omitempty"`
}

func mergeIntoDoc(doc fullDoc) io.ReadCloser {
Expand All @@ -207,11 +213,13 @@ func mergeIntoDoc(doc fullDoc) io.ReadCloser {
_ = buf.WriteByte(',')
}

// The main doc
_, _ = buf.Write(doc.Doc[1 : len(doc.Doc)-1]) // Omit opening and closing braces
_ = buf.WriteByte(',')

const minJSONObjectLen = 2
if len(doc.Doc) > minJSONObjectLen {
// The main doc
_, _ = buf.Write(doc.Doc[1 : len(doc.Doc)-1]) // Omit opening and closing braces
_ = buf.WriteByte(',')
}

if tmp, _ := json.Marshal(doc); len(tmp) > minJSONObjectLen {
_, _ = buf.Write(tmp[1 : len(tmp)-1])
_ = buf.WriteByte(',')
Expand Down
4 changes: 2 additions & 2 deletions x/sqlite/json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ func Test_prepareDoc(t *testing.T) {
"foo": "bar",
},
want: &docData{
RevID: "6872a0fc474ada5c46ce054b92897063",
Doc: []byte(`{"_deleted":true,"foo":"bar"}`),
RevID: "9bb58f26192e4ba00f01e2e7b136bbd8",
Doc: []byte(`{"foo":"bar"}`),
Deleted: true,
},
},
Expand Down
102 changes: 53 additions & 49 deletions x/sqlite/put_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package sqlite
import (
"context"
"net/http"
"regexp"
"testing"

"github.com/google/go-cmp/cmp"
Expand Down Expand Up @@ -274,12 +275,11 @@ func TestDBPut(t *testing.T) {
"_deleted": true,
"foo": "bar",
},
wantRev: "1-6872a0fc474ada5c46ce054b92897063",
wantRev: "1-.*",
wantRevs: []leaf{
{
ID: "foo",
Rev: 1,
RevID: "6872a0fc474ada5c46ce054b92897063",
ID: "foo",
Rev: 1,
},
},
check: func(t *testing.T, d driver.DB) {
Expand Down Expand Up @@ -775,19 +775,17 @@ func TestDBPut(t *testing.T) {
},
"foo": "bar",
},
wantRev: "1-4b98474b255b67856668474854b0d5f8",
wantRev: "1-.*",
wantRevs: []leaf{
{
ID: "foo",
Rev: 1,
RevID: "4b98474b255b67856668474854b0d5f8",
ID: "foo",
Rev: 1,
},
},
wantAttachments: []attachmentRow{
{
DocID: "foo",
Rev: 1,
RevID: "4b98474b255b67856668474854b0d5f8",
Filename: "foo.txt",
ContentType: "text/plain",
Length: 25,
Expand All @@ -806,19 +804,17 @@ func TestDBPut(t *testing.T) {
},
"foo": "bar",
},
wantRev: "1-1a46dc947908f36db2ac78b7edaecda3",
wantRev: "1-.*",
wantRevs: []leaf{
{
ID: "foo",
Rev: 1,
RevID: "1a46dc947908f36db2ac78b7edaecda3",
ID: "foo",
Rev: 1,
},
},
wantAttachments: []attachmentRow{
{
DocID: "foo",
Rev: 1,
RevID: "1a46dc947908f36db2ac78b7edaecda3",
Filename: "foo.txt",
ContentType: "application/octet-stream",
Length: 25,
Expand All @@ -829,7 +825,7 @@ func TestDBPut(t *testing.T) {
})
tests.Add("update doc with attachments without deleting them", func(t *testing.T) interface{} {
db := newDB(t)
_, err := db.Put(context.Background(), "foo", map[string]interface{}{
rev, err := db.Put(context.Background(), "foo", map[string]interface{}{
"foo": "bar",
"_attachments": map[string]interface{}{
"foo.txt": map[string]interface{}{
Expand All @@ -846,34 +842,30 @@ func TestDBPut(t *testing.T) {
db: db,
docID: "foo",
doc: map[string]interface{}{
"_rev": "1-4b98474b255b67856668474854b0d5f8",
"_rev": rev,
"foo": "baz",
"_attachments": map[string]interface{}{
"foo.txt": map[string]interface{}{
"stub": true,
},
},
},
wantRev: "2-a7cadffe4f950734f8eeae832e15f6c2",
wantRev: "2-.*",
wantRevs: []leaf{
{
ID: "foo",
Rev: 1,
RevID: "4b98474b255b67856668474854b0d5f8",
ID: "foo",
Rev: 1,
},
{
ID: "foo",
Rev: 2,
RevID: "a7cadffe4f950734f8eeae832e15f6c2",
ParentRev: &[]int{1}[0],
ParentRevID: &[]string{"4b98474b255b67856668474854b0d5f8"}[0],
ID: "foo",
Rev: 2,
ParentRev: &[]int{1}[0],
},
},
wantAttachments: []attachmentRow{
{
DocID: "foo",
Rev: 1,
RevID: "4b98474b255b67856668474854b0d5f8",
Filename: "foo.txt",
ContentType: "text/plain",
Length: 25,
Expand All @@ -885,7 +877,7 @@ func TestDBPut(t *testing.T) {
})
tests.Add("update doc with attachments, delete one", func(t *testing.T) interface{} {
db := newDB(t)
_, err := db.Put(context.Background(), "foo", map[string]interface{}{
rev, err := db.Put(context.Background(), "foo", map[string]interface{}{
"foo": "bar",
"_attachments": map[string]interface{}{
"foo.txt": map[string]interface{}{
Expand All @@ -906,46 +898,40 @@ func TestDBPut(t *testing.T) {
db: db,
docID: "foo",
doc: map[string]interface{}{
"_rev": "1-7884bb688778892bd22837c5d8cba96b",
"_rev": rev,
"foo": "baz",
"_attachments": map[string]interface{}{
"foo.txt": map[string]interface{}{
"stub": true,
},
},
},
wantRev: "2-a7cadffe4f950734f8eeae832e15f6c2",
wantRev: "2-.*",
wantRevs: []leaf{
{
ID: "foo",
Rev: 1,
RevID: "7884bb688778892bd22837c5d8cba96b",
ID: "foo",
Rev: 1,
},
{
ID: "foo",
Rev: 2,
RevID: "a7cadffe4f950734f8eeae832e15f6c2",
ParentRev: &[]int{1}[0],
ParentRevID: &[]string{"7884bb688778892bd22837c5d8cba96b"}[0],
ID: "foo",
Rev: 2,
ParentRev: &[]int{1}[0],
},
},
wantAttachments: []attachmentRow{
{
DocID: "foo",
Rev: 1,
RevID: "7884bb688778892bd22837c5d8cba96b",
Filename: "bar.txt",
ContentType: "text/plain",
Length: 25,
Digest: "md5-TmfHxaRgUrE9l3tkAn4s0Q==",
Data: "This is a base64 encoding",
DeletedRev: &[]int{2}[0],
DeletedRevID: &[]string{"a7cadffe4f950734f8eeae832e15f6c2"}[0],
DocID: "foo",
Rev: 1,
Filename: "bar.txt",
ContentType: "text/plain",
Length: 25,
Digest: "md5-TmfHxaRgUrE9l3tkAn4s0Q==",
Data: "This is a base64 encoding",
DeletedRev: &[]int{2}[0],
},
{
DocID: "foo",
Rev: 1,
RevID: "7884bb688778892bd22837c5d8cba96b",
Filename: "foo.txt",
ContentType: "text/plain",
Length: 25,
Expand Down Expand Up @@ -992,13 +978,22 @@ func TestDBPut(t *testing.T) {
if err != nil {
return
}
if rev != tt.wantRev {
if !regexp.MustCompile(tt.wantRev).MatchString(rev) {
t.Errorf("Unexpected rev: %s, want %s", rev, tt.wantRev)
}
if len(tt.wantRevs) == 0 {
t.Errorf("No leaves to check")
}
leaves := readRevisions(t, dbc.(*db).db, tt.docID)
for i, r := range tt.wantRevs {
// allow tests to omit RevID
if r.RevID == "" {
leaves[i].RevID = ""
}
if r.ParentRevID == nil {
leaves[i].ParentRevID = nil
}
}
if d := cmp.Diff(tt.wantRevs, leaves); d != "" {
t.Errorf("Unexpected leaves: %s", d)
}
Expand Down Expand Up @@ -1028,6 +1023,15 @@ func checkAttachments(t *testing.T, d driver.DB, want []attachmentRow) {
if err := rows.Err(); err != nil {
t.Fatal(err)
}
for i, w := range want {
// allow tests to omit RevID
if w.RevID == "" {
got[i].RevID = ""
}
if w.DeletedRevID == nil {
got[i].DeletedRevID = nil
}
}
if d := cmp.Diff(want, got); d != "" {
t.Errorf("Unexpected attachments: %s", d)
}
Expand Down
Loading

0 comments on commit d0fff7c

Please sign in to comment.