package com.couchbase.client.core.cluster;
import static org.junit.Assert.*;
import com.couchbase.client.core.message.ResponseStatus;
import com.couchbase.client.core.message.kv.UpsertRequest;
import com.couchbase.client.core.message.kv.UpsertResponse;
import com.couchbase.client.core.message.kv.subdoc.multi.*;
import com.couchbase.client.core.message.kv.subdoc.simple.SimpleSubdocResponse;
import com.couchbase.client.core.message.kv.subdoc.simple.SubDeleteRequest;
import com.couchbase.client.core.message.kv.subdoc.simple.SubDictAddRequest;
import com.couchbase.client.core.message.kv.subdoc.simple.SubGetRequest;
import com.couchbase.client.core.util.ClusterDependentTest;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.util.CharsetUtil;
import io.netty.util.ReferenceCountUtil;
import io.netty.util.ResourceLeakDetector;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
/**
* Extended attributes test
* Works on couchbase server versions 5.0 and above
*
* @author Subhashni Balakrishnan
* @since 1.4.2
*/
public class SubdocumentExtendedAttributeAccessTest extends ClusterDependentTest {
static {
ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.PARANOID);
}
private static final String testXAttrKey = "testXAttrKey";
private static final String jsonContent = "{\"value\":\"stringValue\", \"sub\": {\"value\": \"subStringValue\",\"array\": [\"array1\", 2, true]}}";
@BeforeClass
public static void checkExtendedAttributeAvailable() throws Exception {
connect(false);
assumeMinimumVersionCompatible(5, 0);
}
@Before
public void prepareData() {
UpsertRequest upsert = new UpsertRequest(testXAttrKey, Unpooled.copiedBuffer(jsonContent, CharsetUtil.UTF_8), bucket(), true);
UpsertResponse response = cluster().<UpsertResponse>send(upsert).toBlocking().single();
assertTrue("Couldn't insert " + testXAttrKey, response.status().isSuccess());
response.release();
}
@Test
public void shouldBeAbleToAccessXAttrs() {
String subPath = "spring.class";
ByteBuf fragment = Unpooled.copiedBuffer("\"SomeClass\"", CharsetUtil.UTF_8);
//insert
SubDictAddRequest insertRequest = new SubDictAddRequest(testXAttrKey, subPath, fragment, bucket());
insertRequest.xattr(true);
insertRequest.createIntermediaryPath(true);
SimpleSubdocResponse insertResponse = cluster().<SimpleSubdocResponse>send(insertRequest).toBlocking().single();
assertTrue(insertResponse.status().isSuccess());
assertEquals(0, insertResponse.content().readableBytes());
insertResponse.content().release();
//get
SubGetRequest getRequest = new SubGetRequest(testXAttrKey, "spring.class", bucket());
getRequest.xattr(true);
SimpleSubdocResponse lookupResponse = cluster().<SimpleSubdocResponse>send(getRequest).toBlocking().single();
assertTrue(lookupResponse.status().isSuccess());
assertEquals(lookupResponse.content().toString(CharsetUtil.UTF_8) , "\"SomeClass\"");
lookupResponse.content().release();
//delete
SubDeleteRequest deleteRequest = new SubDeleteRequest(testXAttrKey, subPath, bucket());
deleteRequest.xattr(true);
SimpleSubdocResponse deleteResponse = cluster().<SimpleSubdocResponse>send(deleteRequest).toBlocking().single();
assertTrue(deleteResponse.status().isSuccess());
assertEquals(0, deleteResponse.content().readableBytes());
deleteResponse.content().release();
getRequest = new SubGetRequest(testXAttrKey, "spring.class", bucket());
getRequest.xattr(true);
lookupResponse = cluster().<SimpleSubdocResponse>send(getRequest).toBlocking().single();
assertTrue(lookupResponse.status() == ResponseStatus.SUBDOC_PATH_NOT_FOUND);
lookupResponse.content().release();
}
@Test
public void shouldBeAbleToAccessMultipleXAttrsInSameNameSpace() {
ByteBuf classFragment = Unpooled.copiedBuffer("\"SomeClass\"", CharsetUtil.UTF_8);
ByteBuf refFragment = Unpooled.copiedBuffer("\"ids\"", CharsetUtil.UTF_8);
SubMultiMutationRequest mutationRequest = new SubMultiMutationRequest(testXAttrKey, bucket(),
new MutationCommandBuilder(Mutation.DICT_UPSERT, "spring.class")
.fragment(classFragment).createIntermediaryPath(true).xattr(true).build(),
new MutationCommandBuilder(Mutation.DICT_UPSERT, "spring.refs")
.fragment(refFragment).createIntermediaryPath(true).xattr(true).build());
MultiMutationResponse mutationResponse = cluster().<MultiMutationResponse>send(mutationRequest).toBlocking().single();
assertTrue(mutationResponse.status().isSuccess());
mutationResponse.responses().get(0).value().release();
mutationResponse.responses().get(1).value().release();
SubMultiLookupRequest lookupRequest = new SubMultiLookupRequest(testXAttrKey, bucket(),
new LookupCommandBuilder(Lookup.GET, "spring.class")
.xattr(true).build(),
new LookupCommandBuilder(Lookup.GET, "spring.refs")
.xattr(true).build());
MultiLookupResponse lookupResponse = cluster().<MultiLookupResponse>send(lookupRequest).toBlocking().single();
assertTrue(lookupResponse.status().isSuccess());
lookupResponse.responses().get(0).value().release();
lookupResponse.responses().get(1).value().release();
mutationRequest = new SubMultiMutationRequest(testXAttrKey, bucket(),
new MutationCommandBuilder(Mutation.DELETE, "spring.class").xattr(true).build(),
new MutationCommandBuilder(Mutation.DELETE, "spring.refs").xattr(true).build());
mutationResponse = cluster().<MultiMutationResponse>send(mutationRequest).toBlocking().single();
assertTrue(mutationResponse.status().isSuccess());
mutationResponse.responses().get(0).value().release();
mutationResponse.responses().get(1).value().release();
}
}