Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
jio
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Bryan Kaperick
jio
Commits
9bf585e5
Commit
9bf585e5
authored
Jun 29, 2018
by
Bryan Kaperick
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added additional tests for edgecase behavior.
parent
923a85d2
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
508 additions
and
107 deletions
+508
-107
src/jio.storage/historystorage.js
src/jio.storage/historystorage.js
+106
-97
test/jio.storage/historystorage.tests.js
test/jio.storage/historystorage.tests.js
+402
-10
No files found.
src/jio.storage/historystorage.js
View file @
9bf585e5
...
@@ -46,31 +46,27 @@
...
@@ -46,31 +46,27 @@
HistoryStorage
.
prototype
.
get
=
function
(
id_in
)
{
HistoryStorage
.
prototype
.
get
=
function
(
id_in
)
{
// Query to get the last edit made to this document
var
substorage
=
this
.
_sub_storage
,
doc_id_query
,
metadata_query
,
options
;
if
(
this
.
_include_revisions
)
{
if
(
this
.
_include_revisions
)
{
// Try to treat id_in as a timestamp instead of a name
doc_id_query
=
new
SimpleQuery
({
return
this
.
_sub_storage
.
get
(
id_in
)
operator
:
"
<=
"
,
.
push
(
function
(
result
)
{
key
:
"
timestamp
"
,
if
(
result
.
op
===
"
put
"
)
{
value
:
id_in
return
result
.
doc
;
}
throwRemovedError
(
id_in
);
},
function
(
error
)
{
if
(
error
.
status_code
===
404
&&
error
instanceof
jIO
.
util
.
jIOError
)
{
throwCantFindError
(
id_in
);
}
throw
error
;
});
});
}
else
{
doc_id_query
=
new
SimpleQuery
({
key
:
"
doc_id
"
,
value
:
id_in
});
}
}
// Query to get the last edit made to this document
var
substorage
=
this
.
_sub_storage
,
// Include id_in as value in query object for safety
// Include id_in as value in query object for safety
metadata_query
=
new
ComplexQuery
({
metadata_query
=
new
ComplexQuery
({
operator
:
"
AND
"
,
operator
:
"
AND
"
,
query_list
:
[
query_list
:
[
new
SimpleQuery
({
key
:
"
doc_id
"
,
value
:
id_in
})
,
doc_id_query
,
new
ComplexQuery
({
new
ComplexQuery
({
operator
:
"
OR
"
,
operator
:
"
OR
"
,
query_list
:
[
query_list
:
[
...
@@ -79,13 +75,15 @@
...
@@ -79,13 +75,15 @@
]
]
})
})
]
]
}),
});
options
=
{
options
=
{
query
:
metadata_query
,
query
:
metadata_query
,
select_list
:
[
"
op
"
],
select_list
:
[
"
op
"
],
limit
:
[
0
,
1
],
limit
:
[
0
,
1
],
sort_on
:
[[
"
timestamp
"
,
"
descending
"
]]
sort_on
:
[[
"
timestamp
"
,
"
descending
"
]]
};
};
return
substorage
.
allDocs
(
options
)
return
substorage
.
allDocs
(
options
)
.
push
(
function
(
results
)
{
.
push
(
function
(
results
)
{
if
(
results
.
data
.
total_rows
>
0
)
{
if
(
results
.
data
.
total_rows
>
0
)
{
...
@@ -102,7 +100,6 @@
...
@@ -102,7 +100,6 @@
};
};
HistoryStorage
.
prototype
.
put
=
function
(
id
,
data
)
{
HistoryStorage
.
prototype
.
put
=
function
(
id
,
data
)
{
var
timestamp
=
generateUniqueTimestamp
(
Date
.
now
()),
var
timestamp
=
generateUniqueTimestamp
(
Date
.
now
()),
metadata
=
{
metadata
=
{
// XXX: remove this attribute once query can sort_on id
// XXX: remove this attribute once query can sort_on id
...
@@ -133,9 +130,11 @@
...
@@ -133,9 +130,11 @@
query_removed_check
,
query_removed_check
,
options
,
options
,
query_doc_id
,
query_doc_id
,
options_remcheck
;
options_remcheck
,
include_revs
=
this
.
_include_revisions
,
have_seen_id
=
false
;
if
(
this
.
_include_revision
s
)
{
if
(
include_rev
s
)
{
query_doc_id
=
new
SimpleQuery
({
query_doc_id
=
new
SimpleQuery
({
operator
:
"
<=
"
,
operator
:
"
<=
"
,
key
:
"
timestamp
"
,
key
:
"
timestamp
"
,
...
@@ -143,6 +142,7 @@
...
@@ -143,6 +142,7 @@
});
});
}
else
{
}
else
{
query_doc_id
=
new
SimpleQuery
({
key
:
"
doc_id
"
,
value
:
id
});
query_doc_id
=
new
SimpleQuery
({
key
:
"
doc_id
"
,
value
:
id
});
have_seen_id
=
true
;
}
}
query_removed_check
=
new
ComplexQuery
({
query_removed_check
=
new
ComplexQuery
({
...
@@ -177,7 +177,7 @@
...
@@ -177,7 +177,7 @@
options_remcheck
=
{
options_remcheck
=
{
query
:
query_removed_check
,
query
:
query_removed_check
,
select_list
:
[
"
op
"
,
"
timestamp
"
],
select_list
:
[
"
op
"
,
"
timestamp
"
],
//
limit: [0, 1],
limit
:
[
0
,
1
],
sort_on
:
[[
"
timestamp
"
,
"
descending
"
]]
sort_on
:
[[
"
timestamp
"
,
"
descending
"
]]
};
};
options
=
{
options
=
{
...
@@ -187,8 +187,12 @@
...
@@ -187,8 +187,12 @@
};
};
return
this
.
_sub_storage
.
allDocs
(
options_remcheck
)
return
this
.
_sub_storage
.
allDocs
(
options_remcheck
)
// Check the document exists and is not removed
.
push
(
function
(
results
)
{
.
push
(
function
(
results
)
{
if
(
results
.
data
.
total_rows
>
0
)
{
if
(
results
.
data
.
total_rows
>
0
)
{
if
(
results
.
data
.
rows
[
0
].
id
===
id
)
{
have_seen_id
=
true
;
}
if
(
results
.
data
.
rows
[
0
].
value
.
op
===
"
remove
"
)
{
if
(
results
.
data
.
rows
[
0
].
value
.
op
===
"
remove
"
)
{
throwRemovedError
(
id
);
throwRemovedError
(
id
);
}
}
...
@@ -205,6 +209,18 @@
...
@@ -205,6 +209,18 @@
attachment_promises
=
[],
attachment_promises
=
[],
ind
,
ind
,
entry
;
entry
;
// If input mapped to a real timestamp, then the first query result must
// have the inputted id. Otherwise, unexpected results could arise
// by inputting nonsensical strings as id when include_revisions = true
if
(
include_revs
&&
results
.
data
.
total_rows
>
0
&&
results
.
data
.
rows
[
0
].
id
!==
id
&&
!
have_seen_id
)
{
throwCantFindError
(
id
);
}
// Only return attachments if:
// Only return attachments if:
// (it is the most recent revision) AND (it is a putAttachment)
// (it is the most recent revision) AND (it is a putAttachment)
attachments
=
results
.
data
.
rows
.
filter
(
function
(
docum
)
{
attachments
=
results
.
data
.
rows
.
filter
(
function
(
docum
)
{
...
@@ -257,7 +273,6 @@
...
@@ -257,7 +273,6 @@
// Query to get the last edit made to this document
// Query to get the last edit made to this document
var
substorage
=
this
.
_sub_storage
,
var
substorage
=
this
.
_sub_storage
,
// Include id_in as value in query object for safety
// "doc_id: id AND
// "doc_id: id AND
// (op: remove OR ((op: putAttachment OR op: removeAttachment) AND
// (op: remove OR ((op: putAttachment OR op: removeAttachment) AND
// name: name))"
// name: name))"
...
@@ -295,6 +310,7 @@
...
@@ -295,6 +310,7 @@
return
substorage
.
allDocs
(
options
)
return
substorage
.
allDocs
(
options
)
.
push
(
function
(
results
)
{
.
push
(
function
(
results
)
{
if
(
results
.
data
.
total_rows
>
0
)
{
if
(
results
.
data
.
total_rows
>
0
)
{
// XXX: issue if attachments are put on a removed document
if
(
results
.
data
.
rows
[
0
].
value
.
op
===
"
remove
"
||
if
(
results
.
data
.
rows
[
0
].
value
.
op
===
"
remove
"
||
results
.
data
.
rows
[
0
].
value
.
op
===
"
removeAttachment
"
)
{
results
.
data
.
rows
[
0
].
value
.
op
===
"
removeAttachment
"
)
{
throwRemovedError
(
id
);
throwRemovedError
(
id
);
...
@@ -324,8 +340,6 @@
...
@@ -324,8 +340,6 @@
};
};
HistoryStorage
.
prototype
.
buildQuery
=
function
(
options
)
{
HistoryStorage
.
prototype
.
buildQuery
=
function
(
options
)
{
// XXX: if include_revisions, we should also include the document results
// for different edits of attachments
// Set default values
// Set default values
if
(
options
===
undefined
)
{
options
=
{};
}
if
(
options
===
undefined
)
{
options
=
{};
}
if
(
options
.
query
===
undefined
)
{
options
.
query
=
""
;
}
if
(
options
.
query
===
undefined
)
{
options
.
query
=
""
;
}
...
@@ -338,76 +352,68 @@
...
@@ -338,76 +352,68 @@
options
.
query
=
jIO
.
QueryFactory
.
create
(
options
.
query
);
options
.
query
=
jIO
.
QueryFactory
.
create
(
options
.
query
);
var
meta_options
,
var
meta_options
,
substorage
=
this
.
_sub_storage
,
include_revs
=
this
.
_include_revisions
,
// Check if query involved _timestamp.
// If not, use default behavior and only query on latest revisions
rev_query
=
this
.
_include_revisions
,
doc_id_name
,
doc_id_name
,
timestamp_name
;
timestamp_name
;
// Query for all edits putting or removing documents (and nothing about
// Query for all edits
// attachments)
meta_options
=
{
meta_options
=
{
query
:
""
,
//(op: remove) OR (op: put)",
query
:
""
,
sort_on
:
options
.
sort_on
sort_on
:
options
.
sort_on
,
select_list
:
[
"
doc
"
,
"
op
"
,
"
doc_id
"
]
};
};
return
this
.
_sub_storage
.
allDocs
(
meta_options
)
return
this
.
_sub_storage
.
allDocs
(
meta_options
)
// Get all documents found in query
// XXX: Once include_docs is implemented, this step can be simplified
.
push
(
function
(
results
)
{
var
promises
=
results
.
data
.
rows
.
map
(
function
(
data
)
{
return
substorage
.
get
(
data
.
id
);
});
return
RSVP
.
all
(
promises
);
})
.
push
(
function
(
results
)
{
.
push
(
function
(
results
)
{
results
=
results
.
data
.
rows
;
var
seen
=
{},
var
seen
=
{},
query_matches
,
query_matches
,
docs_to_query
,
docs_to_query
,
i
;
i
;
doc_id_name
=
"
_doc_id
"
;
doc_id_name
=
"
_doc_id
"
;
timestamp_name
=
"
_timestamp
"
;
timestamp_name
=
"
_timestamp
"
;
for
(
i
=
0
;
i
<
results
.
length
;
i
+=
1
)
{
for
(
i
=
0
;
i
<
results
.
length
;
i
+=
1
)
{
if
(
results
[
i
].
op
===
"
put
"
)
{
if
(
results
[
i
].
value
.
op
===
"
put
"
)
{
while
(
results
[
i
].
doc
.
hasOwnProperty
(
doc_id_name
))
{
while
(
results
[
i
].
value
.
doc
.
hasOwnProperty
(
doc_id_name
))
{
doc_id_name
=
"
_
"
+
doc_id_name
;
doc_id_name
=
"
_
"
+
doc_id_name
;
}
}
while
(
results
[
i
].
doc
.
hasOwnProperty
(
timestamp_name
))
{
while
(
results
[
i
].
value
.
doc
.
hasOwnProperty
(
timestamp_name
))
{
timestamp_name
=
"
_
"
+
timestamp_name
;
timestamp_name
=
"
_
"
+
timestamp_name
;
}
}
}
}
}
}
if
(
rev_query
)
{
if
(
include_revs
)
{
// We only query on versions mapping to puts or putAttachments
// We only query on versions mapping to puts or putAttachments
results
=
results
.
map
(
function
(
docum
,
ind
)
{
results
=
results
.
map
(
function
(
docum
,
ind
)
{
var
data_key
;
var
data_key
;
if
(
docum
.
op
===
"
put
"
)
{
if
(
docum
.
value
.
op
===
"
put
"
)
{
return
docum
;
return
docum
;
}
}
if
(
docum
.
op
===
"
putAttachment
"
)
{
if
(
docum
.
value
.
op
===
"
remove
"
)
{
docum
.
value
.
doc
=
{};
return
docum
;
}
if
(
docum
.
value
.
op
===
"
putAttachment
"
||
docum
.
value
.
op
===
"
removeAttachment
"
)
{
// putAttachment document does not contain doc metadata, so we
// putAttachment document does not contain doc metadata, so we
// add it from the most recent non-removed put on same id
// add it from the most recent non-removed put on same id
docum
.
doc
=
{};
docum
.
value
.
doc
=
{};
for
(
i
=
ind
+
1
;
i
<
results
.
length
;
i
+=
1
)
{
for
(
i
=
ind
+
1
;
i
<
results
.
length
;
i
+=
1
)
{
if
(
results
[
i
].
doc_id
===
docum
.
doc_id
)
{
if
(
results
[
i
].
value
.
doc_id
===
docum
.
value
.
doc_id
)
{
if
(
results
[
i
].
op
===
"
put
"
)
{
if
(
results
[
i
].
value
.
op
===
"
put
"
)
{
for
(
data_key
in
results
[
i
].
doc
)
{
for
(
data_key
in
results
[
i
].
value
.
doc
)
{
if
(
results
[
i
].
doc
.
hasOwnProperty
(
data_key
))
{
if
(
results
[
i
].
value
.
doc
.
hasOwnProperty
(
data_key
))
{
docum
.
doc
[
data_key
]
=
results
[
i
].
doc
[
data_key
];
docum
.
value
.
doc
[
data_key
]
=
results
[
i
].
value
.
doc
[
data_key
];
}
}
}
}
return
docum
;
return
docum
;
}
}
// If most recent edit on document was a remove before this
if
(
results
[
i
].
value
.
op
===
"
remove
"
)
{
// attachment, then don't include attachment in query
return
docum
;
if
(
results
[
i
].
doc_id
===
"
remove
"
)
{
return
false
;
}
}
}
}
}
}
...
@@ -420,35 +426,36 @@
...
@@ -420,35 +426,36 @@
// edits
// edits
results
=
results
.
map
(
function
(
docum
,
ind
)
{
results
=
results
.
map
(
function
(
docum
,
ind
)
{
var
data_key
;
var
data_key
;
if
(
docum
.
op
===
"
put
"
)
{
if
(
docum
.
value
.
op
===
"
put
"
)
{
// Mark as read and include in query
// Mark as read and include in query
if
(
!
seen
.
hasOwnProperty
(
docum
.
doc_id
))
{
if
(
!
seen
.
hasOwnProperty
(
docum
.
value
.
doc_id
))
{
seen
[
docum
.
doc_id
]
=
{};
seen
[
docum
.
value
.
doc_id
]
=
{};
return
docum
;
return
docum
;
}
}
}
else
if
(
docum
.
op
===
"
remove
"
||
}
else
if
(
docum
.
value
.
op
===
"
remove
"
||
docum
.
op
===
"
removeAttachment
"
)
{
docum
.
value
.
op
===
"
removeAttachment
"
)
{
// Mark as read but do not include in query
// Mark as read but do not include in query
seen
[
docum
.
doc_id
]
=
{};
seen
[
docum
.
value
.
doc_id
]
=
{};
}
else
if
(
docum
.
op
===
"
putAttachment
"
)
{
}
else
if
(
docum
.
value
.
op
===
"
putAttachment
"
)
{
// If latest edit, mark as read, add document metadata from most
// If latest edit, mark as read, add document metadata from most
// recent put, and add to query
// recent put, and add to query
if
(
!
seen
.
hasOwnProperty
(
docum
.
doc_id
))
{
if
(
!
seen
.
hasOwnProperty
(
docum
.
value
.
doc_id
))
{
seen
[
docum
.
doc_id
]
=
{};
seen
[
docum
.
value
.
doc_id
]
=
{};
docum
.
doc
=
{};
docum
.
value
.
doc
=
{};
for
(
i
=
ind
+
1
;
i
<
results
.
length
;
i
+=
1
)
{
for
(
i
=
ind
+
1
;
i
<
results
.
length
;
i
+=
1
)
{
if
(
results
[
i
].
doc_id
===
docum
.
doc_id
)
{
if
(
results
[
i
].
value
.
doc_id
===
docum
.
value
.
doc_id
)
{
if
(
results
[
i
].
op
===
"
put
"
)
{
if
(
results
[
i
].
value
.
op
===
"
put
"
)
{
for
(
data_key
in
results
[
i
].
doc
)
{
for
(
data_key
in
results
[
i
].
value
.
doc
)
{
if
(
results
[
i
].
doc
.
hasOwnProperty
(
data_key
))
{
if
(
results
[
i
].
value
.
doc
.
hasOwnProperty
(
data_key
))
{
docum
.
doc
[
data_key
]
=
results
[
i
].
doc
[
data_key
];
docum
.
value
.
doc
[
data_key
]
=
results
[
i
].
value
.
doc
[
data_key
];
}
}
}
}
return
docum
;
return
docum
;
}
}
if
(
results
[
i
].
doc_id
===
"
remove
"
)
{
if
(
results
[
i
].
value
.
doc_id
===
"
remove
"
)
{
// If most recent edit on document was a remove before
// If most recent edit on document was a remove before
// this attachment, then don't include attachment in query
// this attachment, then don't include attachment in query
return
false
;
return
false
;
...
@@ -462,16 +469,18 @@
...
@@ -462,16 +469,18 @@
}
}
docs_to_query
=
results
docs_to_query
=
results
// Filter out all docs flagged as false in previous map call
.
filter
(
function
(
docum
)
{
.
filter
(
function
(
docum
)
{
return
docum
;
return
docum
;
})
})
.
map
(
function
(
docum
)
{
.
map
(
function
(
docum
)
{
// Save timestamp and id information for retrieval at the end of
// Save timestamp and id information for retrieval at the end of
// buildQuery
// buildQuery
docum
.
doc
[
timestamp_name
]
=
docum
.
timestamp
;
docum
.
value
.
doc
[
timestamp_name
]
=
docum
.
id
;
docum
.
doc
[
doc_id_name
]
=
docum
.
doc_id
;
docum
.
value
.
doc
[
doc_id_name
]
=
docum
.
value
.
doc_id
;
return
docum
.
doc
;
return
docum
.
value
.
doc
;
});
});
// Return timestamp and id information from query
// Return timestamp and id information from query
options
.
select_list
.
push
(
doc_id_name
);
options
.
select_list
.
push
(
doc_id_name
);
options
.
select_list
.
push
(
timestamp_name
);
options
.
select_list
.
push
(
timestamp_name
);
...
...
test/jio.storage/historystorage.tests.js
View file @
9bf585e5
...
@@ -202,6 +202,41 @@
...
@@ -202,6 +202,41 @@
.
always
(
function
()
{
start
();
});
.
always
(
function
()
{
start
();
});
});
});
test
(
"
get attachment immediately after removing it
"
,
function
()
{
stop
();
expect
(
3
);
var
jio
=
this
.
jio
,
blob1
=
this
.
blob1
;
jio
.
put
(
"
doc
"
,
{
title
:
"
foo0
"
})
.
push
(
function
()
{
return
jio
.
putAttachment
(
"
doc
"
,
"
attacheddata
"
,
blob1
);
})
.
push
(
function
()
{
return
jio
.
removeAttachment
(
"
doc
"
,
"
attacheddata
"
);
})
.
push
(
function
()
{
return
jio
.
getAttachment
(
"
doc
"
,
"
attacheddata
"
);
})
.
push
(
function
()
{
ok
(
false
,
"
This query should have thrown a 404 error
"
);
},
function
(
error
)
{
ok
(
error
instanceof
jIO
.
util
.
jIOError
,
"
throws a jio error
"
);
deepEqual
(
error
.
status_code
,
404
,
"
allAttachments of a removed document throws a 404 error
"
);
deepEqual
(
error
.
message
,
"
HistoryStorage: cannot find object 'doc' (removed)
"
,
"
Error is handled by Historystorage.
"
);
})
.
fail
(
function
(
error
)
{
//console.log(error);
ok
(
false
,
error
);
})
.
always
(
function
()
{
start
();
});
});
test
(
"
Ordering of put and remove attachments is correct
"
,
test
(
"
Ordering of put and remove attachments is correct
"
,
function
()
{
function
()
{
...
@@ -386,7 +421,7 @@
...
@@ -386,7 +421,7 @@
test
(
"
Correctness of allAttachments method on older revisions
"
,
test
(
"
Correctness of allAttachments method on older revisions
"
,
function
()
{
function
()
{
stop
();
stop
();
expect
(
8
);
expect
(
11
);
var
jio
=
this
.
jio
,
var
jio
=
this
.
jio
,
history
=
this
.
history
,
history
=
this
.
history
,
not_history
=
this
.
not_history
,
not_history
=
this
.
not_history
,
...
@@ -488,6 +523,21 @@
...
@@ -488,6 +523,21 @@
data
:
blob11
data
:
blob11
});
});
})
})
.
push
(
function
()
{
return
history
.
allAttachments
(
"
not-a-timestamp-or-doc_id
"
);
})
.
push
(
function
()
{
ok
(
false
,
"
This query should have thrown a 404 error
"
);
},
function
(
error
)
{
ok
(
error
instanceof
jIO
.
util
.
jIOError
,
"
throws a jio error
"
);
deepEqual
(
error
.
status_code
,
404
,
"
allAttachments of a removed document throws a 404 error
"
);
deepEqual
(
error
.
message
,
"
HistoryStorage: cannot find object 'not-a-timestamp-or-doc_id'
"
,
"
Error is handled by Historystorage.
"
);
})
.
fail
(
function
(
error
)
{
.
fail
(
function
(
error
)
{
//console.log(error);
//console.log(error);
ok
(
false
,
error
);
ok
(
false
,
error
);
...
@@ -496,6 +546,7 @@
...
@@ -496,6 +546,7 @@
});
});
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
// Querying older revisions
// Querying older revisions
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
...
@@ -544,6 +595,118 @@
...
@@ -544,6 +595,118 @@
}
}
});
});
test
(
"
Removing documents before putting them
"
,
function
()
{
stop
();
expect
(
4
);
var
jio
=
this
.
jio
,
not_history
=
this
.
not_history
,
timestamps
;
jio
.
remove
(
"
doc
"
)
.
push
(
function
()
{
return
jio
.
put
(
"
doc2
"
,
{
title
:
"
foo
"
});
})
.
push
(
function
()
{
return
jio
.
get
(
"
doc
"
);
})
.
push
(
function
()
{
ok
(
false
,
"
This statement should not be reached
"
);
},
function
(
error
)
{
ok
(
error
instanceof
jIO
.
util
.
jIOError
,
"
Correct type of error
"
);
deepEqual
(
error
.
status_code
,
404
,
"
Correct status code for getting a non-existent document
"
);
deepEqual
(
error
.
message
,
"
HistoryStorage: cannot find object 'doc' (removed)
"
,
"
Error is handled by history storage before reaching console
"
);
})
.
push
(
function
()
{
return
not_history
.
allDocs
({
select_list
:
[
"
timestamp
"
],
sort_on
:
[[
"
timestamp
"
,
"
ascending
"
]]
});
})
.
push
(
function
(
results
)
{
timestamps
=
results
.
data
.
rows
.
map
(
function
(
d
)
{
return
d
.
value
.
timestamp
;
});
})
.
push
(
function
()
{
return
jio
.
allDocs
({
select_list
:
[
"
title
"
]});
})
.
push
(
function
(
results
)
{
deepEqual
(
results
.
data
.
rows
,
[
{
id
:
"
doc2
"
,
value
:
{
title
:
"
foo
"
},
doc
:
{},
timestamp
:
timestamps
[
1
]
}],
"
DOcument that was removed before being put is not retrieved
"
);
})
.
fail
(
function
(
error
)
{
//console.log(error);
ok
(
false
,
error
);
})
.
always
(
function
()
{
start
();
});
});
test
(
"
Removing documents and then putting them
"
,
function
()
{
stop
();
expect
(
2
);
var
jio
=
this
.
jio
,
history
=
this
.
history
,
timestamps
;
jio
.
remove
(
"
doc
"
)
.
push
(
function
()
{
return
jio
.
put
(
"
doc
"
,
{
title
:
"
foo
"
});
})
.
push
(
function
()
{
return
jio
.
get
(
"
doc
"
);
})
.
push
(
function
(
result
)
{
deepEqual
(
result
,
{
title
:
"
foo
"
},
"
A put was the most recent edit on 'doc'
"
);
})
.
push
(
function
()
{
return
history
.
allDocs
({
select_list
:
[
"
timestamp
"
]
});
})
.
push
(
function
(
results
)
{
timestamps
=
results
.
data
.
rows
.
map
(
function
(
d
)
{
return
d
.
timestamp
;
});
})
.
push
(
function
()
{
return
history
.
allDocs
({
select_list
:
[
"
title
"
]});
})
.
push
(
function
(
results
)
{
deepEqual
(
results
.
data
.
rows
,
[
{
id
:
"
doc
"
,
value
:
{
title
:
"
foo
"
},
doc
:
{},
timestamp
:
timestamps
[
0
]
},
{
id
:
"
doc
"
,
value
:
{},
doc
:
{},
timestamp
:
timestamps
[
1
]
}],
"
DOcument that was removed before being put is not retrieved
"
);
})
.
fail
(
function
(
error
)
{
//console.log(error);
ok
(
false
,
error
);
})
.
always
(
function
()
{
start
();
});
});
test
(
"
Handling bad input
"
,
test
(
"
Handling bad input
"
,
function
()
{
function
()
{
stop
();
stop
();
...
@@ -614,7 +777,7 @@
...
@@ -614,7 +777,7 @@
test
(
"
Getting a document with timestamp when include_revisions is false
"
,
test
(
"
Getting a document with timestamp when include_revisions is false
"
,
function
()
{
function
()
{
stop
();
stop
();
expect
(
9
);
expect
(
6
);
var
jio
=
this
.
jio
,
var
jio
=
this
.
jio
,
history
=
this
.
history
,
history
=
this
.
history
,
timestamp
;
timestamp
;
...
@@ -654,10 +817,13 @@
...
@@ -654,10 +817,13 @@
"
HistoryStorage: cannot find object '
"
+
timestamp
+
"
'
"
,
"
HistoryStorage: cannot find object '
"
+
timestamp
+
"
'
"
,
"
Error is handled by history storage before reaching console
"
);
"
Error is handled by history storage before reaching console
"
);
})
})
/**
* XXX: I don't think this test is necessary
.push(function () {
.push(function () {
return history.get("doc");
return history.get("doc");
})
})
.
push
(
function
()
{
.push(function (res) {
console.log(res);
ok(false, "This statement should not be reached");
ok(false, "This statement should not be reached");
}, function (error) {
}, function (error) {
//console.log(error);
//console.log(error);
...
@@ -670,6 +836,8 @@
...
@@ -670,6 +836,8 @@
"HistoryStorage: cannot find object 'doc'",
"HistoryStorage: cannot find object 'doc'",
"Error is handled by history storage before reaching console");
"Error is handled by history storage before reaching console");
})
})
**/
.
fail
(
function
(
error
)
{
.
fail
(
function
(
error
)
{
//console.log(error);
//console.log(error);
ok
(
false
,
error
);
ok
(
false
,
error
);
...
@@ -920,6 +1088,52 @@
...
@@ -920,6 +1088,52 @@
.
always
(
function
()
{
start
();
});
.
always
(
function
()
{
start
();
});
});
});
test
(
"
Getting after attachments have been put
"
,
function
()
{
stop
();
expect
(
4
);
var
jio
=
this
.
jio
,
history
=
this
.
history
,
blob
=
new
Blob
([
'
a
'
]),
edit_log
;
jio
.
put
(
"
doc
"
,
{
"
title
"
:
"
foo0
"
})
.
push
(
function
()
{
return
jio
.
putAttachment
(
"
doc
"
,
"
attachment
"
,
blob
);
})
.
push
(
function
()
{
return
jio
.
removeAttachment
(
"
doc
"
,
"
attachment
"
,
blob
);
})
.
push
(
function
()
{
return
jio
.
get
(
"
doc
"
);
})
.
push
(
function
(
res
)
{
deepEqual
(
res
,
{
title
:
"
foo0
"
});
return
history
.
allDocs
({
select_list
:
[
"
title
"
]});
})
.
push
(
function
(
results
)
{
edit_log
=
results
.
data
.
rows
;
return
history
.
get
(
edit_log
[
0
].
timestamp
);
})
.
push
(
function
(
result
)
{
deepEqual
(
result
,
{
title
:
"
foo0
"
});
return
history
.
get
(
edit_log
[
1
].
timestamp
);
})
.
push
(
function
(
result
)
{
deepEqual
(
result
,
{
title
:
"
foo0
"
});
return
history
.
get
(
edit_log
[
2
].
timestamp
);
})
.
push
(
function
(
result
)
{
deepEqual
(
result
,
{
title
:
"
foo0
"
});
})
.
fail
(
function
(
error
)
{
//console.log(error);
ok
(
false
,
error
);
})
.
always
(
function
()
{
start
();
});
});
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
// Querying older revisions
// Querying older revisions
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
...
@@ -1656,10 +1870,10 @@
...
@@ -1656,10 +1870,10 @@
})
})
.
push
(
function
()
{
.
push
(
function
()
{
return
history
.
allDocs
({
return
history
.
allDocs
({
query
:
"
NOT (date: >= 2 AND date: <= 3)
"
,
query
:
"
NOT (date: >= 2 AND date: <= 3) AND
"
+
"
(date: = 1 OR date: = 4)
"
,
select_list
:
[
"
date
"
,
"
non-existent-key
"
,
"
type
"
,
"
title
"
],
select_list
:
[
"
date
"
,
"
non-existent-key
"
,
"
type
"
,
"
title
"
],
sort_on
:
[[
"
date
"
,
"
descending
"
]
sort_on
:
[[
"
date
"
,
"
descending
"
]]
]
});
});
})
})
.
push
(
function
(
results
)
{
.
push
(
function
(
results
)
{
...
@@ -1724,16 +1938,194 @@
...
@@ -1724,16 +1938,194 @@
type
:
"
foo
"
type
:
"
foo
"
},
},
timestamp
:
timestamps
[
1
]
timestamp
:
timestamps
[
1
]
}
],
"
Query gives correct results in correct order
"
);
})
.
fail
(
function
(
error
)
{
//console.log(error);
ok
(
false
,
error
);
})
.
always
(
function
()
{
start
();
});
});
test
(
"
allDocs with include_revisions with an attachment on a removed document
"
,
function
()
{
stop
();
expect
(
1
);
var
jio
=
this
.
jio
,
history
=
this
.
history
,
not_history
=
this
.
not_history
,
timestamps
,
blob
=
new
Blob
([
'
a
'
]);
jio
.
put
(
"
document
"
,
{
title
:
"
foo
"
})
.
push
(
function
()
{
return
jio
.
remove
(
"
document
"
);
})
.
push
(
function
()
{
return
jio
.
putAttachment
(
"
document
"
,
"
attachment
"
,
blob
);
})
// Get timestamps
.
push
(
function
()
{
return
not_history
.
allDocs
({
sort_on
:
[[
"
timestamp
"
,
"
ascending
"
]]
});
})
.
push
(
function
(
results
)
{
timestamps
=
results
.
data
.
rows
.
map
(
function
(
d
)
{
return
d
.
id
;
});
})
.
push
(
function
()
{
return
history
.
allDocs
({
select_list
:
[
"
title
"
]});
})
.
push
(
function
(
results
)
{
deepEqual
(
results
.
data
.
rows
,
[
{
id
:
"
document
"
,
doc
:
{},
value
:
{},
timestamp
:
timestamps
[
2
]
},
},
{
{
id
:
"
document
"
,
doc
:
{},
doc
:
{},
id
:
"
doc
"
,
value
:
{},
value
:
{},
timestamp
:
timestamps
[
1
]
},
{
id
:
"
document
"
,
doc
:
{},
value
:
{
title
:
"
foo
"
},
timestamp
:
timestamps
[
0
]
timestamp
:
timestamps
[
0
]
}],
"
Attachment on removed document is handled correctly
"
);
return
not_history
.
allDocs
({
select_list
:
[
"
doc
"
]});
})
.
fail
(
function
(
error
)
{
//console.log(error);
ok
(
false
,
error
);
})
.
always
(
function
()
{
start
();
});
}
}
],
);
"
Query gives correct results in correct order
"
);
test
(
"
allDocs with include_revisions with a removed attachment
"
,
function
()
{
stop
();
expect
(
2
);
var
jio
=
this
.
jio
,
history
=
this
.
history
,
not_history
=
this
.
not_history
,
timestamps
,
blob
=
new
Blob
([
'
a
'
]);
jio
.
put
(
"
document
"
,
{
title
:
"
foo
"
})
.
push
(
function
()
{
return
jio
.
putAttachment
(
"
document
"
,
"
attachment
"
,
blob
);
})
.
push
(
function
()
{
return
jio
.
removeAttachment
(
"
document
"
,
"
attachment
"
);
})
// Get timestamps
.
push
(
function
()
{
return
not_history
.
allDocs
({
sort_on
:
[[
"
timestamp
"
,
"
ascending
"
]]
});
})
.
push
(
function
(
results
)
{
timestamps
=
results
.
data
.
rows
.
map
(
function
(
d
)
{
return
d
.
id
;
});
})
.
push
(
function
()
{
return
history
.
allDocs
({
select_list
:
[
"
title
"
]});
})
.
push
(
function
(
results
)
{
deepEqual
(
results
.
data
.
rows
,
[
{
id
:
"
document
"
,
doc
:
{},
value
:
{
title
:
"
foo
"
},
timestamp
:
timestamps
[
2
]
},
{
id
:
"
document
"
,
doc
:
{},
value
:
{
title
:
"
foo
"
},
timestamp
:
timestamps
[
1
]
},
{
id
:
"
document
"
,
doc
:
{},
value
:
{
title
:
"
foo
"
},
timestamp
:
timestamps
[
0
]
}],
"
Attachment on removed document is handled correctly
"
);
})
.
push
(
function
()
{
return
jio
.
allAttachments
(
"
document
"
);
})
})
.
push
(
function
(
results
)
{
deepEqual
(
results
,
{},
"
No non-removed attachments
"
);
})
.
fail
(
function
(
error
)
{
//console.log(error);
ok
(
false
,
error
);
})
.
always
(
function
()
{
start
();
});
});
test
(
"
Parallel edits will not break anything
"
,
function
()
{
stop
();
expect
(
2
);
var
jio
=
this
.
jio
,
history
=
this
.
history
,
blob1
=
new
Blob
([
'
ab
'
]),
blob2
=
new
Blob
([
'
abc
'
]),
blob3
=
new
Blob
([
'
abcd
'
]);
jio
.
put
(
"
doc
"
,
{
k
:
"
v0
"
})
.
push
(
function
()
{
return
RSVP
.
all
([
jio
.
put
(
"
doc
"
,
{
k
:
"
v
"
}),
jio
.
putAttachment
(
"
doc
"
,
"
data
"
,
blob1
),
jio
.
putAttachment
(
"
doc
"
,
"
data2
"
,
blob2
),
jio
.
putAttachment
(
"
doc
"
,
"
data
"
,
blob3
),
jio
.
removeAttachment
(
"
doc
"
,
"
data
"
),
jio
.
removeAttachment
(
"
doc
"
,
"
data2
"
),
jio
.
remove
(
"
doc
"
),
jio
.
remove
(
"
doc
"
),
jio
.
put
(
"
doc
"
,
{
k
:
"
v
"
}),
jio
.
put
(
"
doc
"
,
{
k
:
"
v
"
}),
jio
.
put
(
"
doc2
"
,
{
k
:
"
foo
"
}),
jio
.
remove
(
"
doc
"
),
jio
.
remove
(
"
doc
"
)
]);
})
.
push
(
function
()
{
ok
(
true
,
"
No errors thrown.
"
);
return
history
.
allDocs
();
})
.
push
(
function
(
results
)
{
var
res
=
results
.
data
.
rows
;
equal
(
res
.
length
,
14
,
"
All edits are recorded regardless of ordering
"
);
return
jio
.
allDocs
();
})
.
fail
(
function
(
error
)
{
.
fail
(
function
(
error
)
{
//console.log(error);
//console.log(error);
ok
(
false
,
error
);
ok
(
false
,
error
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment