/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 org.jclouds.s3.xml;

import static org.testng.Assert.assertEquals;

import java.io.IOException;
import java.util.Date;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;

import org.jclouds.PerformanceTest;
import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.http.functions.config.SaxParserModule;
import org.jclouds.s3.domain.BucketMetadata;
import org.jclouds.s3.domain.CanonicalUser;
import org.jclouds.s3.domain.ListBucketResponse;
import org.jclouds.s3.domain.ObjectMetadata;
import org.jclouds.s3.domain.ObjectMetadata.StorageClass;
import org.jclouds.util.Strings2;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import org.xml.sax.SAXException;

import com.google.common.collect.Iterables;
import com.google.inject.Guice;
import com.google.inject.Injector;

/**
 * Tests parsing of S3 responses
 */
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
@Test(groups = "performance", sequential = true, timeOut = 2 * 60 * 1000, testName = "S3ParserTest")
public class S3ParserTest extends PerformanceTest {
   Injector injector = null;
   ParseSax.Factory factory;

   @BeforeTest
   protected void setUpInjector() {
      injector = Guice.createInjector(new SaxParserModule());
      factory = injector.getInstance(ParseSax.Factory.class);
      assert factory != null;
   }

   @AfterTest
   protected void tearDownInjector() {
      factory = null;
      injector = null;
   }

   public static final String listAllMyBucketsResultOn200 = "<ListAllMyBucketsResult xmlns=\"http://s3.amazonaws.com/doc/callables/\"><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID></Owner><Buckets><Bucket><Name>adrianjbosstest</Name><CreationDate>2009-03-12T02:00:07.000Z</CreationDate></Bucket><Bucket><Name>adrianjbosstest2</Name><CreationDate>2009-03-12T02:00:09.000Z</CreationDate></Bucket></Buckets></ListAllMyBucketsResult>";
   public static final String listAllMyBucketsResultOn200DisplayNameFirst = "<ListAllMyBucketsResult xmlns=\"http://s3.amazonaws.com/doc/callables/\"><Owner><DisplayName>TestName</DisplayName><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID></Owner><Buckets><Bucket><Name>adrianjbosstest</Name><CreationDate>2009-03-12T02:00:07.000Z</CreationDate></Bucket></Buckets></ListAllMyBucketsResult>";
   public static final String listAllMyBucketsResultOn200OwnerLast = "<ListAllMyBucketsResult xmlns=\"http://s3.amazonaws.com/doc/callables/\"><Buckets><Bucket><Name>adrianjbosstest</Name><CreationDate>2009-03-12T02:00:07.000Z</CreationDate></Bucket></Buckets><Owner><DisplayName>TestName</DisplayName><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID></Owner></ListAllMyBucketsResult>";

   @Test
   void testParseListAllMyBucketsSerialResponseTime() throws HttpException {
      for (int i = 0; i < LOOP_COUNT; i++)
         runParseListAllMyBuckets();
   }

   private Set<BucketMetadata> runParseListAllMyBuckets() throws HttpException {
      return factory.create(injector.getInstance(ListAllMyBucketsHandler.class)).parse(
               Strings2.toInputStream(listAllMyBucketsResultOn200));
   }

   @Test
   void testParseListAllMyBucketsParallelResponseTime() throws InterruptedException, ExecutionException {
      CompletionService<Set<BucketMetadata>> completer = new ExecutorCompletionService<Set<BucketMetadata>>(exec);
      for (int i = 0; i < LOOP_COUNT; i++)
         completer.submit(new Callable<Set<BucketMetadata>>() {
            public Set<BucketMetadata> call() throws IOException, SAXException, HttpException {
               return runParseListAllMyBuckets();
            }
         });
      for (int i = 0; i < LOOP_COUNT; i++)
         assert completer.take().get() != null;
   }

   @Test
   public void testCanParseListAllMyBuckets() throws HttpException {
      Set<BucketMetadata> s3Buckets = runParseListAllMyBuckets();
      BucketMetadata container1 = Iterables.get(s3Buckets, 0);
      assert container1.getName().equals("adrianjbosstest");
      Date expectedDate1 = new SimpleDateFormatDateService().iso8601DateParse("2009-03-12T02:00:07.000Z");
      Date date1 = container1.getCreationDate();
      assert date1.equals(expectedDate1);
      BucketMetadata container2 = (BucketMetadata) s3Buckets.toArray()[1];
      assert container2.getName().equals("adrianjbosstest2");
      Date expectedDate2 = new SimpleDateFormatDateService().iso8601DateParse("2009-03-12T02:00:09.000Z");
      Date date2 = container2.getCreationDate();
      assert date2.equals(expectedDate2);
      assert s3Buckets.size() == 2;
      CanonicalUser owner = new CanonicalUser("e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0");
      assert container1.getOwner().equals(owner);
      assert container2.getOwner().equals(owner);
   }

