// Path: src/java/com/google/cloud/bigquery/dwhassessment/extractiontool/db/ScriptManagerImpl.java
// @VisibleForTesting
// static String getUtcTimeStringFromTimestamp(Timestamp timestamp) {
//   Instant instant = timestamp.toInstant();
//   // Remove the "Z" (that signifies UTC timezone) and the separators that are not necessary for
//   // human interpretation.
//   String instantWithoutNanoseconds =
//       instant.truncatedTo(ChronoUnit.SECONDS).toString().replaceAll("[Z\\-:]", "").trim();
//   // Keep 6 digits of the fractional seconds from nano, which is equivalent to round(nanos / 10^9
//   // * 10^6) with left-padded zeros. Prepend with S to separate from seconds.
//   String sixDigitNanos =
//       String.format((Locale) null, "S%06d", Math.round(timestamp.getNanos() / Math.pow(10, 3)));
//   return instantWithoutNanoseconds + sixDigitNanos;
// }
// 
// Path: src/java/com/google/cloud/bigquery/dwhassessment/extractiontool/dumper/DataEntityManager.java
// public interface DataEntityManager extends Closeable {
// 
//   /**
//    * Get the output stream for an entity.
//    *
//    * @param name The name of the output entity.
//    */
//   OutputStream getEntityOutputStream(String name) throws IOException;
// 
//   /**
//    * Indicate whether the data entity allows resumable processing.
//    *
//    * @return true if some progress can be retained after the writing is interrupted.
//    */
//   boolean isResumable();
// 
//   /**
//    * Get the absolute path of a file given its name.
//    *
//    * @param name The name of the file.
//    */
//   Path getAbsolutePath(String name);
// }
// 
// Path: src/javatests/com/google/cloud/bigquery/dwhassessment/extractiontool/dumper/FakeDataEntityManagerImpl.java
// public class FakeDataEntityManagerImpl implements DataEntityManager {
// 
//   private final Path tmpDir;
//   private final ByteArrayOutputStream outputStream;
//   private final boolean bareStreamMode;
// 
//   /**
//    * Constructs a fake DataEntityManager for testing; it supports chunked writing; the output files
//    * are saved in a temporary directory.
//    */
//   public FakeDataEntityManagerImpl(String testDirName) throws IOException {
//     this.tmpDir = Files.createTempDirectory(testDirName);
//     this.outputStream = null;
//     bareStreamMode = false;
//   }
// 
//   /**
//    * Construct a fake DataEntityManager with a fixed reference of ByteArrayOutputStream; it does not
//    * support any file operations.
//    */
//   public FakeDataEntityManagerImpl(ByteArrayOutputStream outputStream) {
//     this.outputStream = outputStream;
//     this.tmpDir = null;
//     bareStreamMode = true;
//   }
// 
//   @Override
//   public OutputStream getEntityOutputStream(String name) throws IOException {
//     return bareStreamMode ? outputStream : Files.newOutputStream(tmpDir.resolve(name));
//   }
// 
//   @Override
//   public boolean isResumable() {
//     return !bareStreamMode;
//   }
// 
//   @Override
//   public Path getAbsolutePath(String name) {
//     return bareStreamMode ? null : tmpDir.resolve(name);
//   }
// 
//   @Override
//   public void close() throws IOException {}
// }


