/*
* Copyright (c) 2016 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 com.couchbase.client.java.datastructures.collections;
import com.couchbase.client.java.Bucket;
import com.couchbase.client.java.Cluster;
import com.couchbase.client.java.CouchbaseCluster;
import com.couchbase.client.java.document.JsonArrayDocument;
import com.couchbase.client.java.document.JsonDocument;
import com.couchbase.client.java.document.json.JsonArray;
import com.couchbase.client.java.document.json.JsonObject;
import com.couchbase.client.java.error.DocumentDoesNotExistException;
import com.couchbase.client.java.error.TranscodingException;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.UUID;
import static org.junit.Assert.*;
public class CouchbaseArrayListTest {
private static Cluster cluster;
private static Bucket bucket;
@BeforeClass
public static void setup() {
cluster = CouchbaseCluster.create();
bucket = cluster.openBucket();
}
@AfterClass
public static void teardown() {
cluster.disconnect();
}
private String uuid;
@Before
public void generateId() {
uuid = uuid();
}
@After
public void deleteDoc() {
try {
bucket.remove(uuid);
} catch (DocumentDoesNotExistException e) {
//ignore
}
}
private static String uuid() {
return UUID.randomUUID().toString();
}
@Test
public void size() throws Exception {
List<Object> list = new CouchbaseArrayList(uuid, bucket);
assertEquals(0, list.size());
}
@Test
public void isEmpty() throws Exception {
List<Object> list = new CouchbaseArrayList(uuid, bucket);
assertTrue(list.isEmpty());
}
@Test
public void shouldAdd() throws Exception {
List<Object> list = new CouchbaseArrayList(uuid, bucket, Collections.<Object>emptyList());
assertFalse(list.contains("foobar"));
list.add("foobar");
assertTrue(list.contains("foobar"));
assertEquals(1, list.size());
assertFalse(list.isEmpty());
}
@Test
public void shouldRemoveByValue() throws Exception {
List<Object> list = new CouchbaseArrayList(uuid, bucket, "foo", "bar");
assertTrue(list.contains("foo"));
assertTrue(list.contains("bar"));
assertEquals(2, list.size());
assertFalse(list.isEmpty());
assertFalse(list.contains("blarb"));
assertFalse(list.remove("blarb"));
assertEquals(2, list.size());
assertFalse(list.isEmpty());
assertTrue(list.remove("foo"));
assertFalse(list.contains("foo"));
assertEquals(1, list.size());
assertFalse(list.isEmpty());
assertTrue(list.remove("bar"));
assertFalse(list.contains("bar"));
assertEquals(0, list.size());
assertTrue(list.isEmpty());
}
@Test
public void shouldRemoveByIndex() {
List<Object> list = new CouchbaseArrayList(uuid, bucket, "foo", "bar", "baz", true);
assertEquals(4, list.size());
list.remove(1);
assertEquals(3, list.size());
assertEquals("baz", list.get(1));
}
@Test(expected = IndexOutOfBoundsException.class)
public void shouldThrowOnOutOfBoundsRemove() {
List<Object> list = new CouchbaseArrayList(uuid, bucket, "foo", "bar");
list.remove(14334324);
}
@Test
public void shouldReturnIterator() {
List<Object> list = new CouchbaseArrayList(uuid, bucket, "foo", "bar");
Iterator<Object> iter = list.iterator();
int i = 0;
while(iter.hasNext()) {
Object obj = iter.next();
assertTrue(obj instanceof String);
switch(i) {
case 0:
assertEquals("foo", obj);
break;
case 1:
assertEquals("bar", obj);
break;
}
i++;
}
assertEquals(2, i);
}
@Test
public void shouldClear() {
List<Object> list = new CouchbaseArrayList(uuid, bucket, "foo", "bar");
assertEquals(2, list.size());
list.clear();
assertTrue(list.isEmpty());
assertEquals(0, list.size());
}
//since clear is optimized, also test the iterator removal of the whole list
@Test
public void shouldClearViaIterator() {
List<Object> list = new CouchbaseArrayList(uuid, bucket, "foo", "bar");
assertEquals(2, list.size());
Iterator<Object> iterator = list.iterator();
while (iterator.hasNext()) {
Object next = iterator.next();
assertNotNull(next);
iterator.remove();
}
assertTrue(list.isEmpty());
assertEquals(0, list.size());
}
@Test
public void shouldIteratorRemoveInReverseOrder() {
List<String> list = new CouchbaseArrayList<String>(uuid, bucket, "keep", "foo", "bar", "baz", "foobar");
assertEquals(5, list.size());
ListIterator<String> iterator = list.listIterator();
while (iterator.hasNext()) iterator.next();
//at "foobar"
iterator.remove(); //-foobar
assertEquals("baz", iterator.previous()); //at "baz"
assertEquals("bar", iterator.previous()); //at "bar"
iterator.remove(); //-bar
assertEquals("foo", iterator.previous()); //at "foo"
iterator.remove(); //-foo
assertEquals("baz", iterator.next()); //at "baz"
iterator.remove(); //-baz
assertEquals(1, list.size());
assertEquals("keep", list.get(0));
}
@Test
public void shouldGet() {
List<Object> list = new CouchbaseArrayList(uuid, bucket);
list.add("foo");
list.add("bar");
assertEquals("foo", list.get(0));
assertEquals("bar", list.get(1));
}
@Test(expected = IndexOutOfBoundsException.class)
public void shouldFailOnOutOfBoundsGet() {
List<Object> list = new CouchbaseArrayList(uuid, bucket);
list.get(4234324);
}
@Test
public void testConstructorWithPreExistingDocument() {
JsonArrayDocument preExisting = JsonArrayDocument.create(uuid, JsonArray.from("test"));
bucket.upsert(preExisting);
List<String> list = new CouchbaseArrayList(uuid, bucket);
assertEquals(1, list.size());
assertEquals("test", list.get(0));
}
@Test
public void testConstructorWithPreExistingDocumentOfWrongTypeFails() {
JsonDocument preExisting = JsonDocument.create(uuid, JsonObject.create().put("test", "value"));
bucket.upsert(preExisting);
List<String> list = new CouchbaseArrayList(uuid, bucket);
try {
list.size();
fail("Expected TranscodingException");
} catch (TranscodingException e) {
//expected
}
}
@Test
public void testConstructorWithVarargDataOverwrites() {
JsonDocument preExisting = JsonDocument.create(uuid, JsonObject.create().put("test", "value"));
bucket.upsert(preExisting);
List<String> list = new CouchbaseArrayList(uuid, bucket, "foo");
assertEquals(1, list.size());
assertEquals("foo", list.get(0));
}
@Test
public void testConstructorWithCollectionDataOverwrites() {
JsonDocument preExisting = JsonDocument.create(uuid, JsonObject.create().put("test", "value"));
bucket.upsert(preExisting);
List<String> list = new CouchbaseArrayList(uuid, bucket, Collections.singletonList("foo"));
assertEquals(1, list.size());
assertEquals("foo", list.get(0));
}
@Test
public void testConstructorWithEmptyCollectionOverwrites() {
JsonDocument preExisting = JsonDocument.create(uuid, JsonObject.create().put("test", "value"));
bucket.upsert(preExisting);
List<String> list = new CouchbaseArrayList(uuid, bucket, Collections.emptyList());
assertEquals(0, list.size());
}
@Test
public void shouldAcceptAllJsonValueCompatibleTypes() {
List<Object> list = new CouchbaseArrayList<Object>(uuid, bucket);
JsonObject sub1 = JsonObject.create().put("foo", "bar").put("value", 4);
JsonArray sub2 = JsonArray.from("A", "B", 5);
list.add("someString");
list.add(123);
list.add(4.56);
list.add(null);
list.add(true);
list.add(sub1);
list.add(sub2);
assertEquals(7, list.size());
assertTrue(list.contains(sub1));
assertTrue(list.contains(sub2));
assertTrue(list.contains(null));
}
}