   @Test
   public void testCanParseListAllMyBucketsDisplayNameFirst() throws HttpException {
      Set<BucketMetadata> s3Buckets = factory.create(injector.getInstance(ListAllMyBucketsHandler.class)).parse(
              Strings2.toInputStream(listAllMyBucketsResultOn200DisplayNameFirst));
      BucketMetadata container = Iterables.get(s3Buckets, 0);
      assert container.getName().equals("adrianjbosstest");
      Date expectedDate1 = new SimpleDateFormatDateService().iso8601DateParse("2009-03-12T02:00:07.000Z");
      Date date = container.getCreationDate();
      assert date.equals(expectedDate1);
      assert s3Buckets.size() == 1;
      CanonicalUser owner = new CanonicalUser("e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0",
              "TestName");
      assert container.getOwner().equals(owner);
   }

   @Test
   public void testCanParseListAllMyBucketsOwnerLast() throws HttpException {
      Set<BucketMetadata> s3Buckets = factory.create(injector.getInstance(ListAllMyBucketsHandler.class)).parse(
              Strings2.toInputStream(listAllMyBucketsResultOn200OwnerLast));
      BucketMetadata container = Iterables.get(s3Buckets, 0);
      assert container.getName().equals("adrianjbosstest");
      Date expectedDate = new SimpleDateFormatDateService().iso8601DateParse("2009-03-12T02:00:07.000Z");
      Date date1 = container.getCreationDate();
      assert date1.equals(expectedDate);
      assert s3Buckets.size() == 1;
      CanonicalUser owner = new CanonicalUser("e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0",
              "TestName");
      assert container.getOwner().equals(owner);
   }

   public static final String listContainerResult = "<ListContainerHandler xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Name>adrianjbosstest</Name><Prefix></Prefix><Marker></Marker><MaxKeys>1000</MaxKeys><IsTruncated>false</IsTruncated><Contents><Key>3366</Key><LastModified>2009-03-12T02:00:13.000Z</LastModified><ETag>&quot;9d7bb64e8e18ee34eec06dd2cf37b766&quot;</ETag><Size>136</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents></ListContainerHandler>";

   public void testCanParseListContainerResult() throws HttpException {
      ListBucketResponse container = runParseListContainerResult();
      assert !container.isTruncated();
      assert container.getName().equals("adrianjbosstest");
      assert container.size() == 1;
      ObjectMetadata object = container.iterator().next();
      assert object.getKey().equals("3366");
      Date expected = new SimpleDateFormatDateService().iso8601DateParse("2009-03-12T02:00:13.000Z");
      assert object.getLastModified().equals(expected) : String.format("expected %1$s, but got %2$s", expected, object
               .getLastModified());
      assertEquals(object.getETag(), "\"9d7bb64e8e18ee34eec06dd2cf37b766\"");
      assert object.getContentMetadata().getContentLength() == 136;
      CanonicalUser owner = new CanonicalUser("e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0");
      owner.setDisplayName("ferncam");
      assert object.getOwner().equals(owner);
      assert object.getStorageClass().equals(StorageClass.STANDARD);
   }

   private ListBucketResponse runParseListContainerResult() throws HttpException {
      return factory.create(injector.getInstance(ListBucketHandler.class)).setContext(
               HttpRequest.builder().method("GET").endpoint("http://bucket.com").build()).parse(
               Strings2.toInputStream(listContainerResult));
   }

   public static final String successfulCopyObject200 = "<CopyObjectResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><LastModified>2009-03-19T13:23:27.000Z</LastModified><ETag>\"92836a3ea45a6984d1b4d23a747d46bb\"</ETag></CopyObjectResult>";

   private ObjectMetadata runParseCopyObjectResult() throws HttpException {
      return factory.create(injector.getInstance(CopyObjectHandler.class)).parse(
               Strings2.toInputStream(successfulCopyObject200));
   }

   public void testCanParseCopyObjectResult() throws HttpException {
      ObjectMetadata metadata = runParseCopyObjectResult();
      Date expected = new SimpleDateFormatDateService().iso8601DateParse("2009-03-19T13:23:27.000Z");
      assertEquals(metadata.getLastModified(), expected);
      assertEquals(metadata.getETag(), "\"92836a3ea45a6984d1b4d23a747d46bb\"");
   }

   @Test
   void testParseListContainerResultSerialResponseTime() throws HttpException {
      for (int i = 0; i < LOOP_COUNT; i++)
         runParseListContainerResult();
   }

   @Test
   void testParseListContainerResultParallelResponseTime() throws InterruptedException, ExecutionException {
      CompletionService<ListBucketResponse> completer = new ExecutorCompletionService<ListBucketResponse>(exec);
      for (int i = 0; i < LOOP_COUNT; i++)
         completer.submit(new Callable<ListBucketResponse>() {
            public ListBucketResponse call() throws IOException, SAXException, HttpException {
               return runParseListContainerResult();
            }
         });
      for (int i = 0; i < LOOP_COUNT; i++)
         assert completer.take().get() != null;
   }

}