import static com.google.common.truth.Truth.assertThat;
import static com.google.cloud.bigquery.dwhassessment.extractiontool.db.ScriptManagerImpl.getUtcTimeStringFromTimestamp;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThrows;
import com.google.cloud.bigquery.dwhassessment.extractiontool.dumper.DataEntityManager;
import com.google.cloud.bigquery.dwhassessment.extractiontool.dumper.FakeDataEntityManagerImpl;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.time.Instant;
import java.util.NoSuchElementException;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import org.apache.avro.Schema;
import org.apache.avro.file.DataFileReader;
import org.apache.avro.file.SeekableByteArrayInput;
import org.apache.avro.generic.GenericData.Record;
import org.apache.avro.generic.GenericDatumReader;
import org.apache.avro.generic.GenericRecordBuilder;
import org.apache.avro.io.DatumReader;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
        connection,
        /*dryRun=*/ false,
        sqlTemplateRenderer,
        "default_chunked",
        dataEntityManagerTmp,
        /*chunkRows=*/ 2,
        /*startingChunkNumber=*/ 7);

    DataFileReader<Record> readerForFirstChunk =
        getAssertingReaderForAvroResults(
            dataEntityManagerTmp.getAbsolutePath(
                "default_chunked-20070707T200707S007000-20070707T200707S007000_7.avro"));
    assertThat(readerForFirstChunk.next().get(1))
        .isEqualTo(Instant.parse("2007-07-07T20:07:07.007000000Z").toEpochMilli());
    assertFalse(readerForFirstChunk.hasNext());
  }

  @Test
  public void getUtcTimeStringFromTimestamp_outputShouldBeCorrect() {
    assertThat(getUtcTimeStringFromTimestamp(Timestamp.from(Instant.parse("2022-01-24T14:52:00Z"))))
        .isEqualTo("20220124T145200S000000");
    assertThat(
            getUtcTimeStringFromTimestamp(
                Timestamp.from(Instant.parse("2022-01-24T14:52:00.000Z"))))
        .isEqualTo("20220124T145200S000000");
    assertThat(
            getUtcTimeStringFromTimestamp(
                Timestamp.from(Instant.parse("2022-01-24T14:52:00.123456Z"))))
        .isEqualTo("20220124T145200S123456");
    assertThat(
// Path: src/java/com/google/cloud/bigquery/dwhassessment/extractiontool/db/ScriptManagerImpl.java
// @VisibleForTesting
// static String getUtcTimeStringFromTimestamp(Timestamp timestamp) {
//   Instant instant = timestamp.toInstant();
//   // Remove the "Z" (that signifies UTC timezone) and the separators that are not necessary for
//   // human interpretation.
//   String instantWithoutNanoseconds =
//       instant.truncatedTo(ChronoUnit.SECONDS).toString().replaceAll("[Z\\-:]", "").trim();
//   // Keep 6 digits of the fractional seconds from nano, which is equivalent to round(nanos / 10^9
//   // * 10^6) with left-padded zeros. Prepend with S to separate from seconds.
//   String sixDigitNanos =
//       String.format((Locale) null, "S%06d", Math.round(timestamp.getNanos() / Math.pow(10, 3)));
//   return instantWithoutNanoseconds + sixDigitNanos;
// }
// 
// Path: src/java/com/google/cloud/bigquery/dwhassessment/extractiontool/dumper/DataEntityManager.java
// public interface DataEntityManager extends Closeable {
// 
//   /**
//    * Get the output stream for an entity.
//    *
//    * @param name The name of the output entity.
//    */
//   OutputStream getEntityOutputStream(String name) throws IOException;
// 
//   /**
//    * Indicate whether the data entity allows resumable processing.
//    *
//    * @return true if some progress can be retained after the writing is interrupted.
//    */
//   boolean isResumable();
// 
//   /**
//    * Get the absolute path of a file given its name.
//    *
//    * @param name The name of the file.
//    */
//   Path getAbsolutePath(String name);
// }
// 
// Path: src/javatests/com/google/cloud/bigquery/dwhassessment/extractiontool/dumper/FakeDataEntityManagerImpl.java
// public class FakeDataEntityManagerImpl implements DataEntityManager {
// 
//   private final Path tmpDir;
//   private final ByteArrayOutputStream outputStream;
//   private final boolean bareStreamMode;
// 
//   /**
//    * Constructs a fake DataEntityManager for testing; it supports chunked writing; the output files
//    * are saved in a temporary directory.
//    */
//   public FakeDataEntityManagerImpl(String testDirName) throws IOException {
//     this.tmpDir = Files.createTempDirectory(testDirName);
//     this.outputStream = null;
//     bareStreamMode = false;
//   }
// 
//   /**
//    * Construct a fake DataEntityManager with a fixed reference of ByteArrayOutputStream; it does not
//    * support any file operations.
//    */
//   public FakeDataEntityManagerImpl(ByteArrayOutputStream outputStream) {
//     this.outputStream = outputStream;
//     this.tmpDir = null;
//     bareStreamMode = true;
//   }
// 
//   @Override
//   public OutputStream getEntityOutputStream(String name) throws IOException {
//     return bareStreamMode ? outputStream : Files.newOutputStream(tmpDir.resolve(name));
//   }
// 
//   @Override
//   public boolean isResumable() {
//     return !bareStreamMode;
//   }
// 
//   @Override
//   public Path getAbsolutePath(String name) {
//     return bareStreamMode ? null : tmpDir.resolve(name);
//   }
// 
//   @Override
//   public void close() throws IOException {}
// }


// Path: src/javatests/com/google/cloud/bigquery/dwhassessment/extractiontool/db/ScriptManagerImplTest.java
import static com.google.common.truth.Truth.assertThat;
import static com.google.cloud.bigquery.dwhassessment.extractiontool.db.ScriptManagerImpl.getUtcTimeStringFromTimestamp;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThrows;
import com.google.cloud.bigquery.dwhassessment.extractiontool.dumper.DataEntityManager;
import com.google.cloud.bigquery.dwhassessment.extractiontool.dumper.FakeDataEntityManagerImpl;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.time.Instant;
import java.util.NoSuchElementException;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import org.apache.avro.Schema;
import org.apache.avro.file.DataFileReader;
import org.apache.avro.file.SeekableByteArrayInput;
import org.apache.avro.generic.GenericData.Record;
import org.apache.avro.generic.GenericDatumReader;
import org.apache.avro.generic.GenericRecordBuilder;
import org.apache.avro.io.DatumReader;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

        connection,
        /*dryRun=*/ false,
        sqlTemplateRenderer,
        "default_chunked",
        dataEntityManagerTmp,
        /*chunkRows=*/ 2,
        /*startingChunkNumber=*/ 7);

    DataFileReader<Record> readerForFirstChunk =
        getAssertingReaderForAvroResults(
            dataEntityManagerTmp.getAbsolutePath(
                "default_chunked-20070707T200707S007000-20070707T200707S007000_7.avro"));
    assertThat(readerForFirstChunk.next().get(1))
        .isEqualTo(Instant.parse("2007-07-07T20:07:07.007000000Z").toEpochMilli());
    assertFalse(readerForFirstChunk.hasNext());
  }

  @Test
  public void getUtcTimeStringFromTimestamp_outputShouldBeCorrect() {
    assertThat(getUtcTimeStringFromTimestamp(Timestamp.from(Instant.parse("2022-01-24T14:52:00Z"))))
        .isEqualTo("20220124T145200S000000");
    assertThat(
            getUtcTimeStringFromTimestamp(
                Timestamp.from(Instant.parse("2022-01-24T14:52:00.000Z"))))
        .isEqualTo("20220124T145200S000000");
    assertThat(
            getUtcTimeStringFromTimestamp(
                Timestamp.from(Instant.parse("2022-01-24T14:52:00.123456Z"))))
        .isEqualTo("20220124T145200S123456");
    assertThat(
            getUtcTimeStringFromTimestamp(