Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Objective-C view support for Couchbase Mobile iOS

This is a squashed commit of all the work done on other
branches by Jonathon Mah & me.

This commit adds source files to the Xcode project and Erlang
build script; modifies some .ini and .app files;
and adds unit tests.

Change-Id: Idd8e6ef87efbeb9ade62868467b822dff8fbf357
Reviewed-on: http://review.couchbase.org/10021
Tested-by: Farshid Ghods <farshid.ghods@gmail.com>
Reviewed-by: Jens Alfke <jens@couchbase.com>
  • Loading branch information...
commit 5a83f1c4d3039cf4ca10609e7a0e28f39a381d21 1 parent 3006c93
@snej snej authored
View
106 EmptyApp/Tests/EmptyAppTests.m
@@ -8,6 +8,7 @@
#import "EmptyAppTests.h"
#import <Couchbase/CouchbaseMobile.h>
+#import <Couchbase/CouchbaseCallbacks.h>
extern BOOL sUnitTesting;
extern CouchbaseMobile* sCouchbase; // Defined in EmptyAppDelegate.m
@@ -198,4 +199,109 @@ - (void)test4_Collation {
}
+- (void)test5_ObjCViews {
+ [self send: @"PUT" toPath: @"/unittestdb" body: nil];
+ [self send: @"PUT" toPath: @"/unittestdb/doc1" body: @"{\"txt\":\"O HAI MR Obj-C!\","
+ "\"numbers\": {\"int\": 1234567, \"float\": 1234.5678, \"zero\": 0},"
+ "\"bignum\": 12345678901234567890,"
+ "\"special\": [false, null, true],"
+ "\"empty array\":[],"
+ "\"empty dict\": {}}"];
+
+ [[CouchbaseCallbacks sharedInstance] registerMapBlock:
+ ^(NSDictionary *doc, CouchEmitBlock emit) {
+ NSString* txt = [doc objectForKey: @"txt"];
+ NSLog(@"In map block: txt=%@", txt);
+ NSAssert(txt != nil, @"Missing txt key");
+ if ([txt isEqualToString: @"O HAI MR Obj-C!"]) {
+ // this is the doc with test values:
+ NSDictionary* numbers = [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithInt: 1234567], @"int",
+ [NSNumber numberWithDouble: 1234.5678], @"float",
+ [NSNumber numberWithInt: 0], @"zero", nil];
+ STAssertEqualObjects(numbers, [doc objectForKey: @"numbers"], nil);
+ STAssertEqualsWithAccuracy([[doc objectForKey: @"bignum"] doubleValue],
+ 12345678901234567890.0, 1.0, nil);
+ NSArray* special = [NSArray arrayWithObjects: (id)kCFBooleanFalse,
+ [NSNull null], kCFBooleanTrue, nil];
+ STAssertEqualObjects(special, [doc objectForKey: @"special"], nil);
+ STAssertEqualObjects([NSArray array], [doc objectForKey: @"empty array"], nil);
+ STAssertEqualObjects([NSDictionary dictionary], [doc objectForKey: @"empty dict"], nil);
+ }
+ emit(txt, nil);
+ } forKey: @"testValuesMap"];
+
+ [[CouchbaseCallbacks sharedInstance] registerMapBlock:
+ ^(NSDictionary *doc, CouchEmitBlock emit) {
+ NSLog(@"In faux map block");
+ emit(@"objc", nil);
+ } forKey: @"fauxMap"];
+
+
+ [[CouchbaseCallbacks sharedInstance] registerReduceBlock:
+ ^ id (NSArray *keys, NSArray *values, BOOL rereduce) {
+ NSLog(@"In reduce block");
+ return [NSNumber numberWithUnsignedInteger:values.count];
+ } forKey:@"count"];
+
+ [self send: @"PUT" toPath: @"/unittestdb/_design/objcview"
+ body: @"{\"language\":\"objc\", \"views\":"
+ @"{\"testobjc\":{\"map\":\"testValuesMap\","
+ @"\"reduce\":\"count\"},"
+ @"\"testmap2\":{\"map\":\"fauxMap\","
+ @"\"reduce\":\"count\"}}}"];
+
+ NSDictionary* headers;
+ [self send: @"GET" toPath: @"/unittestdb/_design/objcview/_view/testobjc"
+ body: nil responseHeaders: &headers];
+ NSString* eTag = [headers objectForKey: @"Etag"];
+ NSLog(@"ETag: %@", eTag);
+ STAssertNotNil(eTag, nil);
+ [self send: @"GET" toPath: @"/unittestdb/_design/objcview/_view/testobjc"
+ body: nil responseHeaders: &headers];
+ NSLog(@"ETag: %@", [headers objectForKey: @"Etag"]);
+ STAssertEqualObjects([headers objectForKey: @"Etag"], eTag, @"View eTag isn't stable");
+
+ [self send: @"PUT" toPath: @"/unittestdb/doc2" body: @"{\"txt\":\"KTHXBYE\"}"];
+
+ [self send: @"GET" toPath: @"/unittestdb/_design/objcview/_view/testobjc"
+ body: nil responseHeaders: &headers];
+ NSLog(@"ETag: %@", [headers objectForKey: @"Etag"]);
+ STAssertFalse([eTag isEqualToString: [headers objectForKey: @"Etag"]], @"View didn't update");
+}
+
+
+- (void) test6_ObjCValidation {
+ [[CouchbaseCallbacks sharedInstance] registerValidateUpdateBlock:
+ ^BOOL(NSDictionary *doc, id<CouchbaseValidationContext> context) {
+ STAssertEqualObjects(context.databaseName, @"unittestdb", nil);
+ STAssertNil(context.userName, nil);
+ STAssertTrue(context.isAdmin, nil);
+ STAssertNotNil(context.security, nil);
+ BOOL ok = [doc objectForKey: @"valid"] != nil;
+ NSLog(@"In validation block; returning %i", ok);
+ if (!ok)
+ context.errorMessage = @"totally bogus";
+ return ok;
+ } forKey: @"VALIDATE"];
+
+ [self send: @"PUT" toPath: @"/unittestdb" body: nil];
+ [self send: @"PUT" toPath: @"/unittestdb/_design/objcvalidation"
+ body: @"{\"language\":\"objc\","
+ @"\"validate_doc_update\":\"VALIDATE\"}"];
+
+ [self send: @"PUT" toPath: @"/unittestdb/doc1" body: @"{\"valid\":true}"];
+
+ NSURLRequest* request = [self request:@"PUT" path:@"/unittestdb/doc2"
+ body:@"{\"something\":\"O HAI\"}"];
+ NSHTTPURLResponse* response = nil;
+ NSData* output = [NSURLConnection sendSynchronousRequest: request
+ returningResponse: (NSURLResponse**)&response
+ error: NULL];
+ STAssertEquals(response.statusCode, 403, @"Unexpected HTTP status (should be forbidden)");
+ NSString* outputStr = [[[NSString alloc] initWithData: output encoding: NSUTF8StringEncoding] autorelease];
+ STAssertEqualObjects(outputStr, @"{\"error\":\"forbidden\",\"reason\":\"totally bogus\"}\n", nil);
+}
+
+
@end
View
8 Framework/Couchbase.xcodeproj/project.pbxproj
@@ -14,6 +14,7 @@
273A734213BD4DE90078870D /* default.ini in Copy into CouchbaseResources */ = {isa = PBXBuildFile; fileRef = 3D4791CB12A19F6A00581D10 /* default.ini */; };
278FE89713E74C7A009FEE49 /* libiMonkey.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 27167ECD13C4E64B001CC5B6 /* libiMonkey.a */; };
27A74EAF13D4E64D00522F59 /* default_ios.ini in Copy into CouchbaseResources */ = {isa = PBXBuildFile; fileRef = 3D4791CC12A19F6A00581D10 /* default_ios.ini */; };
+ 27CB6548143A5EC900EEA1F2 /* CouchbaseCallbacks.h in Copy Header(s) */ = {isa = PBXBuildFile; fileRef = 27CB6547143A5EC900EEA1F2 /* CouchbaseCallbacks.h */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -34,6 +35,7 @@
dstSubfolderSpec = 1;
files = (
273A733613BD473D0078870D /* CouchbaseMobile.h in Copy Header(s) */,
+ 27CB6548143A5EC900EEA1F2 /* CouchbaseCallbacks.h in Copy Header(s) */,
);
name = "Copy Header(s)";
runOnlyForDeploymentPostprocessing = 0;
@@ -69,6 +71,8 @@
278FE82C13E72604009FEE49 /* ibrowse */ = {isa = PBXFileReference; lastKnownFileType = folder; name = ibrowse; path = src/ibrowse; sourceTree = "<group>"; };
278FE82D13E72604009FEE49 /* mochiweb */ = {isa = PBXFileReference; lastKnownFileType = folder; name = mochiweb; path = src/mochiweb; sourceTree = "<group>"; };
27A72C3413C502980096E41D /* libCouchbase.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libCouchbase.a; sourceTree = BUILT_PRODUCTS_DIR; };
+ 27CB6547143A5EC900EEA1F2 /* CouchbaseCallbacks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CouchbaseCallbacks.h; path = "../../../vendor/couchdb/src/objc-dispatch/c_src/CouchbaseCallbacks.h"; sourceTree = "<group>"; };
+ 2849E7A21424A2970075C6DE /* objc-dispatch */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "objc-dispatch"; path = "src/objc-dispatch"; sourceTree = "<group>"; };
3D4791CB12A19F6A00581D10 /* default.ini */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = default.ini; sourceTree = "<group>"; };
3D4791CC12A19F6A00581D10 /* default_ios.ini */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = default_ios.ini; sourceTree = "<group>"; };
3DEAEA6612A2D70B00EEBD22 /* erlang */ = {isa = PBXFileReference; lastKnownFileType = folder; name = erlang; path = ../erlang; sourceTree = "<group>"; };
@@ -95,6 +99,7 @@
children = (
79C3C6F4131F011A00C8B96D /* CouchbaseMobile.h */,
79C3C6F5131F011A00C8B96D /* CouchbaseMobile.m */,
+ 27CB6547143A5EC900EEA1F2 /* CouchbaseCallbacks.h */,
);
path = Classes;
sourceTree = "<group>";
@@ -117,6 +122,7 @@
278FE82B13E72604009FEE49 /* erlang-oauth */,
278FE82C13E72604009FEE49 /* ibrowse */,
278FE82D13E72604009FEE49 /* mochiweb */,
+ 2849E7A21424A2970075C6DE /* objc-dispatch */,
);
name = CouchDB;
path = ../../vendor/couchdb;
@@ -308,7 +314,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "# Copies the canned 'erlang' directory into CouchbaseResources, and compiles CouchDB and other libraries into that destination directory.\nScripts/build_erlang_packages.sh\nScripts/concat_js_files.sh";
+ shellScript = "# Copies the canned 'erlang' directory into CouchbaseResources, and compiles CouchDB and other libraries into that destination directory.\nset -e # bail out on error\nScripts/build_erlang_packages.sh\nScripts/concat_js_files.sh";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
View
6 Framework/Resources/default_ios.ini
@@ -29,6 +29,12 @@ file = $INSTALLDIR/log/couch.log
num_threads = 2
mapred_js = $BUNDLEDIR/erlang/emonk_mapred.js
+[view_servers]
+objc = {couch_view_server_objc, nil}
+
+[app_servers]
+objc = {couch_app_server_objc, nil}
+
[app_server_emonk]
source = $BUNDLEDIR/erlang/emonk_app.js
View
4 Framework/Scripts/build_erlang_packages.sh
@@ -15,7 +15,7 @@ echo "Copying erlang dir to ${ERLANG_DSTDIR}"
ditto "${SRCROOT}/erlang" "${ERLANG_DSTDIR}"
# Now compile the Erlang libraries we build from source:
-$COMPILE "../../vendor/couchdb/src/couchdb" "couch.erl couch_api_wrap.erl couch_api_wrap_httpc.erl couch_app.erl couch_app_server.erl couch_app_server_emonk.erl couch_app_server_erlang.erl couch_auth_cache.erl couch_btree.erl couch_changes.erl couch_compaction_daemon.erl couch_compress.erl couch_compress_types.erl couch_config.erl couch_config_writer.erl couch_db.erl couch_db_frontend.erl couch_db_update_notifier.erl couch_db_update_notifier_sup.erl couch_db_updater.erl couch_doc.erl couch_drv.erl couch_event_sup.erl couch_external_manager.erl couch_external_server.erl couch_file.erl couch_httpc_pool.erl couch_httpd.erl couch_httpd_auth.erl couch_httpd_db.erl couch_httpd_external.erl couch_httpd_misc_handlers.erl couch_httpd_oauth.erl couch_httpd_proxy.erl couch_httpd_replicator.erl couch_httpd_rewrite.erl couch_httpd_show.erl couch_httpd_stats_handlers.erl couch_httpd_vhost.erl couch_httpd_view.erl couch_httpd_view_merger.erl couch_internal_load_gen.erl couch_key_tree.erl couch_log.erl couch_native_process.erl couch_os_daemons.erl couch_os_process.erl couch_primary_sup.erl couch_query_servers.erl couch_ref_counter.erl couch_rep_sup.erl couch_replication_manager.erl couch_replication_notifier.erl couch_replicator.erl couch_replicator_doc_copier.erl couch_replicator_rev_finder.erl couch_replicator_utils.erl couch_secondary_sup.erl couch_server.erl couch_server_sup.erl couch_stats_aggregator.erl couch_stats_collector.erl couch_stream.erl couch_task_status.erl couch_util.erl couch_uuids.erl couch_view.erl couch_view_compactor.erl couch_view_group.erl couch_view_merger.erl couch_view_server.erl couch_view_server_emonk.erl couch_view_server_erlang.erl couch_view_server_os.erl couch_view_updater.erl couch_work_queue.erl json_stream_parse.erl couch_ios.erl" "$ERLANG_DSTDIR/lib/couch/ebin"
+$COMPILE "../../vendor/couchdb/src/couchdb" "couch.erl couch_api_wrap.erl couch_api_wrap_httpc.erl couch_app.erl couch_app_server.erl couch_app_server_emonk.erl couch_app_server_erlang.erl couch_app_server_objc.erl couch_auth_cache.erl couch_btree.erl couch_changes.erl couch_compaction_daemon.erl couch_compress.erl couch_compress_types.erl couch_config.erl couch_config_writer.erl couch_db.erl couch_db_frontend.erl couch_db_update_notifier.erl couch_db_update_notifier_sup.erl couch_db_updater.erl couch_doc.erl couch_drv.erl couch_event_sup.erl couch_external_manager.erl couch_external_server.erl couch_file.erl couch_httpc_pool.erl couch_httpd.erl couch_httpd_auth.erl couch_httpd_db.erl couch_httpd_external.erl couch_httpd_misc_handlers.erl couch_httpd_oauth.erl couch_httpd_proxy.erl couch_httpd_replicator.erl couch_httpd_rewrite.erl couch_httpd_show.erl couch_httpd_stats_handlers.erl couch_httpd_vhost.erl couch_httpd_view.erl couch_httpd_view_merger.erl couch_internal_load_gen.erl couch_key_tree.erl couch_log.erl couch_native_process.erl couch_os_daemons.erl couch_os_process.erl couch_primary_sup.erl couch_query_servers.erl couch_ref_counter.erl couch_rep_sup.erl couch_replication_manager.erl couch_replication_notifier.erl couch_replicator.erl couch_replicator_doc_copier.erl couch_replicator_rev_finder.erl couch_replicator_utils.erl couch_secondary_sup.erl couch_server.erl couch_server_sup.erl couch_stats_aggregator.erl couch_stats_collector.erl couch_stream.erl couch_task_status.erl couch_util.erl couch_uuids.erl couch_view.erl couch_view_compactor.erl couch_view_group.erl couch_view_merger.erl couch_view_server.erl couch_view_server_emonk.erl couch_view_server_erlang.erl couch_view_server_objc.erl couch_view_server_os.erl couch_view_updater.erl couch_work_queue.erl json_stream_parse.erl couch_ios.erl" "$ERLANG_DSTDIR/lib/couch/ebin"
$COMPILE "../../vendor/couchdb/src/erlang-oauth" "oauth.erl oauth_hmac_sha1.erl oauth_http.erl oauth_plaintext.erl oauth_rsa_sha1.erl oauth_unix.erl oauth_uri.erl" "$ERLANG_DSTDIR/lib/erlang-oauth/ebin"
@@ -29,6 +29,8 @@ $COMPILE "../../vendor/couchdb/src/snappy" "snappy.erl" "$ERLANG_DSTDIR/lib/snap
$COMPILE "../../vendor/couchdb/src/emonk/src" "emonk.erl" "$ERLANG_DSTDIR/lib/emonk/ebin"
+$COMPILE "../../vendor/couchdb/src/objc-dispatch/src" "objc_dispatch.erl" "$ERLANG_DSTDIR/lib/objc-dispatch/ebin"
+
$COMPILE "../../vendor/geocouch/src/geocouch" "couch_httpd_spatial.erl couch_spatial.erl couch_spatial_compactor.erl couch_spatial_updater.erl couch_httpd_spatial_list.erl couch_spatial_group.erl geocouch_duplicates.erl" "$ERLANG_DSTDIR/lib/geocouch/ebin" "../../../couchdb/src/couchdb"
$COMPILE "../../vendor/geocouch/src/vtree" "vtree.erl vtree_bulk.erl vtree_insbench.erl vtreestats.erl vtreeviz.erl" "$ERLANG_DSTDIR/lib/geocouch/ebin" "../../../couchdb/src/couchdb"
View
2  Framework/erlang/lib/couch/ebin/couch.app
@@ -1,7 +1,7 @@
{application, couch, [
{description, "Couchbase Mobile"},
{vsn, "2.0.0-beta"},
- {modules, [couch,couch_app,couch_app_server,couch_app_server_emonk,couch_app_server_erlang,couch_app_server_os,couch_auth_cache,couch_btree,couch_changes,couch_config,couch_config_writer,couch_db,couch_db_update_notifier,couch_db_update_notifier_sup,couch_db_updater,couch_doc,couch_event_sup,couch_external_manager,couch_external_server,couch_file,couch_httpd,couch_httpd_auth,couch_httpd_db,couch_httpd_external,couch_httpd_misc_handlers,couch_httpd_oauth,couch_httpd_rewrite,couch_httpd_show,couch_httpd_stats_handlers,couch_httpd_vhost,couch_httpd_view,couch_key_tree,couch_log,couch_native_process,couch_os_process,couch_query_servers,couch_ref_counter,couch_rep,couch_rep_att,couch_rep_changes_feed,couch_rep_db_listener,couch_rep_httpc,couch_rep_missing_revs,couch_rep_reader,couch_rep_sup,couch_rep_writer,couch_server,couch_server_sup,couch_stats_aggregator,couch_stats_collector,couch_stream,couch_task_status,couch_util,couch_uuids,couch_view,couch_view_compactor,couch_view_group,couch_view_server,couch_view_server_emonk,couch_view_server_erlang,couch_view_server_os,couch_view_updater,couch_work_queue]},
+ {modules, [couch,couch_app,couch_app_server,couch_app_server_emonk,couch_app_server_erlang,couch_app_server_objc,couch_app_server_os,couch_auth_cache,couch_btree,couch_changes,couch_config,couch_config_writer,couch_db,couch_db_update_notifier,couch_db_update_notifier_sup,couch_db_updater,couch_doc,couch_event_sup,couch_external_manager,couch_external_server,couch_file,couch_httpd,couch_httpd_auth,couch_httpd_db,couch_httpd_external,couch_httpd_misc_handlers,couch_httpd_oauth,couch_httpd_rewrite,couch_httpd_show,couch_httpd_stats_handlers,couch_httpd_vhost,couch_httpd_view,couch_key_tree,couch_log,couch_native_process,couch_os_process,couch_query_servers,couch_ref_counter,couch_rep,couch_rep_att,couch_rep_changes_feed,couch_rep_db_listener,couch_rep_httpc,couch_rep_missing_revs,couch_rep_reader,couch_rep_sup,couch_rep_writer,couch_server,couch_server_sup,couch_stats_aggregator,couch_stats_collector,couch_stream,couch_task_status,couch_util,couch_uuids,couch_view,couch_view_compactor,couch_view_group,couch_view_server,couch_view_server_emonk,couch_view_server_erlang,couch_view_server_objc,couch_view_server_os,couch_view_updater,couch_work_queue]},
{registered, [
couch_config,
couch_db_update,
Please sign in to comment.
Something went wrong with that request. Please try again.