Coverage Report - com.jcabi.dynamo.mock.MadeTable
 
Classes in this File Line Coverage Branch Coverage Complexity
MadeTable
0%
0/39
0%
0/6
2
 
 1  
 /**
 2  
  * Copyright (c) 2012-2016, jcabi.com
 3  
  * All rights reserved.
 4  
  *
 5  
  * Redistribution and use in source and binary forms, with or without
 6  
  * modification, are permitted provided that the following conditions
 7  
  * are met: 1) Redistributions of source code must retain the above
 8  
  * copyright notice, this list of conditions and the following
 9  
  * disclaimer. 2) Redistributions in binary form must reproduce the above
 10  
  * copyright notice, this list of conditions and the following
 11  
  * disclaimer in the documentation and/or other materials provided
 12  
  * with the distribution. 3) Neither the name of the jcabi.com nor
 13  
  * the names of its contributors may be used to endorse or promote
 14  
  * products derived from this software without specific prior written
 15  
  * permission.
 16  
  *
 17  
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 18  
  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
 19  
  * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 20  
  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 21  
  * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 22  
  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 23  
  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 24  
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 25  
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 26  
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 27  
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 28  
  * OF THE POSSIBILITY OF SUCH DAMAGE.
 29  
  */
 30  
 package com.jcabi.dynamo.mock;
 31  
 
 32  
 import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
 33  
 import com.amazonaws.services.dynamodbv2.model.CreateTableRequest;
 34  
 import com.amazonaws.services.dynamodbv2.model.DeleteTableRequest;
 35  
 import com.amazonaws.services.dynamodbv2.model.DescribeTableRequest;
 36  
 import com.amazonaws.services.dynamodbv2.model.DescribeTableResult;
 37  
 import com.amazonaws.services.dynamodbv2.model.ResourceNotFoundException;
 38  
 import com.jcabi.aspects.Tv;
 39  
 import com.jcabi.dynamo.Region;
 40  
 import com.jcabi.log.Logger;
 41  
 import java.util.concurrent.TimeUnit;
 42  
 
 43  
 /**
 44  
  * A Table that can be made and dropped.
 45  
  *
 46  
  * <p>Use it like this in your integration test:
 47  
  *
 48  
  * <pre> public class FooITCase {
 49  
  *   private Region region;
 50  
  *   private MadeTable table;
 51  
  *   &#64;Before
 52  
  *   public void prepare() {
 53  
  *     this.region = new Region.Simple(..your IT credentials..);
 54  
  *     this.table = new MadeTable(this.region, new CreateTableRequest()...);
 55  
  *     this.table.createIfAbsent();
 56  
  *   }
 57  
  *   &#64;After
 58  
  *   public void dropTable() {
 59  
  *     this.table.drop();
 60  
  *   }
 61  
  *   &#64;Test
 62  
  *   public void createsAndDeletesItems() {
 63  
  *     Foo foo = new Foo(this.region);
 64  
  *     foo.doSomething();
 65  
  *   }
 66  
  * }</pre>
 67  
  *
 68  
  * <p>In this example, a new DynamoDB table will be created before every
 69  
  * test method, and dropped when it's finished. This may be not the best
 70  
  * approach performance wise, since every table creation takes at least
 71  
  * ten seconds (at the time of writing). To speed things up a little, you
 72  
  * can create table before the entire test case and drop when all methods
 73  
  * are completed:
 74  
  *
 75  
  * <pre> public class FooITCase {
 76  
  *   private static Region region;
 77  
  *   private static MadeTable table;
 78  
  *   &#64;BeforeClass
 79  
  *   public static void prepare() {
 80  
  *     FooITCase.region = new Region.Simple(..your IT credentials..);
 81  
  *     FooITCase.table = new MadeTable(
 82  
  *       FooITCase.region, new CreateTableRequest()...
 83  
  *     );
 84  
  *     FooITCase.table.createIfAbsent();
 85  
  *   }
 86  
  *   &#64;AfterClass
 87  
  *   public static void dropTable() {
 88  
  *     FooITCase.table.drop();
 89  
  *   }
 90  
  *   &#64;Test
 91  
  *   public void createsAndDeletesItems() {
 92  
  *     Foo foo = new Foo(FooITCase.region);
 93  
  *     foo.doSomething();
 94  
  *   }
 95  
  * }</pre>
 96  
  *
 97  
  * <p>You IAM user policy would look like this (XXXXX should be replaced
 98  
  * by your AWS account number):
 99  
  *
 100  
  * <pre>{
 101  
  *   "Statement": [
 102  
  *     {
 103  
  *       "Action": "dynamodb:*",
 104  
  *       "Effect": "Allow",
 105  
  *       "Resource": "arn:aws:dynamodb:us-east-1:XXXXX:table/test-*"
 106  
  *     },
 107  
  *     {
 108  
  *       "Action": "dynamodb:ListTables",
 109  
  *       "Effect": "Allow",
 110  
  *       "Resource": "*"
 111  
  *     }
 112  
  *   ]
 113  
  * }</pre>
 114  
  *
 115  
  * @author Yegor Bugayenko (yegor@tpc2.com)
 116  
  * @version $Id: ded0f6fff8dba974331a6cd34f65b53c017a5fbb $
 117  
  * @since 0.8
 118  
  */
 119  
 public final class MadeTable {
 120  
 
 121  
     /**
 122  
      * Region.
 123  
      */
 124  
     private final transient Region region;
 125  
 
 126  
     /**
 127  
      * Table name.
 128  
      */
 129  
     private final transient CreateTableRequest request;
 130  
 
 131  
     /**
 132  
      * Public ctor.
 133  
      * @param reg Region
 134  
      * @param req Request
 135  
      */
 136  0
     public MadeTable(final Region reg, final CreateTableRequest req) {
 137  0
         this.region = reg;
 138  0
         this.request = req;
 139  0
     }
 140  
 
 141  
     /**
 142  
      * Create table if it's absent.
 143  
      * @throws InterruptedException If something fails
 144  
      * @since 0.9
 145  
      */
 146  
     public void createIfAbsent() throws InterruptedException {
 147  0
         if (!this.exists()) {
 148  0
             this.create();
 149  
         }
 150  0
     }
 151  
 
 152  
     /**
 153  
      * Create table.
 154  
      * @throws InterruptedException If something fails
 155  
      */
 156  
     public void create() throws InterruptedException {
 157  0
         final AmazonDynamoDB aws = this.region.aws();
 158  0
         final String name = this.request.getTableName();
 159  0
         aws.createTable(this.request);
 160  0
         Logger.info(this, "DynamoDB table '%s' creation requested...", name);
 161  0
         final DescribeTableRequest req = new DescribeTableRequest()
 162  
             .withTableName(name);
 163  
         while (true) {
 164  0
             final DescribeTableResult result = aws.describeTable(req);
 165  0
             if ("ACTIVE".equals(result.getTable().getTableStatus())) {
 166  0
                 Logger.info(
 167  
                     this,
 168  
                     "DynamoDB table '%s' is %s",
 169  
                     name, result.getTable().getTableStatus()
 170  
                 );
 171  0
                 break;
 172  
             }
 173  0
             Logger.info(
 174  
                 this,
 175  
                 "waiting for DynamoDB table '%s': %s",
 176  
                 name, result.getTable().getTableStatus()
 177  
             );
 178  0
             TimeUnit.SECONDS.sleep((long) Tv.TEN);
 179  0
         }
 180  0
     }
 181  
 
 182  
     /**
 183  
      * Drop table.
 184  
      * @throws InterruptedException If something fails
 185  
      */
 186  
     public void drop() throws InterruptedException {
 187  0
         final AmazonDynamoDB aws = this.region.aws();
 188  0
         final String name = this.request.getTableName();
 189  0
         aws.deleteTable(new DeleteTableRequest().withTableName(name));
 190  0
         Logger.info(this, "DynamoDB table '%s' deletion requested", name);
 191  0
         while (this.exists()) {
 192  0
             Logger.info(this, "DynamoDB table '%s' still exists", name);
 193  0
             TimeUnit.SECONDS.sleep((long) Tv.TEN);
 194  
         }
 195  0
         Logger.info(this, "DynamoDB table '%s' deleted", name);
 196  0
     }
 197  
 
 198  
     /**
 199  
      * The table exists?
 200  
      * @return TRUE if it exists in DynamoDB
 201  
      * @since 0.9
 202  
      */
 203  
     public boolean exists() {
 204  0
         final AmazonDynamoDB aws = this.region.aws();
 205  0
         final String name = this.request.getTableName();
 206  
         boolean exists;
 207  
         try {
 208  0
             aws.describeTable(name);
 209  0
             exists = true;
 210  0
             Logger.info(this, "DynamoDB table '%s' already exists", name);
 211  0
         } catch (final ResourceNotFoundException ex) {
 212  0
             exists = false;
 213  0
             Logger.info(
 214  
                 this, "DynamoDB table '%s' doesn't exist: %s",
 215  
                 name, ex.getLocalizedMessage()
 216  
             );
 217  0
         }
 218  0
         return exists;
 219  
     }
 220  
 
 221  
 }