// Path: core/src/main/java/com/github/jeluard/stone/api/ConsolidationListener.java
// public interface ConsolidationListener {
// 
//   interface Persistent extends ConsolidationListener {
// 
//     /**
//      * @return latest (most recent) timestamp persisted
//      */
//     Optional<Long> getLatestTimestamp();
// 
//   }
// 
//   /**
//    * Invoked each time a newly published value cross a {@link Window} boundary triggering the consolidation process.
//    * <br>
//    * Different thread might invoke this method but never concurrently. Consecutive {@code timestamp} values are guaranteed to be monotonically increasing.
//    *
//    * @param timestamp end timestamp for window just crossed
//    * @param consolidates array of consolidated values in the {@link Window#getConsolidatorTypes()} order; array will be reused so don't store as is
//    */
//   void onConsolidation(long timestamp, int[] consolidates);
// 
// }
// 
// Path: core/src/main/java/com/github/jeluard/stone/spi/Storage.java
// @ThreadSafe
// public abstract class Storage implements Reader {
// 
//   private final int maximumSize;
// 
//   public Storage(final int maximumSize) {
//     this.maximumSize = maximumSize;
//   }
// 
//   /**
//    * @return
//    */
//   protected final int getMaximumSize() {
//     return this.maximumSize;
//   }
// 
//   /**
//    * Default implementation relying on {@link #all()}.
//    *
//    * @return 
//    */
//   @Override
//   public Optional<Long> beginning() throws IOException {
//     try {
//       final Iterator<Pair<Long, int[]>> consolidates = all().iterator();
//       return Optional.of(consolidates.next().first);
//     } catch (NoSuchElementException e) {
//       return Optional.absent();
//     }
//   }
// 
//   /**
//    * Default implementation relying on {@link #all()}: it iterates over {@link #all()} elements to access the last one.
//    *
//    * @return 
//    * @see Iterables#getLast(java.lang.Iterable)
//    */
//   @Override
//   public Optional<Long> end() throws IOException {
//     try {
//       final Iterator<Pair<Long, int[]>> consolidates = all().iterator();
//       return Optional.of(Iterators.getLast(consolidates).first);
//     } catch (NoSuchElementException e) {
//       return Optional.absent();
//     }
//   }
// 
//   /**
//    * Default implementation relying on {@link #all()}: it iterates over all elements while they are parts of specified {@code interval}.
//    *
//    * @param beginning
//    * @param end
//    * @return 
//    * @see AbstractIterator
//    */
//   @Override
//   public Iterable<Pair<Long, int[]>> during(final long beginning, final long end) throws IOException {
//     return new Iterable<Pair<Long, int[]>>() {
//       final Iterable<Pair<Long, int[]>> all = all();
//       @Override 
//       public Iterator<Pair<Long, int[]>> iterator() {
//         return new AbstractIterator<Pair<Long, int[]>>() {
//           final Iterator<Pair<Long, int[]>> iterator = all.iterator();
//           @Override
//           protected Pair<Long, int[]> computeNext() {
//             while (this.iterator.hasNext()) {
//               final Pair<Long, int[]> consolidates = this.iterator.next();
//               final long timestamp = consolidates.first;
//               if (timestamp < beginning) {
//                 //Before the beginning
//                 continue;
//               }
//               if (timestamp > end) {
//                 //After the beginning
//                 break;
//               }
// 
//               return consolidates;
//             }
//             return endOfData();
//           }
//         };
//       }
//     };
//   }
// 
//   /**
//    * Append {@code values} associated to {@code timestamp}.
//    *
//    * @param timestamp
//    * @param values
//    * @throws IOException 
//    */
//   public abstract void append(long timestamp, int[] values) throws IOException;
// 
// }


