All Downloads are FREE. Search and download functionalities are using the official Maven repository.

test.java.com.cloudant.tests.util.Utils Maven / Gradle / Ivy

There is a newer version: 2.20.1
Show newest version
/*
 * Copyright (c) 2015 IBM Corp. All rights reserved.
 *
 * 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.cloudant.tests.util;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

import com.cloudant.client.api.CloudantClient;
import com.cloudant.client.api.Database;
import com.cloudant.client.api.DesignDocumentManager;
import com.cloudant.client.api.model.DesignDocument;
import com.cloudant.client.api.model.ReplicatorDocument;
import com.cloudant.client.api.model.Response;
import com.cloudant.client.internal.URIBase;
import com.cloudant.client.org.lightcouch.NoDocumentException;
import com.cloudant.http.Http;
import com.cloudant.http.HttpConnection;
import com.cloudant.http.HttpConnectionInterceptorContext;
import com.cloudant.http.HttpConnectionResponseInterceptor;

import java.io.File;
import java.io.FileNotFoundException;
import java.net.URI;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicReference;

public class Utils {

    //wait up to 2 minutes for replications to complete
    private static final long TIMEOUT_MILLISECONDS = TimeUnit.MINUTES.toMillis(2);
    //Design documents directory
    private static final File DESIGN_DOC_DIR
            = new File(System.getProperty("user.dir") + "/src/test/resources/design-files");

    public static void removeReplicatorTestDoc(CloudantClient account, String replicatorDocId)
            throws Exception {

        //Grab replicator doc revision using HTTP HEAD command
        String replicatorDb = "_replicator";
        URI uri = new URIBase(account.getBaseUri()).path(replicatorDb).path(replicatorDocId)
                .build();
        HttpConnection head = Http.HEAD(uri);

        //add a response interceptor to allow us to retrieve the ETag revision header
        final AtomicReference revisionRef = new AtomicReference();
        head.responseInterceptors.add(new HttpConnectionResponseInterceptor() {

            @Override
            public HttpConnectionInterceptorContext interceptResponse
                    (HttpConnectionInterceptorContext context) {
                revisionRef.set(context.connection.getConnection().getHeaderField("ETag"));
                return context;
            }
        });

        account.executeRequest(head);
        String revision = revisionRef.get();
        assertNotNull("The revision should not be null", revision);
        Database replicator = account.database(replicatorDb, false);
        Response removeResponse = replicator.remove(replicatorDocId,
                revision.replaceAll("\"", ""));

        assertThat(removeResponse.getError(), is(nullValue()));
    }

    public static ReplicatorDocument waitForReplicatorToStart(CloudantClient account,
                                                              String replicatorDocId)
            throws Exception {
        return waitForReplicatorToReachStatus(account, replicatorDocId, "triggered");
    }

    public static ReplicatorDocument waitForReplicatorToComplete(CloudantClient account,
                                                                 String replicatorDocId)
            throws Exception {
        return waitForReplicatorToReachStatus(account, replicatorDocId, "completed");
    }

    public static ReplicatorDocument waitForReplicatorToReachStatus(CloudantClient account,
                                                                    String replicatorDocId,
                                                                    String status)
            throws Exception {
        ReplicatorDocument replicatorDoc = null;

        boolean finished = false;

        long startTime = System.currentTimeMillis();
        long timeout = startTime + TIMEOUT_MILLISECONDS;
        //initial wait of 100 ms
        long delay = 100;

        while (!finished && System.currentTimeMillis() < timeout) {
            //Sleep before finding replication document
            Thread.sleep(delay);

            replicatorDoc = account.replicator()
                    .replicatorDocId(replicatorDocId)
                    .find();

            //Check if replicator doc is in specified state
            String state;
            if (replicatorDoc != null && (state = replicatorDoc.getReplicationState()) != null) {
                //if we've reached the status or we reached an error then we are finished
                if (state.equalsIgnoreCase(status) || state.equalsIgnoreCase("error")) {
                    finished = true;
                }
            }
            //double the delay for the next iteration
            delay *= 2;
        }
        if (!finished) {
            throw new TimeoutException("Timed out waiting for replication to complete");
        }
        return replicatorDoc;
    }

    public static String generateUUID() {
        return UUID.randomUUID().toString().replace("-", "");
    }

    /**
     * 

* When testing against a cluster requests can be routed to different nodes. This means after * a save a document may not appear for all subsequent requests until an internal replication * has finished between all the nodes. This method tries to find a document up to maxRetries * times, with retries separated by 0.5 s. Retrying may route the request to a node that * already has the document and the delay between retries also gives an opportunity for * internal replication to complete between nodes increasing the chance of retrieving the * document. *

*

* It should be noted that trying to read back a document immediately after writing to a cluster * is not a best practice, but is needed in some test cases to reproduce, for example, * conflict conditions. It is also worth noting that a document being returned from this * method is not a guarantee that it has reached all nodes, only that it has reached a node * that received one of the requests. *

* * @param db * @param docId */ public static T findDocumentWithRetries(Database db, String docId, Class clazz, int maxRetries) throws Exception { for (int i = 1; i <= maxRetries; i++) { try { return db.find(clazz, docId); } catch (NoDocumentException e) { if (i == maxRetries) { throw e; } else { //sleep for 0.5 s before trying again Thread.sleep(500); } } } throw new Exception("Retries exceeded"); } /** * Test utility that splits a string and asserts that the expected number of separators were * found. Expected number is for separators, but the assertion is done on parts, so this * method is not safe for strings that end in their separator sequence. * * @param toSplit the string to split * @param splitOn the separator string * @param expectedNumber the expected number of separators * @return */ public static String[] splitAndAssert(String toSplit, String splitOn, int expectedNumber) { String[] parts = toSplit.split(splitOn); assertEquals("There should be " + expectedNumber + " instances of " + splitOn + " in the " + "content", expectedNumber + 1, parts.length); return parts; } /** * Test utility to put design documents under the testing resource folder in to the database. * @param db database to put the design docs * @param directory location of design docs */ public static void putDesignDocs(Database db, File directory) throws FileNotFoundException { //Get design documents from directory List designDocuments = DesignDocumentManager.fromDirectory(directory); DesignDocumentManager designDocumentManager = db.getDesignDocumentManager(); DesignDocument[] designDocArray = designDocuments .toArray(new DesignDocument[designDocuments.size()]); //Put documents into database designDocumentManager.put(designDocArray); } public static void putDesignDocs(Database db) throws FileNotFoundException { putDesignDocs(db, DESIGN_DOC_DIR); } public static void assertOKResponse(Response r) throws Exception { assertTrue("The response code should be 2XX was " + r.getStatusCode(), r.getStatusCode() / 100 == 2); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy