| #!/usr/bin/env escript |
| %% -*- erlang -*- |
| %%! -pa ./src/couchdb -pa ./src/mochiweb -sasl errlog_type false -noshell |
| |
| % Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| % use this file except in compliance with the License. You may obtain a copy of |
| % the License at |
| % |
| % http://www.apache.org/licenses/LICENSE-2.0 |
| % |
| % Unless required by applicable law or agreed to in writing, software |
| % distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| % WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| % License for the specific language governing permissions and limitations under |
| % the License. |
| |
| %% XXX: Figure out how to -include("couch_db.hrl") |
| -record(doc, {id= <<"">>, revs={0, []}, body={[]}, |
| atts=[], deleted=false, meta=[]}). |
| -record(att, {name, type, len, md5= <<>>, revpos=0, data}). |
| |
| main(_) -> |
| test_util:init_code_path(), |
| etap:plan(26), |
| case (catch test()) of |
| ok -> |
| etap:end_tests(); |
| Other -> |
| etap:diag(io_lib:format("Test died abnormally: ~p", [Other])), |
| etap:bail() |
| end, |
| ok. |
| |
| test() -> |
| ok = test_from_json_success(), |
| ok = test_from_json_errors(), |
| ok. |
| |
| test_from_json_success() -> |
| Cases = [ |
| { |
| {[]}, |
| #doc{}, |
| "Return an empty document for an empty JSON object." |
| }, |
| { |
| {[{<<"_id">>, <<"zing!">>}]}, |
| #doc{id= <<"zing!">>}, |
| "Parses document ids." |
| }, |
| { |
| {[{<<"_id">>, <<"_design/foo">>}]}, |
| #doc{id= <<"_design/foo">>}, |
| "_design/document ids." |
| }, |
| { |
| {[{<<"_id">>, <<"_local/bam">>}]}, |
| #doc{id= <<"_local/bam">>}, |
| "_local/document ids." |
| }, |
| { |
| {[{<<"_rev">>, <<"4-230234">>}]}, |
| #doc{revs={4, [<<"230234">>]}}, |
| "_rev stored in revs." |
| }, |
| { |
| {[{<<"soap">>, 35}]}, |
| #doc{body={[{<<"soap">>, 35}]}}, |
| "Non underscore prefixed fields stored in body." |
| }, |
| { |
| {[{<<"_attachments">>, {[ |
| {<<"my_attachment.fu">>, {[ |
| {<<"stub">>, true}, |
| {<<"content_type">>, <<"application/awesome">>}, |
| {<<"length">>, 45} |
| ]}}, |
| {<<"noahs_private_key.gpg">>, {[ |
| {<<"data">>, <<"SSBoYXZlIGEgcGV0IGZpc2gh">>}, |
| {<<"content_type">>, <<"application/pgp-signature">>} |
| ]}} |
| ]}}]}, |
| #doc{atts=[ |
| #att{ |
| name = <<"my_attachment.fu">>, |
| data = stub, |
| type = <<"application/awesome">>, |
| len = 45 |
| }, |
| #att{ |
| name = <<"noahs_private_key.gpg">>, |
| data = <<"I have a pet fish!">>, |
| type = <<"application/pgp-signature">>, |
| len = 18 |
| } |
| ]}, |
| "Attachments are parsed correctly." |
| }, |
| { |
| {[{<<"_deleted">>, true}]}, |
| #doc{deleted=true}, |
| "_deleted controls the deleted field." |
| }, |
| { |
| {[{<<"_deleted">>, false}]}, |
| #doc{}, |
| "{\"_deleted\": false} is ok." |
| }, |
| { |
| {[ |
| {<<"_revisions">>, {[ |
| {<<"start">>, 4}, |
| {<<"ids">>, [<<"foo1">>, <<"phi3">>, <<"omega">>]} |
| ]}}, |
| {<<"_rev">>, <<"6-something">>} |
| ]}, |
| #doc{revs={4, [<<"foo1">>, <<"phi3">>, <<"omega">>]}}, |
| "_revisions attribute are preferred to _rev." |
| }, |
| { |
| {[{<<"_revs_info">>, dropping}]}, |
| #doc{}, |
| "Drops _revs_info." |
| }, |
| { |
| {[{<<"_local_seq">>, dropping}]}, |
| #doc{}, |
| "Drops _local_seq." |
| }, |
| { |
| {[{<<"_conflicts">>, dropping}]}, |
| #doc{}, |
| "Drops _conflicts." |
| }, |
| { |
| {[{<<"_deleted_conflicts">>, dropping}]}, |
| #doc{}, |
| "Drops _deleted_conflicts." |
| } |
| ], |
| |
| lists:foreach(fun({EJson, Expect, Mesg}) -> |
| etap:is(couch_doc:from_json_obj(EJson), Expect, Mesg) |
| end, Cases), |
| ok. |
| |
| test_from_json_errors() -> |
| Cases = [ |
| { |
| [], |
| {bad_request, "Document must be a JSON object"}, |
| "arrays are invalid" |
| }, |
| { |
| 4, |
| {bad_request, "Document must be a JSON object"}, |
| "integers are invalid" |
| }, |
| { |
| true, |
| {bad_request, "Document must be a JSON object"}, |
| "literals are invalid" |
| }, |
| { |
| {[{<<"_id">>, {[{<<"foo">>, 5}]}}]}, |
| {bad_request, <<"Document id must be a string">>}, |
| "Document id must be a string." |
| }, |
| { |
| {[{<<"_id">>, <<"_random">>}]}, |
| {bad_request, |
| <<"Only reserved document ids may start with underscore.">>}, |
| "Disallow arbitrary underscore prefixed docids." |
| }, |
| { |
| {[{<<"_rev">>, 5}]}, |
| {bad_request, <<"Invalid rev format">>}, |
| "_rev must be a string" |
| }, |
| { |
| {[{<<"_rev">>, "foobar"}]}, |
| {bad_request, <<"Invalid rev format">>}, |
| "_rev must be %d-%s" |
| }, |
| { |
| {[{<<"_rev">>, "foo-bar"}]}, |
| "Error if _rev's integer expection is broken." |
| }, |
| { |
| {[{<<"_revisions">>, {[{<<"start">>, true}]}}]}, |
| {doc_validation, "_revisions.start isn't an integer."}, |
| "_revisions.start must be an integer." |
| }, |
| { |
| {[{<<"_revisions">>, {[ |
| {<<"start">>, 0}, |
| {<<"ids">>, 5} |
| ]}}]}, |
| {doc_validation, "_revisions.ids isn't a array."}, |
| "_revions.ids must be a list." |
| }, |
| { |
| {[{<<"_revisions">>, {[ |
| {<<"start">>, 0}, |
| {<<"ids">>, [5]} |
| ]}}]}, |
| {doc_validation, "RevId isn't a string"}, |
| "Revision ids must be strings." |
| }, |
| { |
| {[{<<"_something">>, 5}]}, |
| {doc_validation, <<"Bad special document member: _something">>}, |
| "Underscore prefix fields are reserved." |
| } |
| ], |
| |
| lists:foreach(fun |
| ({EJson, Expect, Mesg}) -> |
| Error = (catch couch_doc:from_json_obj(EJson)), |
| etap:is(Error, Expect, Mesg); |
| ({EJson, Mesg}) -> |
| try |
| couch_doc:from_json_obj(EJson), |
| etap:ok(false, "Conversion failed to raise an exception.") |
| catch |
| _:_ -> etap:ok(true, Mesg) |
| end |
| end, Cases), |
| ok. |