expectedAssocs = new ArrayList<>(5);
        expectedAssocs.add(new ExpectedAssoc(RenditionModel.ASSOC_RENDITION, "imgpreview", 1));
        expectedAssocs.add(new ExpectedAssoc(RenditionModel.ASSOC_RENDITION, "avatar", 1));
//        expectedAssocs.add(new ExpectedAssoc(ContentModel.ASSOC_FAILED_THUMBNAIL, null, 1));
        performLongRunningThumbnailTest(expectedThumbnails, expectedAssocs, new EmptyLongRunningConcurrentWork(), 1, 1);
    }
    
    /**
     * Test transformer.
     * 
     * @since 4.0.1
     */
    private static class TransientFailTransformer extends AbstractContentTransformer2
    {
        public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options)
        {
            return sourceMimetype.equals(MimetypeMap.MIMETYPE_PDF) && targetMimetype.equals(TEST_FAILING_MIME_TYPE);
        }
        
        protected void transformInternal(ContentReader reader, ContentWriter writer, TransformationOptions options) throws Exception
        {
            // fail every time.
            throw new ContentServiceTransientException("Transformation intentionally failed for test purposes.");
        }
    }
    
    /**
     * Bogus transformer that simulates a somewhat longer running transformation
     */
    private static class LongRunningTransformer extends AbstractContentTransformer2
    {
        private int transformCount = 0;
        @Override
        public void register()
        {
            super.register();
            setStrictMimeTypeCheck(false);
        }
        public void setTransformCount(int transformCount)
        {
            this.transformCount = transformCount;
        }
        public int getTransformCount()
        {
            return transformCount;
        }
        
        @Override
        public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options)
        {
            return sourceMimetype.equals(TEST_LONG_RUNNING_MIME_TYPE) && 
                    (targetMimetype.equals(MimetypeMap.MIMETYPE_IMAGE_JPEG) ||
                            targetMimetype.equals(MimetypeMap.MIMETYPE_IMAGE_PNG));
        }
        @Override
        protected void transformInternal(ContentReader reader, ContentWriter writer, TransformationOptions options)
                throws Exception
        {
            Thread.sleep(TEST_LONG_RUNNING_TRANSFORM_TIME);
            writer.putContent("SUCCESS");
            transformCount++;
        }
    }
    
    /**
     * Defines the work to be done while long running transformations are being performed
     * and the means to verify that work completed successfully.
     * 
     * Implementations might update a property then verify the updated value for example.
     */
    private interface LongRunningConcurrentWork
    {
        public void run(NodeRef source) throws Exception;
        public void verify(NodeRef source) throws Exception;
    }
    
    /**
     * Implementation of LongRunningConcurrentWork that does nothing
     */
    private class EmptyLongRunningConcurrentWork implements LongRunningConcurrentWork
    {
        @Override
        public void run(NodeRef source) throws Exception { }
        @Override
        public void verify(NodeRef source) throws Exception { }
    }
}