import com.github.jeluard.guayaba.test.AbstractHelperClassTest;
import com.github.jeluard.guayaba.test.junit.LoggerRule;
import com.github.jeluard.stone.api.ConsolidationListener;
import com.github.jeluard.stone.spi.Storage;
import java.io.IOException;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mockito;
/**
 * Copyright 2012 Julien Eluard
 * This project includes software developed by Julien Eluard: https://github.com/jeluard/
 *
 * 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.github.jeluard.stone.helper;




public class StoragesTest extends AbstractHelperClassTest {

  @Rule
  public LoggerRule loggerRule = new LoggerRule(Loggers.BASE_LOGGER);

  @Override
  protected Class<?> getType() {
    return Storages.class;
  }

  @Test
  public void shouldConsolidationBePropagated() throws IOException {
    final Storage storage = Mockito.mock(Storage.class);
    final ConsolidationListener consolidationListener = Storages.asConsolidationListener(storage, Loggers.BASE_LOGGER);
    consolidationListener.onConsolidation(System.currentTimeMillis(), new int[0]);

    Mockito.verify(storage).append(Mockito.anyLong(), Mockito.any(int[].class));
  }

  @Test
  public void shouldConsolidationListenerBeSafe() throws IOException {
    final Storage storage = Mockito.mock(Storage.class);
    Mockito.doThrow(new IOException()).when(storage).append(Mockito.anyLong(), Mockito.any(int[].class));
// Path: core/src/main/java/com/github/jeluard/stone/api/ConsolidationListener.java
// public interface ConsolidationListener {
// 
//   interface Persistent extends ConsolidationListener {
// 
//     /**
//      * @return latest (most recent) timestamp persisted
//      */
//     Optional<Long> getLatestTimestamp();
// 
//   }
// 
//   /**
//    * Invoked each time a newly published value cross a {@link Window} boundary triggering the consolidation process.
//    * <br>
//    * Different thread might invoke this method but never concurrently. Consecutive {@code timestamp} values are guaranteed to be monotonically increasing.
//    *
//    * @param timestamp end timestamp for window just crossed
//    * @param consolidates array of consolidated values in the {@link Window#getConsolidatorTypes()} order; array will be reused so don't store as is
//    */
//   void onConsolidation(long timestamp, int[] consolidates);
// 
// }
// 
// Path: core/src/main/java/com/github/jeluard/stone/spi/Storage.java
// @ThreadSafe
// public abstract class Storage implements Reader {
// 
//   private final int maximumSize;
// 
//   public Storage(final int maximumSize) {
//     this.maximumSize = maximumSize;
//   }
// 
//   /**
//    * @return
//    */
//   protected final int getMaximumSize() {
//     return this.maximumSize;
//   }
// 
//   /**
//    * Default implementation relying on {@link #all()}.
//    *
//    * @return 
//    */
//   @Override
//   public Optional<Long> beginning() throws IOException {
//     try {
//       final Iterator<Pair<Long, int[]>> consolidates = all().iterator();
//       return Optional.of(consolidates.next().first);
//     } catch (NoSuchElementException e) {
//       return Optional.absent();
//     }
//   }
// 
//   /**
//    * Default implementation relying on {@link #all()}: it iterates over {@link #all()} elements to access the last one.
//    *
//    * @return 
//    * @see Iterables#getLast(java.lang.Iterable)
//    */
//   @Override
//   public Optional<Long> end() throws IOException {
//     try {
//       final Iterator<Pair<Long, int[]>> consolidates = all().iterator();
//       return Optional.of(Iterators.getLast(consolidates).first);
//     } catch (NoSuchElementException e) {
//       return Optional.absent();
//     }
//   }
// 
//   /**
//    * Default implementation relying on {@link #all()}: it iterates over all elements while they are parts of specified {@code interval}.
//    *
//    * @param beginning
//    * @param end
//    * @return 
//    * @see AbstractIterator
//    */
//   @Override
//   public Iterable<Pair<Long, int[]>> during(final long beginning, final long end) throws IOException {
//     return new Iterable<Pair<Long, int[]>>() {
//       final Iterable<Pair<Long, int[]>> all = all();
//       @Override 
//       public Iterator<Pair<Long, int[]>> iterator() {
//         return new AbstractIterator<Pair<Long, int[]>>() {
//           final Iterator<Pair<Long, int[]>> iterator = all.iterator();
//           @Override
//           protected Pair<Long, int[]> computeNext() {
//             while (this.iterator.hasNext()) {
//               final Pair<Long, int[]> consolidates = this.iterator.next();
//               final long timestamp = consolidates.first;
//               if (timestamp < beginning) {
//                 //Before the beginning
//                 continue;
//               }
//               if (timestamp > end) {
//                 //After the beginning
//                 break;
//               }
// 
//               return consolidates;
//             }
//             return endOfData();
//           }
//         };
//       }
//     };
//   }
// 
//   /**
//    * Append {@code values} associated to {@code timestamp}.
//    *
//    * @param timestamp
//    * @param values
//    * @throws IOException 
//    */
//   public abstract void append(long timestamp, int[] values) throws IOException;
// 
// }


// Path: core/src/test/java/com/github/jeluard/stone/helper/StoragesTest.java
import com.github.jeluard.guayaba.test.AbstractHelperClassTest;
import com.github.jeluard.guayaba.test.junit.LoggerRule;
import com.github.jeluard.stone.api.ConsolidationListener;
import com.github.jeluard.stone.spi.Storage;
import java.io.IOException;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mockito;

/**
 * Copyright 2012 Julien Eluard
 * This project includes software developed by Julien Eluard: https://github.com/jeluard/
 *
 * 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.github.jeluard.stone.helper;




public class StoragesTest extends AbstractHelperClassTest {

  @Rule
  public LoggerRule loggerRule = new LoggerRule(Loggers.BASE_LOGGER);

  @Override
  protected Class<?> getType() {
    return Storages.class;
  }

  @Test
  public void shouldConsolidationBePropagated() throws IOException {
    final Storage storage = Mockito.mock(Storage.class);
    final ConsolidationListener consolidationListener = Storages.asConsolidationListener(storage, Loggers.BASE_LOGGER);
    consolidationListener.onConsolidation(System.currentTimeMillis(), new int[0]);

    Mockito.verify(storage).append(Mockito.anyLong(), Mockito.any(int[].class));
  }

  @Test
  public void shouldConsolidationListenerBeSafe() throws IOException {
    final Storage storage = Mockito.mock(Storage.class);
    Mockito.doThrow(new IOException()).when(storage).append(Mockito.anyLong(), Mockito.any(int[].class));
    final ConsolidationListener consolidationListener = Storages.asConsolidationListener(storage, Loggers.BASE_LOGGER);