/** * Copyright 2012 Couchbase, Inc. * * 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. */ package org.couchbase.mock.views; import net.spy.memcached.internal.OperationFuture; import org.couchbase.mock.Bucket; import org.couchbase.mock.client.ClientBaseTest; import org.couchbase.mock.memcached.Item; import org.couchbase.mock.memcached.Storage; import java.io.IOException; import java.rmi.ConnectIOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * * @author Sergey Avseyev */ public class ViewTest extends ClientBaseTest { public void testParser() throws Exception { String body = "{" + " \"_id\": \"_design/blog\"," + " \"language\": \"javascript\"," + " \"views\": {" + " \"recent_posts\": {" + " \"map\": \"function(doc){ if(doc.date && doc.title){emit(doc.date, doc.title);} }\"" + " }" + " }" + "}"; DesignDocument ddoc = DesignDocument.create(body, "blog"); assertEquals("_design/blog", ddoc.getId()); assertEquals(body, ddoc.getBody()); ArrayList<View> views = ddoc.getViews(); assertNotNull(views); assertEquals(1, views.size()); View recentPosts = views.get(0); assertEquals("recent_posts", recentPosts.getName()); assertEquals("function(doc){ if(doc.date && doc.title){emit(doc.date, doc.title);} }", recentPosts.getMapSource()); assertEquals(null, recentPosts.getReduceSource()); } private Iterable<Item> seedDocuments(int num) throws IOException { ArrayList<OperationFuture> ops = new ArrayList<OperationFuture>(); for (int i = 0; i < num; i++) { String key = String.format("key-%03d", i); String val = String.format("{\"val\":%d}", i); ops.add(client.set(key, val)); } for (OperationFuture op : ops) { try { op.get(); } catch (Exception e) { throw new RuntimeException(e); } if (!op.getStatus().isSuccess()) { throw new RuntimeException("Operation failed to execute!"); } String ss = (String) client.get(op.getKey()); assertNotNull(ss); assertNotSame("", ss); } // Now, get the vBucket store.. :( Bucket bucket = couchbaseMock.getBuckets().get("default"); return bucket.getMasterItems(Storage.StorageType.CACHE); } public void testMapperTrivial() throws Exception { Iterable<Item> store = seedDocuments(40); View view = new View("all", "function(doc,meta){emit(meta.id, null)}", null); QueryResult results = view.execute(store); /* execute with default config */ assertEquals(40, results.getTotalRowCount()); assertEquals(40, results.getFilteredRowCount()); assertEquals("key-000", results.keyAt(0)); assertEquals(null, results.valueAt(0)); } public void testSkipLimit() throws Exception { Iterable<Item> store = seedDocuments(40); View view = new View("all", "function(doc,meta){emit(meta.id, null)}", null); Configuration config = new Configuration(); config.setSkip(10); config.setLimit(5); QueryResult results = view.execute(store, config); assertEquals(40, results.getTotalRowCount()); assertEquals(5, results.getFilteredRowCount()); Map firstRow = (Map) results.rowAt(0); assertEquals("key-010", (String) firstRow.get("key")); } public void testRanging() throws Exception { Iterable<Item> store = seedDocuments(40); View view = new View("all", "function(doc){ emit( doc.val ); emit( doc.val+1 ); }", null); Configuration config = new Configuration(); config.setStartKey(1); config.setEndKey(3); config.setInclusiveEnd(true); /* filter results: 1, 1, 2, 2, 3, 3 */ QueryResult results = view.execute(store, config); assertEquals(80, results.getTotalRowCount()); assertEquals(6, results.getFilteredRowCount()); assertEquals(1, results.numKeyAt(0)); assertEquals("key-000", results.idAt(0)); /* filter results: 3, 3, 2, 2, 1, 1 */ config.setDescending(true); config.setStartKey(3); config.setEndKey(1); results = view.execute(store, config); assertEquals(80, results.getTotalRowCount()); assertEquals(6, results.getFilteredRowCount()); assertEquals(3, results.numKeyAt(0)); assertEquals("key-003", results.idAt(0)); } public void testRangingExclusiveEnd() throws Exception { Iterable<Item> store = seedDocuments(40); View view = new View("all", "function(doc){emit(doc.val); emit(doc.val+1);}", null); Configuration config = new Configuration(); config.setStartKey(1); config.setEndKey(3); config.setInclusiveEnd(false); QueryResult res = view.execute(store, config); assertEquals(80, res.getTotalRowCount()); assertEquals(4, res.getFilteredRowCount()); } public void testMapperDescending() throws Exception { Iterable<Item> store = seedDocuments(9); View view = new View("all", "function(doc,meta){emit(meta.id, null)}", null); Configuration config = new Configuration(); config.setDescending(true); QueryResult res = view.execute(store, config); assertEquals(9, res.getFilteredRowCount()); assertEquals("key-008", res.keyAt(0)); } public void testMapperEmittingCustomKey() throws Exception { Iterable<Item> store = seedDocuments(9); View view = new View("all", "function(doc,meta){emit(meta.id.toUpperCase(), (doc.val + 1).toString())}", null); QueryResult results = view.execute(store); assertEquals(9, results.getFilteredRowCount()); assertEquals("KEY-000", results.keyAt(0)); assertEquals("key-000", results.idAt(0)); assertEquals("1", results.valueAt(0)); assertEquals(null, results.rowAt(0).get("doc")); } public void testReduceCount() throws Exception { Iterable<Item> store = seedDocuments(9); View view = new View("all", "function(doc,meta){emit(meta.id)}", "function(keys, values, rereduce){ return values.length; }"); Configuration config = new Configuration(); config.setReduce(true); QueryResult results = view.execute(store, config); assertEquals(1, results.getFilteredRowCount()); assertEquals(null, results.keyAt(0)); assertEquals(9, results.numValAt(0)); } public void testReduceCountBuiltin() throws Exception { Iterable<Item> store = seedDocuments(9); View view = new View("all", "function(doc,meta){emit(meta.id)}", "_count"); QueryResult results = view.execute(store); assertEquals(1, results.getFilteredRowCount()); assertEquals(null, results.keyAt(0)); assertEquals(9, results.numValAt(0)); } public void testReduceSum() throws Exception { Iterable<Item> store = seedDocuments(9); View view = new View("all", "function(doc,meta){emit(meta.id, doc.val)}", "function(keys, values, rereduce){ return sum(values); }"); QueryResult results = view.execute(store); assertEquals(1, results.getFilteredRowCount()); assertEquals(null, results.keyAt(0)); assertEquals(36, results.numValAt(0)); } public void testReduceSumBuiltin() throws Exception { Iterable<Item> store = seedDocuments(9); View view = new View("all", "function(doc,meta){emit(meta.id, doc.val)}", "_sum"); QueryResult results = view.execute(store); assertEquals(1, results.getFilteredRowCount()); assertEquals(null, results.keyAt(0)); assertEquals(36, results.numValAt(0)); } // public void testReduceStatsBuiltin() throws Exception { // Iterable<Item> store = seedDocuments(9); // View view = new View("all", "function(doc){emit(meta.id, doc.val)}", "_stats"); // HashMap results = view.execute(store); // // ArrayList rows = (ArrayList) results.get("rows"); // assertEquals(1, rows.size()); // // HashMap firstRow = (HashMap) rows.get(0); // assertEquals("null", firstRow.get("key").toString()); // HashMap stats = (HashMap) firstRow.get("value"); // assertEquals(36, ( (Number) stats.get("sum") ).intValue()); // assertEquals(204, ( (Number) stats.get("sumsqr") ).intValue()); // assertEquals(9, ( (Number) stats.get("count") ).intValue()); // assertEquals(0, ( (Number) stats.get("min") ).intValue()); // assertEquals(8, ( (Number) stats.get("max") ).intValue()); // } // @SuppressWarnings("unchecked") public void testReduceGroupCount() throws Exception { Iterable<Item> store = seedDocuments(9); View view = new View("all", "function(doc,meta){if (doc.val % 2 == 0) { emit([\"odd\", meta.id])} else { emit([\"even\", meta.id]) } }", "function(keys, values, rereduce){ return values.length; }"); QueryResult results = view.execute(store); assertEquals(1, results.getFilteredRowCount()); assertEquals(null, results.keyAt(0)); assertEquals(9, results.numValAt(0)); Configuration config = new Configuration(); config.setGroup(true); //K=[e1,..en] results = view.execute(store, config); assertEquals(9, results.getFilteredRowCount()); // Analyze row List<Object> ll = (List<Object>)results.keyAt(0); assertEquals(2, ll.size()); assertEquals("even", ll.get(0)); assertEquals("key-001", ll.get(1)); assertEquals(1, results.numValAt(0)); config = new Configuration(); config.setGroupLevel(1); //K=[e1] results = view.execute(store, config); assertEquals(2, results.getFilteredRowCount()); ll = (List<Object>) results.keyAt(0); assertEquals(1, ll.size()); assertEquals("even", ll.get(0)); assertEquals(4, results.numValAt(0)); config = new Configuration(); config.setGroupLevel(0); //K=null results = view.execute(store, config); assertEquals(1, results.getFilteredRowCount()); assertEquals(null, results.keyAt(0)); assertEquals(9, results.numValAt(0)); config = new Configuration(); config.setGroupLevel(2); // K=[e1, e2] results = view.execute(store, config); assertEquals(9, results.getFilteredRowCount()); ll = (List<Object>) results.keyAt(0); assertEquals(2, ll.size()); assertEquals("even", ll.get(0)); assertEquals("key-001", ll.get(1)); assertEquals(1, results.numValAt(0)); } public void testItAllowsToTurnOffReduce() throws Exception { Iterable<Item> store = seedDocuments(40); View view = new View("all", "function(doc,meta){emit(meta.id, null)}", "_count"); Configuration config = new Configuration(); config.setReduce(false); QueryResult results = view.execute(store, config); assertEquals(40, results.getTotalRowCount()); assertEquals(40, results.getFilteredRowCount()); assertEquals("key-000", results.keyAt(0)); } @SuppressWarnings("unchecked") public void testFilters() throws Exception { Iterable<Item> store = seedDocuments(40); View view = new View("all", "function(doc,meta){ emit([\"id\", meta.id], null); }"); Configuration config = new Configuration(); config.setEncodedKey("[ \"id\" , \"key-001\" ]"); QueryResult results = view.execute(store, config); assertEquals(40, results.getTotalRowCount()); assertEquals(1, results.getFilteredRowCount()); List<Object> ll = (List<Object>)results.keyAt(0); assertEquals(2, ll.size()); assertEquals("id", ll.get(0)); assertEquals("key-001", ll.get(1)); config = new Configuration(); List<String> keys = new ArrayList<String>(); keys.add("[\"id\", \"key-006\"]"); keys.add("[\"id\", \"key-008\"]"); config.setEncodedKeys(keys); results = view.execute(store, config); assertEquals(40, results.getTotalRowCount()); assertEquals(2, results.getFilteredRowCount()); ll = (List<Object>) results.keyAt(0); assertEquals(2, ll.size()); assertEquals("id", ll.get(0)); assertEquals("key-006", ll.get(1)); } }