Example usage for java.lang AssertionError getMessage

List of usage examples for java.lang AssertionError getMessage

Introduction

In this page you can find the example usage for java.lang AssertionError getMessage.

Prototype

public String getMessage() 

Source Link

Document

Returns the detail message string of this throwable.

Usage

From source file:org.apache.solr.cloud.TestRandomFlRTGCloud.java

/**
 * Does one or more RTG request for the specified docIds with a randomized fl & fq params, asserting
 * that the returned document (if any) makes sense given the expected SolrInputDocuments
 *//* ww w.j  ava2  s. c om*/
private void assertRTG(final SolrInputDocument[] knownDocs, final int[] docIds)
        throws IOException, SolrServerException {
    final SolrClient client = getRandClient(random());
    // NOTE: not using SolrClient.getById or getByIds because we want to force choice of "id" vs "ids" params
    final ModifiableSolrParams params = params("qt", "/get");

    // random fq -- nothing fancy, secondary concern for our test
    final Integer FQ_MAX = usually() ? null : random().nextInt();
    if (null != FQ_MAX) {
        params.add("fq", "aaa_i:[* TO " + FQ_MAX + "]");
    }

    final Set<FlValidator> validators = new LinkedHashSet<>();
    validators.add(ID_VALIDATOR); // always include id so we can be confident which doc we're looking at
    addRandomFlValidators(random(), validators);
    FlValidator.addParams(validators, params);

    final List<String> idsToRequest = new ArrayList<>(docIds.length);
    final List<SolrInputDocument> docsToExpect = new ArrayList<>(docIds.length);
    for (int docId : docIds) {
        // every docId will be included in the request
        idsToRequest.add("" + docId);

        // only docs that should actually exist and match our (optional) filter will be expected in response
        if (null != knownDocs[docId]) {
            Integer filterVal = (Integer) knownDocs[docId].getFieldValue("aaa_i");
            if (null == FQ_MAX || ((null != filterVal) && filterVal.intValue() <= FQ_MAX.intValue())) {
                docsToExpect.add(knownDocs[docId]);
            }
        }
    }

    // even w/only 1 docId requested, the response format can vary depending on how we request it
    final boolean askForList = random().nextBoolean() || (1 != idsToRequest.size());
    if (askForList) {
        if (1 == idsToRequest.size()) {
            // have to be careful not to try to use "multi" 'id' params with only 1 docId
            // with a single docId, the only way to ask for a list is with the "ids" param
            params.add("ids", idsToRequest.get(0));
        } else {
            if (random().nextBoolean()) {
                // each id in it's own param
                for (String id : idsToRequest) {
                    params.add("id", id);
                }
            } else {
                // add one or more comma seperated ids params
                params.add(buildCommaSepParams(random(), "ids", idsToRequest));
            }
        }
    } else {
        assert 1 == idsToRequest.size();
        params.add("id", idsToRequest.get(0));
    }

    final QueryResponse rsp = client.query(params);
    assertNotNull(params.toString(), rsp);

    final SolrDocumentList docs = getDocsFromRTGResponse(askForList, rsp);
    assertNotNull(params + " => " + rsp, docs);

    assertEquals("num docs mismatch: " + params + " => " + docsToExpect + " vs " + docs, docsToExpect.size(),
            docs.size());

    // NOTE: RTG makes no garuntees about the order docs will be returned in when multi requested
    for (SolrDocument actual : docs) {
        try {
            int actualId = assertParseInt("id", actual.getFirstValue("id"));
            final SolrInputDocument expected = knownDocs[actualId];
            assertNotNull("expected null doc but RTG returned: " + actual, expected);

            Set<String> expectedFieldNames = new TreeSet<>();
            for (FlValidator v : validators) {
                expectedFieldNames.addAll(v.assertRTGResults(validators, expected, actual));
            }
            // ensure only expected field names are in the actual document
            Set<String> actualFieldNames = new TreeSet<>(actual.getFieldNames());
            assertEquals("Actual field names returned differs from expected", expectedFieldNames,
                    actualFieldNames);
        } catch (AssertionError ae) {
            throw new AssertionError(params + " => " + actual + ": " + ae.getMessage(), ae);
        }
    }
}

From source file:com.joyent.manta.client.crypto.MantaEncryptedObjectInputStreamTest.java

private void canReadByteRange(SupportedCipherDetails cipherDetails, ReadBytes readBytes, int startPosInclusive,
        int endPosInclusive) throws IOException {
    final byte[] content;
    try (InputStream in = testURL.openStream(); ByteArrayOutputStream out = new ByteArrayOutputStream()) {
        IOUtils.copy(in, out);/* w  ww  .  j a v a2s .  c o m*/
        content = out.toByteArray();
    }

    /* If the plaintext size specified is greater than the actual plaintext
     * size, we adjust it here. This is only for creating the expectation
     * that we compare our output to. */
    final int endPositionExclusive;

    if (endPosInclusive + 1 > plaintextSize) {
        endPositionExclusive = plaintextSize;
    } else {
        endPositionExclusive = endPosInclusive + 1;
    }

    boolean unboundedEnd = (endPositionExclusive >= plaintextSize || endPosInclusive < 0);
    byte[] expected = Arrays.copyOfRange(content, startPosInclusive, endPositionExclusive);

    SecretKey key = SecretKeyUtils.generate(cipherDetails);
    EncryptedFile encryptedFile = encryptedFile(key, cipherDetails, this.plaintextSize);
    long ciphertextSize = encryptedFile.file.length();

    /* Here we translate the plaintext ranges to ciphertext ranges. Notice
     * that we take the input of endPos because it may overrun past the
     * size of the plaintext. */
    ByteRangeConversion ranges = cipherDetails.translateByteRange(startPosInclusive, endPosInclusive);
    long ciphertextStart = ranges.getCiphertextStartPositionInclusive();
    long plaintextLength = ((long) (endPosInclusive - startPosInclusive)) + 1L;

    /* Here, we simulate being passed only a subset of the total bytes of
     * a file - just like how the output of a HTTP range request would be
     * passed. */
    try (RandomAccessFile randomAccessFile = new RandomAccessFile(encryptedFile.file, "r")) {
        // We seek to the start of the ciphertext to emulate a HTTP byte range request
        randomAccessFile.seek(ciphertextStart);

        long initialSkipBytes = ranges.getPlaintextBytesToSkipInitially()
                + ranges.getCiphertextStartPositionInclusive();
        long binaryEndPositionInclusive = ranges.getCiphertextEndPositionInclusive();

        long ciphertextRangeMaxBytes = ciphertextSize - ciphertextStart;
        long ciphertextRangeRequestBytes = binaryEndPositionInclusive - ciphertextStart + 1;

        /* We then calculate the range length based on the *actual* ciphertext
         * size so that we are emulating HTTP range requests by returning a
         * the binary of the actual object (even if the range went beyond). */
        long ciphertextByteRangeLength = Math.min(ciphertextRangeMaxBytes, ciphertextRangeRequestBytes);

        if (unboundedEnd)
            ciphertextByteRangeLength = ciphertextSize - ciphertextStart; // include MAC

        byte[] rangedBytes = new byte[(int) ciphertextByteRangeLength];
        randomAccessFile.read(rangedBytes);

        try (ByteArrayInputStream bin = new ByteArrayInputStream(rangedBytes);
                /* When creating the fake stream, we feed it a content-length equal
                 * to the size of the byte range because that is what Manta would
                 * do. Also, we pass along the incorrect plaintext length and
                 * test how the stream handles incorrect values of plaintext length. */
                MantaEncryptedObjectInputStream min = createEncryptedObjectInputStream(key, bin,
                        ciphertextByteRangeLength, cipherDetails, encryptedFile.cipher.getIV(), false,
                        (long) this.plaintextSize, initialSkipBytes, plaintextLength, unboundedEnd)) {
            byte[] actual = new byte[expected.length];
            readBytes.readAll(min, actual);

            try {
                AssertJUnit.assertArrayEquals("Byte range output doesn't match", expected, actual);
            } catch (AssertionError e) {
                Assert.fail(String.format("%s\nexpected: %s\nactual  : %s", e.getMessage(),
                        new String(expected, StandardCharsets.UTF_8),
                        new String(actual, StandardCharsets.UTF_8)));
            }
        }
    }
}

From source file:org.apache.sqoop.manager.sqlserver.SQLServerDatatypeImportSequenceFileManualTest.java

public void dataTypeTest(DATATYPES datatype) {
    int exceptionCount = 0;

    List testdata = tdfs.getTestdata(datatype);

    for (Iterator<MSSQLTestData> itr = testdata.iterator(); itr.hasNext();) {
        MSSQLTestData current = itr.next();
        System.out.println("Testing with : \n" + current);

        try {//  w  w  w . ja  v a  2 s  . c  om
            if (datatype == DATATYPES.DECIMAL || datatype == DATATYPES.NUMERIC) {

                verifyType(
                        current.getDatatype() + "(" + current.getData(KEY_STRINGS.SCALE) + ","
                                + current.getData(KEY_STRINGS.PREC) + ")",
                        current.getData(KEY_STRINGS.TO_INSERT), current.getData(KEY_STRINGS.HDFS_READBACK));

            } else if (datatype == DATATYPES.TIME || datatype == DATATYPES.SMALLDATETIME
                    || datatype == DATATYPES.DATETIME2 || datatype == DATATYPES.DATETIME
                    || datatype == DATATYPES.DATETIMEOFFSET || datatype == DATATYPES.TEXT
                    || datatype == DATATYPES.NTEXT || datatype == DATATYPES.DATE) {
                verifyType(current.getDatatype(), "'" + current.getData(KEY_STRINGS.TO_INSERT) + "'",
                        current.getData(KEY_STRINGS.HDFS_READBACK));
            } else if (datatype == DATATYPES.VARBINARY) {
                verifyType(current.getDatatype() + "(" + current.getData(KEY_STRINGS.SCALE) + ")",
                        "cast('" + current.getData(KEY_STRINGS.TO_INSERT) + "' as varbinary("
                                + current.getData(KEY_STRINGS.SCALE) + "))",
                        current.getData(KEY_STRINGS.HDFS_READBACK));
            } else if (datatype == DATATYPES.BINARY) {
                verifyType(current.getDatatype() + "(" + current.getData(KEY_STRINGS.SCALE) + ")",
                        "cast('" + current.getData(KEY_STRINGS.TO_INSERT) + "' as binary("
                                + current.getData(KEY_STRINGS.SCALE) + "))",
                        current.getData(KEY_STRINGS.HDFS_READBACK));
            } else if (datatype == DATATYPES.NCHAR || datatype == DATATYPES.VARCHAR
                    || datatype == DATATYPES.CHAR || datatype == DATATYPES.NVARCHAR) {
                System.out.println("------>" + current.getData(KEY_STRINGS.DB_READBACK) + "<----");
                verifyType(current.getDatatype() + "(" + current.getData(KEY_STRINGS.SCALE) + ")",
                        "'" + current.getData(KEY_STRINGS.TO_INSERT) + "'",
                        current.getData(KEY_STRINGS.HDFS_READBACK));
            } else if (datatype == DATATYPES.IMAGE) {
                verifyType(current.getDatatype(),
                        "cast('" + current.getData(KEY_STRINGS.TO_INSERT) + "' as image )",
                        current.getData(KEY_STRINGS.HDFS_READBACK));
            } else {
                verifyType(current.getDatatype(), current.getData(KEY_STRINGS.TO_INSERT),
                        current.getData(KEY_STRINGS.HDFS_READBACK));
            }

            addToReport(current, null);

        } catch (AssertionError ae) {
            if (current.getData(KEY_STRINGS.NEG_POS_FLAG).equals("NEG")) {
                System.out.println("failure was expected, PASS");
                addToReport(current, null);
            } else {
                System.out.println("----------------------------------------------------------" + "-");
                System.out.println("Failure for following Test Data :\n" + current.toString());
                System.out.println("----------------------------------------------------------" + "-");
                System.out.println("Exception details : \n");
                System.out.println(ae.getMessage());
                System.out.println("----------------------------------------------------------" + "-");
                addToReport(current, ae);
                exceptionCount++;
            }
        } catch (Exception e) {
            addToReport(current, e);
            exceptionCount++;
        }
    }

    if (exceptionCount > 0) {
        System.out.println("There were failures for :" + datatype.toString());
        System.out.println("Failed for " + exceptionCount + " test data samples\n");
        System.out.println("Sroll up for detailed errors");
        System.out.println("-----------------------------------------------------------");
        throw new AssertionError("Failed for " + exceptionCount + " test data sample");
    }
}

From source file:com.datatorrent.stram.plan.physical.PhysicalPlanTest.java

@Test
public void testParallelPartitioningValidation() {
    LogicalPlan dag = new LogicalPlan();
    dag.setAttribute(OperatorContext.STORAGE_AGENT, new TestPlanContext());

    GenericTestOperator o1 = dag.addOperator("o1", GenericTestOperator.class);

    GenericTestOperator o2 = dag.addOperator("o2", GenericTestOperator.class);

    GenericTestOperator o3 = dag.addOperator("o3", GenericTestOperator.class);
    dag.setInputPortAttribute(o3.inport1, PortContext.PARTITION_PARALLEL, true);
    dag.setInputPortAttribute(o3.inport2, PortContext.PARTITION_PARALLEL, true);

    dag.addStream("o1Output1", o1.outport1, o3.inport1);
    dag.addStream("o2Output1", o2.outport1, o3.inport2);

    try {//  w  ww  .j  av a  2  s  .co  m
        new PhysicalPlan(dag, new TestPlanContext());
    } catch (AssertionError ae) {
        Assert.assertThat("Parallel partition needs common ancestor", ae.getMessage(),
                RegexMatcher.matches("operator cannot extend multiple partitions.*"));
    }

    GenericTestOperator commonAncestor = dag.addOperator("commonAncestor", GenericTestOperator.class);
    dag.setInputPortAttribute(o1.inport1, PortContext.PARTITION_PARALLEL, true);
    dag.setInputPortAttribute(o2.inport1, PortContext.PARTITION_PARALLEL, true);
    dag.addStream("commonAncestor.outport1", commonAncestor.outport1, o1.inport1);
    dag.addStream("commonAncestor.outport2", commonAncestor.outport2, o2.inport1);
    new PhysicalPlan(dag, new TestPlanContext());

    // two operators with multiple streams
    dag = new LogicalPlan();
    dag.setAttribute(OperatorContext.STORAGE_AGENT, new TestPlanContext());
    o1 = dag.addOperator("o1", GenericTestOperator.class);
    o2 = dag.addOperator("o2", GenericTestOperator.class);
    dag.setInputPortAttribute(o2.inport1, PortContext.PARTITION_PARALLEL, true);
    dag.setInputPortAttribute(o2.inport2, PortContext.PARTITION_PARALLEL, true);
    dag.addStream("o1.outport1", o1.outport1, o2.inport1);
    dag.addStream("o2.outport2", o1.outport2, o2.inport2);
    new PhysicalPlan(dag, new TestPlanContext());

}

From source file:iTests.framework.utils.WebuiTestUtils.java

/**
 * temporary workaround because of GS-10075.
 * this bug manifests only on a windows machine for some reason and frequently makes all the test fail on assertCleanSetup.
 *///from   ww w.  j  a  va  2  s.com

public void beforeTest() {
    LogUtils.log("Test Configuration Started: " + this.getClass());
    LogUtils.log("Creating new Admin");
    admin = AdminUtils.createAdmin();
    try {
        LogUtils.log("Waiting for cleanup to finish");
        SetupUtils.assertCleanSetup(admin);
    } catch (AssertionError e) {
        int gridServiceManagersSize = admin.getGridServiceManagers().getSize();
        if (gridServiceManagersSize > 0) { // there is a leaked GSM
            LogUtils.log("Detected a leaked GSM that was not properly killed");
            GridServiceManagers gridServiceManagers = admin.getGridServiceManagers();
            GridServiceManager gridServiceManager = gridServiceManagers.getManagers()[0];
            Machine[] machines = admin.getMachines().getMachines();
            String gsmMachineHostAddress = gridServiceManager.getMachine().getHostAddress();
            long gsmPID = gridServiceManager.getVirtualMachine().getDetails().getPid();
            LogUtils.log("trying to forcefully kill GSM with PID " + gsmPID + " using native OS command");
            try {
                if (gsmMachineHostAddress.equals(InetAddress.getLocalHost().getHostAddress())) {
                    killLocalProcessByPID(gsmPID, 5000);
                } else {
                    for (Machine machine : machines) {
                        if (gsmMachineHostAddress.equals(machine.getHostAddress())) {
                            killRemoteProcessByPID(machine.getHostAddress(), gsmPID, 10 * 1000);
                            LogUtils.log("Succesfully killed process with pid " + gsmMachineHostAddress);
                            break;
                        }
                    }
                }
            } catch (UnknownHostException e1) {
                LogUtils.log("caugh an exception", e1);
            }
        } else { // if no leak was found, propogate the exception out.
            Assert.fail(e.getMessage(), e);
        }
    }
}

From source file:eu.cloud4soa.cli.roo.addon.Cloud4soaOperationsImpl.java

@Override
public void createDeveloperProfileTemplate(final String fileName) {
    String failureMessage = "User developer profile template generation failed";
    executeCommand(new Cloud4soaCommand(failureMessage) {
        @Override/*w ww.j  av a2s . c om*/
        public void execute() throws Exception {
            String developerId = "Developer123456";

            DeveloperDescriptionGenerator developerDescriptionGenerator = new DeveloperDescriptionGenerator();
            try {
                developerDescriptionGenerator.setValue("developerUriId", developerId);

                File file = new File(fileName);

                if (file.exists()) {
                    logger.severe("Description file already exists!");
                    logger.severe("Please delete it or change the file name parameter");
                    this.displaySuccessMessage = false;
                    logger.severe(this.failureMessage);
                    return;
                }

                FileOutputStream fos = new FileOutputStream(file);
                developerDescriptionGenerator.evaluateTemplate(fos);
            } catch (AssertionError exp) {
                logger.severe(exp.getMessage());
            } catch (IllegalArgumentException exp) {
                logger.severe(exp.getMessage());
            }
        }
    });
}

From source file:eu.cloud4soa.cli.roo.addon.Cloud4soaOperationsImpl.java

@Override
public void createPaaSUserProfileTemplate(final String fileName) {
    String failureMessage = "User paas profile template generation failed";
    executeCommand(new Cloud4soaCommand(failureMessage) {
        @Override/*from w ww  .  java  2  s .co  m*/
        public void execute() throws Exception {
            String paasUserId = "PaaSUser123456";
            String paasProviderId = "PaaSProvider123456";
            String homepageId = "Document123456";

            PaaSUserDescriptionGenerator paaSUserDescriptionGenerator = new PaaSUserDescriptionGenerator();
            try {
                paaSUserDescriptionGenerator.setValue("paasUserUriId", paasUserId);
                paaSUserDescriptionGenerator.setValue("paasProviderUriId", paasProviderId);
                paaSUserDescriptionGenerator.setValue("homepageUriId", homepageId);

                File file = new File(fileName);

                if (file.exists()) {
                    logger.severe("Description file already exists!");
                    logger.severe("Please delete it or change the file name parameter");
                    this.displaySuccessMessage = false;
                    logger.severe(this.failureMessage);
                    return;
                }

                FileOutputStream fos = new FileOutputStream(file);
                paaSUserDescriptionGenerator.evaluateTemplate(fos);
            } catch (AssertionError exp) {
                logger.severe(exp.getMessage());
            } catch (IllegalArgumentException exp) {
                logger.severe(exp.getMessage());
            }
        }
    });
}

From source file:eu.cloud4soa.cli.roo.addon.Cloud4soaOperationsImpl.java

@Override
public void createApplicationProfileTemplate(final String fileName) {
    String failureMessage = "Application profile template generation failed";
    executeCommand(new Cloud4soaCommand(failureMessage) {
        @Override//from  w  ww  .j a  v a2  s.c om
        public void execute() throws Exception {
            String applicationId = "Application123456";
            String latencyUriId = "Latency123456";
            String uptimeUriId = "Uptime123456";
            String timeRangeUriId = "TimeRange123456";
            String timeUnitMaxUriId = "MilliSecondMax1";
            String timeUnitMinUriId = "MilliSecondMax2";

            ApplicationDescriptionGenerator applicationDescriptionGenerator = new ApplicationDescriptionGenerator();
            try {
                applicationDescriptionGenerator.setValue("applicationUriId", applicationId);
                applicationDescriptionGenerator.setValue("latencyUriId", latencyUriId);
                applicationDescriptionGenerator.setValue("uptimeUriId", uptimeUriId);
                applicationDescriptionGenerator.setValue("timeRangeUriId", timeRangeUriId);
                applicationDescriptionGenerator.setValue("timeUnitMaxUriId", timeUnitMaxUriId);
                applicationDescriptionGenerator.setValue("timeUnitMinUriId", timeUnitMinUriId);
                File file = new File(fileName);

                if (file.exists()) {
                    logger.severe("Description file already exists!");
                    logger.severe("Please delete it or change the file name parameter");
                    this.displaySuccessMessage = false;
                    logger.severe(this.failureMessage);
                    return;
                }

                FileOutputStream fos = new FileOutputStream(file);
                applicationDescriptionGenerator.evaluateTemplate(fos);
            } catch (AssertionError exp) {
                logger.severe(exp.getMessage());
            } catch (IllegalArgumentException exp) {
                logger.severe(exp.getMessage());
            }
        }
    });
}

From source file:eu.cloud4soa.cli.roo.addon.Cloud4soaOperationsImpl.java

@Override
public void createPaaSProfileTemplate(final String fileName) {
    String failureMessage = "PaaS offering profile template generation failed";
    executeCommand(new Cloud4soaCommand(failureMessage) {
        @Override/*  www .  j a v a2  s .  co  m*/
        public void execute() throws Exception {
            String paasOfferingUriId = "PaaSOffering123456";
            String latencyUriId = "Latency123456";
            String uptimeUriId = "Uptime123456";
            String timeRangeUriId = "TimeRange123456";
            String timeUnitMaxUriId = "MilliSecondMax1";
            String timeUnitMinUriId = "MilliSecondMin2";

            PaaSOfferingDescriptionGenerator paaSOfferingDescriptionGenerator = new PaaSOfferingDescriptionGenerator();
            try {
                paaSOfferingDescriptionGenerator.setValue("paasOfferingUriId", paasOfferingUriId);
                paaSOfferingDescriptionGenerator.setValue("latencyUriId", latencyUriId);
                paaSOfferingDescriptionGenerator.setValue("uptimeUriId", uptimeUriId);
                paaSOfferingDescriptionGenerator.setValue("timeRangeUriId", timeRangeUriId);
                paaSOfferingDescriptionGenerator.setValue("timeUnitMaxUriId", timeUnitMaxUriId);
                paaSOfferingDescriptionGenerator.setValue("timeUnitMinUriId", timeUnitMinUriId);
                File file = new File(fileName);

                if (file.exists()) {
                    logger.severe("Description file already exists!");
                    logger.severe("Please delete it or change the file name parameter");
                    this.displaySuccessMessage = false;
                    logger.severe(this.failureMessage);
                    return;
                }

                FileOutputStream fos = new FileOutputStream(file);
                paaSOfferingDescriptionGenerator.evaluateTemplate(fos);
            } catch (AssertionError exp) {
                logger.severe(exp.getMessage());
            } catch (IllegalArgumentException exp) {
                logger.severe(exp.getMessage());
            }
        }
    });
}

From source file:brooklyn.util.internal.ssh.sshj.SshjTool.java

protected <T, C extends SshAction<T>> T acquire(C action, int sshTries, Duration sshTriesTimeout) {
    Stopwatch stopwatch = Stopwatch.createStarted();

    for (int i = 0; i < sshTries; i++) {
        try {//from ww w  .ja v a2  s .c om
            action.clear();
            if (LOG.isTraceEnabled())
                LOG.trace(">> ({}) acquiring {}", toString(), action);
            Stopwatch perfStopwatch = Stopwatch.createStarted();

            T returnVal;
            try {
                returnVal = action.create();
            } catch (AssertionError e) {
                /*
                 * TODO In net.schmizz.sshj.SSHClient.auth(SSHClient.java:204) throws AssertionError
                 * if not connected. This can happen if another thread has called disconnect
                 * concurrently. This is changed in sshj v0.9.0 to instead throw an IllegalStateException.
                 * 
                 * For now, we'll retry. See "TODO" at top of class about synchronization.
                 */
                throw new IllegalStateException("Problem in " + toString() + " for " + action, e);
            }

            if (LOG.isTraceEnabled())
                LOG.trace("<< ({}) acquired {}", toString(), returnVal);
            if (LOG.isTraceEnabled())
                LOG.trace("SSH Performance: {} {} took {}", new Object[] { sshClientConnection.getHostAndPort(),
                        action.getClass().getSimpleName() != null ? action.getClass().getSimpleName() : action,
                        Time.makeTimeStringRounded(perfStopwatch) });
            return returnVal;
        } catch (Exception e) {
            // uninformative net.schmizz.sshj.connection.ConnectionException: 
            //    Request failed (reason=UNKNOWN) may mean remote Subsytem is disabled (e.g. for FTP)
            // if key is missing, get a UserAuth error
            String errorMessage = String.format("(%s) error acquiring %s", toString(), action);
            String fullMessage = String.format("%s (attempt %s/%s, in time %s/%s)", errorMessage, (i + 1),
                    sshTries, Time.makeTimeStringRounded(stopwatch.elapsed(TimeUnit.MILLISECONDS)),
                    (sshTriesTimeout.equals(Duration.PRACTICALLY_FOREVER) ? "unlimited"
                            : Time.makeTimeStringRounded(sshTriesTimeout)));
            try {
                disconnect();
            } catch (Exception e2) {
                LOG.debug("<< (" + toString() + ") error closing connection: " + e + " / " + e2, e);
            }
            if (i + 1 == sshTries) {
                LOG.debug("<< {} (rethrowing, out of retries): {}", fullMessage, e.getMessage());
                throw propagate(e, fullMessage + "; out of retries");
            } else if (sshTriesTimeout.isShorterThan(stopwatch)) {
                LOG.debug("<< {} (rethrowing, out of time - max {}): {}", new Object[] { fullMessage,
                        Time.makeTimeStringRounded(sshTriesTimeout), e.getMessage() });
                throw new RuntimeTimeoutException(fullMessage + "; out of time", e);
            } else {
                if (LOG.isDebugEnabled())
                    LOG.debug("<< {}: {}", fullMessage, e.getMessage());
                backoffForAttempt(i + 1, errorMessage + ": " + e.getMessage());
                if (action != sshClientConnection)
                    connect();
                continue;
            }
        }
    }
    assert false : "should not reach here";
    return null;
}