diff --git a/isis/src/base/objs/Cube/Cube.h b/isis/src/base/objs/Cube/Cube.h
index eff3b9b33a8e351132e86a248c7c429d078d3664..559aca34d45f24ecacbb2256b8243d4fc4f9b367 100644
--- a/isis/src/base/objs/Cube/Cube.h
+++ b/isis/src/base/objs/Cube/Cube.h
@@ -325,7 +325,7 @@ namespace Isis {
       void putGroup(const PvlGroup &group);
       void latLonRange(double &minLatitude, double &maxLatitude, double &minLongitude,
                        double &maxLongitude);
-
+      FileName realDataFileName() const;
 
     private:
       void applyVirtualBandsToLabel();
@@ -333,7 +333,6 @@ namespace Isis {
 
       void construct();
       QFile *dataFile() const;
-      FileName realDataFileName() const;
 
       void initialize();
       void initCoreFromLabel(const Pvl &label);
diff --git a/isis/src/base/objs/Cube/CubeIoHandler.h b/isis/src/base/objs/Cube/CubeIoHandler.h
index 016371815bdcb54d1fa726284e69b05c5b9f6668..a5114ec4fea3cd065c1734be1ae24480bf2944ae 100644
--- a/isis/src/base/objs/Cube/CubeIoHandler.h
+++ b/isis/src/base/objs/Cube/CubeIoHandler.h
@@ -127,8 +127,6 @@ namespace Isis {
       virtual void updateLabels(Pvl &labels) = 0;
 
       QMutex *dataFileMutex();
-
-    protected:
       int bandCount() const;
       int getBandCountInChunk() const;
       BigInt getBytesPerChunk() const;
@@ -137,13 +135,15 @@ namespace Isis {
       int getChunkCountInSampleDimension() const;
       int getChunkIndex(const RawCubeChunk &)  const;
       BigInt getDataStartByte() const;
-      QFile * getDataFile();
       int lineCount() const;
       int getLineCountInChunk() const;
       PixelType pixelType() const;
       int sampleCount() const;
       int getSampleCountInChunk() const;
 
+    protected:
+      QFile * getDataFile();
+
       void setChunkSizes(int numSamples, int numLines, int numBands);
 
       /**
diff --git a/isis/src/base/objs/Cube/Cube_truth.txt b/isis/src/base/objs/Cube/Cube_truth.txt
deleted file mode 100644
index cfa3c15e76d8ee728e588cb4bc39f4a15426ba5b..0000000000000000000000000000000000000000
--- a/isis/src/base/objs/Cube/Cube_truth.txt
+++ /dev/null
@@ -1,346 +0,0 @@
-Unit test for Cube
-Constructing cube ... 
-File   = 
-Samps  = 0
-Lines  = 0
-Bands  = 0
-Base   = 0
-Mult   = 1
-Type   = 7
-Atchd  = 1
-Format = 1
-Open   = 0
-R/O    = N/A
-R/W    = N/A
-Lbytes = 65536
-
-Creating 32-bit cube ... 
-File   = IsisCube_00.cub
-Samps  = 150
-Lines  = 200
-Bands  = 2
-Base   = 0
-Mult   = 1
-Type   = 7
-Atchd  = 1
-Format = 1
-Open   = 1
-R/O    = 0
-R/W    = 1
-Lbytes = 65536
-
-Write cube ... 
-Opening cube ... 
-File   = IsisCube_01.cub
-Samps  = 150
-Lines  = 200
-Bands  = 2
-Base   = 0
-Mult   = 1
-Type   = 7
-Atchd  = 1
-Format = 1
-Open   = 1
-R/O    = 1
-R/W    = 0
-Lbytes = 6563
-
-Comparing cube ... 
-
-Creating 8-bit cube ... 
-Comparing cube ... 
-File   = IsisCube_02.lbl
-Samps  = 150
-Lines  = 200
-Bands  = 1
-Base   = 200
-Mult   = -1
-Type   = 1
-Atchd  = 0
-Format = 0
-Open   = 1
-R/O    = 1
-R/W    = 0
-Lbytes = 419
-
-Creating 16-bit cube ... 
-Comparing cube ... 
-File   = IsisCube_03.cub
-Samps  = 150
-Lines  = 200
-Bands  = 2
-Base   = 30000
-Mult   = -1
-Type   = 4
-Atchd  = 1
-Format = 1
-Open   = 1
-R/O    = 1
-R/W    = 0
-Lbytes = 65536
-
-Testing histogram method, band 1 ... 
-Average:        14900
-Standard Dev:   8602.66
-Mode:           149.148
-Total Pixels:   30000
-Null Pixels:    0
-
-Testing histogram method, all bands ... 
-Average:        29800
-Standard Dev:   17205.2
-Mode:           149.148
-Total Pixels:   60000
-Null Pixels:    0
-
-**PROGRAMMER ERROR** Invalid band in [CubeInfo::Histogram].
-**PROGRAMMER ERROR** Cannot create histogram object for an unopened cube.
-
-Testing statistics method, band 1 ... 
-Average:        14900
-Standard Dev:   8602.66
-Total Pixels:   30000
-Null Pixels:    0
-
-Testing statistics method, all bands ... 
-Average:        29800
-Standard Dev:   17205.2
-Total Pixels:   60000
-Null Pixels:    0
-
-**PROGRAMMER ERROR** Invalid band in [CubeInfo::Statistics].
-**PROGRAMMER ERROR** Cannot create statistics object for an unopened cube.
-
-Virtual band tests
-Nbands = 2
-Band 1 = 1
-Band 2 = 2
-
-Nbands = 1
-Band 1 = 2
-
-ReOpen tests
-File   = IsisCube_01.cub
-Samps  = 150
-Lines  = 200
-Bands  = 1
-Base   = 0
-Mult   = 1
-Type   = 7
-Atchd  = 1
-Format = 1
-Open   = 1
-R/O    = 1
-R/W    = 0
-Lbytes = 6563
-
-File   = IsisCube_01.cub
-Samps  = 150
-Lines  = 200
-Bands  = 1
-Base   = 0
-Mult   = 1
-Type   = 7
-Atchd  = 1
-Format = 1
-Open   = 1
-R/O    = 0
-R/W    = 1
-Lbytes = 6563
-
-File   = IsisCube_01.cub
-Samps  = 150
-Lines  = 200
-Bands  = 1
-Base   = 0
-Mult   = 1
-Type   = 7
-Atchd  = 1
-Format = 1
-Open   = 1
-R/O    = 1
-R/W    = 0
-Lbytes = 6563
-
-Testing reading past cube boundaries ... 
-Constructing cube ... 
-
-File   = IsisCube_boundary.cub
-Samps  = 10
-Lines  = 10
-Bands  = 4
-Base   = 0
-Mult   = 1
-Type   = 7
-Atchd  = 1
-Format = 1
-Open   = 1
-R/O    = 0
-R/W    = 1
-Lbytes = 65536
-
-Reading completely within cube boundaries ... 
-	Comparing results ... 
-Reading completely outside band boundaries ... 
-	Comparing results ... 
-
-Reading partially within band boundaries ... 
-	 Reading bands 0 (should be null) and 1 (should be 1.0)... 
-		 Comparing results ... 
-	 Reading bands 4 (should be 1.0) and 5 (should be null)... 
-		 Comparing results ... 
-
-Testing reading past cube boundaries with virtual bands (2, 1, 3, 4, 2)... 
-Reading completely outside virtual band boundaries ... 
-	Comparing results starting at band 6... 
-	Comparing results starting at band 1000... 
-	Comparing results starting at band -1... 
-
-Reading partially within virtual band boundaries ... 
-Comparing results ... 
-
-Testing one line BSQ cube (where chunk dimensions == buffer shape) ... 
-Constructing cube ... 
-
-File   = IsisCube_bsqOneLine.cub
-Samps  = 3
-Lines  = 1
-Bands  = 3
-Base   = 0
-Mult   = 1
-Type   = 7
-Atchd  = 1
-Format = 0
-Open   = 1
-R/O    = 0
-R/W    = 1
-Lbytes = 65536
-
-Testing reading ascending repeating virtual bands (1, 2, 2, 3)... 
-
-Testing reading skipped ascending virtual bands (1, 3, 3)... 
-
-Testing reading outside of cube boundaries with virtual bands (1, 5)... 
-
-Testing reading descending virtual bands (3, 1, 3)... 
-
-Testing creating large BSQ where samples exceed 1GB chunk size limit ... 
-Constructing cube ... 
-
-File   = IsisCube_largebsq.cub
-Samps  = 268435457
-Lines  = 2
-Bands  = 1
-Base   = 0
-Mult   = 1
-Type   = 7
-Atchd  = 1
-Format = 0
-Open   = 1
-R/O    = 0
-R/W    = 1
-Lbytes = 65536
-
-
-Testing creating BSQ cube where size of sample pixels exceeds cube's lineCount ... 
-Constructing cube ... 
-
-File   = IsisCube_bsq.cub
-Samps  = 15000
-Lines  = 18000
-Bands  = 1
-Base   = 0
-Mult   = 1
-Type   = 7
-Atchd  = 1
-Format = 0
-Open   = 1
-R/O    = 0
-R/W    = 1
-Lbytes = 65536
-
-
-Testing errors ... 
-**PROGRAMMER ERROR** You already have a cube opened.
-**PROGRAMMER ERROR** You already have a cube opened.
-**PROGRAMMER ERROR** Cannot write to the cube [IsisCube_01.cub] because it is opened read-only.
-**I/O ERROR** Unable to open [blah].
-**PROGRAMMER ERROR** Out of array bounds [2].
-**PROGRAMMER ERROR** Out of array bounds [0].
-**PROGRAMMER ERROR** Try opening a file before you read it.
-**PROGRAMMER ERROR** Tried to write to a cube before opening/creating it.
-**PROGRAMMER ERROR** Number of samples [0], lines [0], or bands [0] cannot be less than 1.
-**I/O ERROR** Label space is full in [IsisCube_04.cub] unable to write labels.
-**USER ERROR** The cube you are attempting to create [IsisCube_05] is [33527GB]. This is larger than the current allowed size of [12GB]. The cube dimensions were (S,L,B) [1000000, 1000000, 9] with [4] bytes per pixel. If you still wish to create this cube, the maximum value can be changed in your personal preference file located in [~/.Isis/IsisPreferences] within the group CubeCustomization, keyword MaximumSize. If you do not have an ISISPreference file, please refer to the documentation 'Environment and Preference Setup'. Error.
-**PROGRAMMER ERROR** Unknown value for access [a]. Expected 'r'  or 'rw'.
-**PROGRAMMER ERROR** SetDimensions:  Invalid number of sample, lines or bands.
-**PROGRAMMER ERROR** SetDimensions:  Invalid number of sample, lines or bands.
-**PROGRAMMER ERROR** SetDimensions:  Invalid number of sample, lines or bands.
-**I/O ERROR** Failed to open [...] with read/write access.
-**ERROR** Cannot create the cube [shouldntExist.cub] with a pixel type set to None.
-**PROGRAMMER ERROR** Cannot add a group to the label of cube [IsisCube_06.cub] because it is opened read-only.
-
-Test creating an ecub
-Object = IsisCube
-  Object = Core
-    ^DnFile = $ISISTESTDATA/isis/src/base/unitTestData/isisTruth.cub
-  End_Object
-
-  Group = TestGroup
-  End_Group
-End_Object
-
-Object = Label
-  Bytes = 65536
-End_Object
-End
-0 0 0 20 20 20 39 39 39 0 20 39 0 20 39 0 20 39 
-**ERROR** The cube [isisTruth_external.ecub] does not support storing DN data because it is using an external file for DNs.
-
-Test creating an ecub from an ecub
-Object = IsisCube
-  Object = Core
-    ^DnFile = isisTruth_external.ecub
-  End_Object
-End_Object
-
-Object = Label
-  Bytes = 65536
-End_Object
-End
-0 0 0 20 20 20 39 39 39 0 20 39 0 20 39 0 20 39 
-**ERROR** The cube [isisTruth_external2.ecub] does not support storing DN data because it is using an external file for DNs.
-
-Test reading an ecub
-Object = IsisCube
-  Object = Core
-    ^DnFile = $ISISTESTDATA/isis/src/base/unitTestData/isisTruth.cub
-  End_Object
-
-  Group = TestGroup
-  End_Group
-
-  Group = TestGroup2
-  End_Group
-End_Object
-
-Object = Label
-  Bytes = 65536
-End_Object
-End
-0 0 0 20 20 20 39 39 39 0 20 39 0 20 39 0 20 39 
-**PROGRAMMER ERROR** Cannot write to the cube [isisTruth_external.ecub] because it is opened read-only.
-
-Test reading an ecub that points to another ecub
-Object = IsisCube
-  Object = Core
-    ^DnFile = isisTruth_external.ecub
-  End_Object
-End_Object
-
-Object = Label
-  Bytes = 65536
-End_Object
-End
-0 0 0 20 20 20 39 39 39 0 20 39 0 20 39 0 20 39 
-**PROGRAMMER ERROR** Cannot write to the cube [isisTruth_external2.ecub] because it is opened read-only.
diff --git a/isis/src/base/objs/Cube/unitTest_disabled.cpp b/isis/src/base/objs/Cube/unitTest_disabled.cpp
deleted file mode 100644
index d0cb588bede7c1bc6771b7d76e78dfad9f3bd43f..0000000000000000000000000000000000000000
--- a/isis/src/base/objs/Cube/unitTest_disabled.cpp
+++ /dev/null
@@ -1,1013 +0,0 @@
-/** This is free and unencumbered software released into the public domain.
-The authors of ISIS do not claim copyright on the contents of this file.
-For more details about the LICENSE terms and the AUTHORS, you will
-find files of those names at the top level of this repository. **/
-
-/* SPDX-License-Identifier: CC0-1.0 */
-#include <iostream>
-
-#include <QFileInfo>
-#include <QDebug>
-
-#include "IException.h"
-#include "Brick.h"
-#include "Cube.h"
-#include "CubeAttribute.h"
-#include "FileName.h"
-#include "LineManager.h"
-#include "Pvl.h"
-#include "Preference.h"
-#include "Histogram.h"
-#include "SpecialPixel.h"
-#include "Statistics.h"
-
-using namespace std;
-using namespace Isis;
-
-
-int main(int argc, char *argv[]) {
-  Preference::Preferences(true);
-
-  try {
-    void Report(Cube & c);
-    cerr << "Unit test for Cube" << endl;
-
-    cerr << "Constructing cube ... " << endl;
-    Cube out;
-    Report(out);
-
-    // Test create and write methods
-    cerr << "Creating 32-bit cube ... " << endl;
-    out.setDimensions(150, 200, 2);
-    out.create("$TMP/IsisCube_00");
-    Report(out);
-
-    cerr << "Write cube ... " << endl;
-    LineManager line(out);
-    long j = 0;
-    for(line.begin(); !line.end(); line++) {
-      for(int i = 0; i < line.size(); i++) {
-        line[i] = (double) j;
-        j++;
-      }
-      j--;
-      out.write(line);
-    }
-
-    // Copy returns the resulting Cube, we don't care about it (but we need it to flush) so delete
-    delete out.copy("$TMP/IsisCube_01", CubeAttributeOutput());
-    out.close();
-
-    // Test the open and read methods
-    cerr << "Opening cube ... " << endl;
-    Cube in("$TMP/IsisCube_01");
-    Report(in);
-
-    cerr << "Comparing cube ... " << endl;
-    LineManager inLine(in);
-    j = 0;
-    for(inLine.begin(); !inLine.end(); inLine++) {
-      in.read(inLine);
-      for(int i = 0; i < inLine.size(); i++) {
-        if(inLine[i] != (double) j) {
-          cerr << "Problem at"
-               << " line " << inLine.Line()
-               << " sample " << i + 1
-               << " band " << inLine.Band() << ":  "
-               << inLine[i] << " != " << double(j) << endl;
-          return 1;
-        }
-        j++;
-      }
-      j--;
-    }
-    in.close();
-    cerr << endl;
-
-    // Test other options for output
-    cerr << "Creating 8-bit cube ... " << endl;
-    Cube out2;
-    out2.setDimensions(150, 200, 1);
-    out2.setLabelsAttached(false);
-    out2.setBaseMultiplier(200.0, -1.0);
-//  out2.SetByteOrder(Msb);
-    out2.setByteOrder(ISIS_LITTLE_ENDIAN ? Msb : Lsb);
-    out2.setFormat(Cube::Bsq);
-    out2.setLabelSize(1000);
-    out2.setPixelType(UnsignedByte);
-    out2.create("$TMP/IsisCube_02");
-
-    j = 0;
-    LineManager oline(out2);
-    for(oline.begin(); !oline.end(); oline++) {
-      for(int i = 0; i < oline.size(); i++) {
-        oline[i] = (double) j;
-      }
-      out2.clearIoCache();
-      out2.write(oline);
-      j++;
-    }
-    out2.close();
-
-    cerr << "Comparing cube ... " << endl;
-    Cube in2;
-    try {
-      in2.open("$TMP/IsisCube_02");
-    }
-    catch (IException &e) {
-      e.print();
-    }
-    Report(in2);
-    j = 0;
-    LineManager inLine2(in2);
-    for(inLine2.begin(); !inLine2.end(); inLine2++) {
-      in2.read(inLine2);
-      for(int i = 0; i < inLine2.size(); i++) {
-        if(inLine2[i] != (double) j) {
-          cerr << "Problem at line " << inLine2.Line()
-               << " sample " << i + 1 << ":  "
-               << inLine2[i] << " != " << double(j) << endl;
-          return 1;
-        }
-      }
-      in2.clearIoCache();
-      j++;
-    }
-    in2.close();
-
-
-    // Test other options for output
-    cerr << "Creating 16-bit cube ... " << endl;
-    Cube out3;
-    out3.setDimensions(150, 200, 2);
-    out3.setBaseMultiplier(30000.0, -1.0);
-//  out3.SetByteOrder(Msb);
-    out2.setByteOrder(ISIS_LITTLE_ENDIAN ? Msb : Lsb);
-    out3.setPixelType(SignedWord);
-    out3.create("$TMP/IsisCube_03");
-
-    j = 0;
-    LineManager oline3(out3);
-    for(oline3.begin(); !oline3.end(); oline3++) {
-      for(int i = 0; i < oline3.size(); i++) {
-        oline3[i] = (double) j;
-        j++;
-      }
-      out3.write(oline3);
-    }
-    out3.close();
-
-    cerr << "Comparing cube ... " << endl;
-    Cube in3;
-    in3.open("$TMP/IsisCube_03");
-    Report(in3);
-    j = 0;
-    LineManager inLine3(in3);
-    for(inLine3.begin(); !inLine3.end(); inLine3++) {
-      in3.read(inLine3);
-      in3.clearIoCache();
-      for(int i = 0; i < inLine3.size(); i++) {
-        if(inLine3[i] != (double) j) {
-          cerr << "Problem at line " << inLine3.Line()
-               << " sample " << i + 1 << " band " << inLine3.Band() << ":  "
-               << inLine3[i] << " != " << double(j) << endl;
-          return 1;
-        }
-        j++;
-      }
-    }
-    in3.close();
-
-
-    in.open("$TMP/IsisCube_01");
-
-    // Test Histogram object on a single band, 1 by default
-    cerr << "Testing histogram method, band 1 ... " << endl;
-    Histogram *bandOneHist = in.histogram();
-    cerr << "Average:        " << bandOneHist->Average() << endl;
-    cerr << "Standard Dev:   " << bandOneHist->StandardDeviation() << endl;
-    cerr << "Mode:           " << bandOneHist->Mode() << endl;
-    cerr << "Total Pixels:   " << bandOneHist->TotalPixels() << endl;
-    cerr << "Null Pixels:    " << bandOneHist->NullPixels() << endl;
-    cerr << endl;
-    delete bandOneHist;
-    bandOneHist = NULL;
-
-    // Test histogram object on all bands
-    cerr << "Testing histogram method, all bands ... " << endl;
-    Histogram *allBandsHistogram = in.histogram(0);
-    cerr << "Average:        " << allBandsHistogram->Average() << endl;
-    cerr << "Standard Dev:   " << allBandsHistogram->StandardDeviation() << endl;
-    cerr << "Mode:           " << allBandsHistogram->Mode() << endl;
-    cerr << "Total Pixels:   " << allBandsHistogram->TotalPixels() << endl;
-    cerr << "Null Pixels:    " << allBandsHistogram->NullPixels() << endl;
-    cerr << endl;
-    delete allBandsHistogram;
-    allBandsHistogram = NULL;
-
-    // Check error for too few (negative) bands
-    try {
-      in.histogram(-1);
-    }
-    catch (IException &e) {
-      e.print();
-    }
-
-    // Check error for histogram object on a closed cube
-    try {
-      // out has already been closed
-      out.histogram(0);
-    }
-    catch (IException &e)
-    {
-      e.print();
-    }
-
-    cerr << endl;
-
-    // Test statistics object on a single band, 1 by default
-    cerr << "Testing statistics method, band 1 ... " << endl;
-    Statistics *bandOneStats = in.statistics();
-    cerr << "Average:        " << bandOneStats->Average() << endl;
-    cerr << "Standard Dev:   " << bandOneStats->StandardDeviation() << endl;
-    cerr << "Total Pixels:   " << bandOneStats->TotalPixels() << endl;
-    cerr << "Null Pixels:    " << bandOneStats->NullPixels() << endl;
-    cerr << endl;
-    delete bandOneStats;
-    bandOneStats = NULL;
-
-    // Test statistics object on all bands
-    cerr << "Testing statistics method, all bands ... " << endl;
-    Statistics *allBandsStats = in.statistics(0);
-    cerr << "Average:        " << allBandsStats->Average() << endl;
-    cerr << "Standard Dev:   " << allBandsStats->StandardDeviation() << endl;
-    cerr << "Total Pixels:   " << allBandsStats->TotalPixels() << endl;
-    cerr << "Null Pixels:    " << allBandsStats->NullPixels() << endl;
-    cerr << endl;
-    delete allBandsStats;
-    allBandsStats = NULL;
-
-    // Check error for too few (negative) bands
-    try {
-      in.statistics(-1);
-    }
-    catch (IException &e) {
-      e.print();
-    }
-
-    // Check error for statistics object on a closed cube
-    try {
-      // out has already been closed
-      out.statistics(0);
-    }
-    catch (IException &e)
-    {
-      e.print();
-    }
-
-    cerr << endl;
-
-    cerr << "Virtual band tests" << endl;  // Virtual Band tests
-
-    cerr << "Nbands = " << in.bandCount() << endl;
-    cerr << "Band 1 = " << in.physicalBand(1) << endl;
-    cerr << "Band 2 = " << in.physicalBand(2) << endl;
-    in.close();
-    cerr << endl;
-
-    QList<QString> vbands;
-    vbands.push_back("2");
-    in.setVirtualBands(vbands);
-    in.open("$TMP/IsisCube_01");
-    cerr << "Nbands = " << in.bandCount() << endl;
-    cerr << "Band 1 = " << in.physicalBand(1) << endl;
-    cerr << endl;
-
-    //  Test ReOpen
-    cerr << "ReOpen tests" << endl;
-    Report(in);
-    in.reopen("rw");
-    Report(in);
-    in.reopen("r");
-    Report(in);
-
-    // Test reading past cube boundaries.
-    // First create a new cube for us to test and fill it with ones.
-    cerr << "Testing reading past cube boundaries ... " << endl;
-    cerr << "Constructing cube ... " << endl << endl;
-    Cube boundaryTestCube;
-    boundaryTestCube.setDimensions(10, 10, 4);
-    boundaryTestCube.create("$TMP/IsisCube_boundary");
-    Report(boundaryTestCube);
-    LineManager boundaryLine(boundaryTestCube);
-
-    for(boundaryLine.begin(); !boundaryLine.end(); boundaryLine++) {
-      for(int i = 0; i < boundaryLine.size(); i++) {
-        boundaryLine[i] = 1.0;
-      }
-      boundaryTestCube.write(boundaryLine);
-    }
-
-    // Now read past the cube boundaries and compare the results to what we
-    // expect. All valid positions in the brick should be filled with ones since
-    // our cube is entirely filled with ones, and any parts that fall outside of
-    // the cube should be nulls.
-    cerr << "Reading completely within cube boundaries ... " << endl;
-    Brick readBrick(1, 1, 2, boundaryTestCube.pixelType());
-    readBrick.SetBasePosition(1, 1, 1);
-    boundaryTestCube.read(readBrick);
-
-    cerr << "\tComparing results ... " << endl;
-    for(int i = 0; i < readBrick.size(); i++) {
-      if (readBrick[i] != 1.0) {
-        cerr << "\tNot all values in brick were 1.0." << endl;
-        return 1;
-      }
-    }
-
-    cerr << "Reading completely outside band boundaries ... " << endl;
-    readBrick.SetBasePosition(1, 1, -1);
-    boundaryTestCube.read(readBrick);
-
-    cerr << "\tComparing results ... " << endl;
-    for(int i = 0; i < readBrick.size(); i++) {
-      if (readBrick[i] != Null) {
-        cerr << "\tNot all values in brick were Null." << endl;
-        return 1;
-      }
-    }
-    cerr << endl;
-
-    // Read before the bands start in the cube.
-    cerr << "Reading partially within band boundaries ... " << endl;
-    cerr << "\t Reading bands 0 (should be null) and 1 (should be 1.0)... " << endl;
-    cerr << "\t\t Comparing results ... " << endl;
-    readBrick.SetBasePosition(1, 1, 0);
-    boundaryTestCube.read(readBrick);
-
-    if (readBrick[0] != Null) {
-      cerr << "\t\t Value outside cube boundary was not Null." << endl;
-      return 1;
-    }
-    if (readBrick[1] != 1.0) {
-      cerr << "\t\t Value inside cube boundary was not 1.0." << endl;
-      return 1;
-    }
-
-    cerr << "\t Reading bands 4 (should be 1.0) and 5 (should be null)... " << endl;
-    cerr << "\t\t Comparing results ... " << endl;
-    // Read after the bands start in the cube.
-    readBrick.SetBasePosition(1, 1, 4);
-    boundaryTestCube.read(readBrick);
-
-    if (readBrick[0] != 1.0) {
-      cerr << "\t\t Value inside cube boundary was not 1.0." << endl;
-      return 1;
-    }
-    if (readBrick[1] != Null) {
-      cerr << "\t\t Value outside cube boundary was not Null." << endl;
-      return 1;
-    }
-    cerr << endl;
-
-    boundaryTestCube.close();
-
-    // Test reading outside a cube with virtual bands.
-    cerr << "Testing reading past cube boundaries with virtual bands (2, 1, 3, 4, 2)... " << endl;
-    QList<QString> virtualBands;
-    virtualBands.push_back("2");
-    virtualBands.push_back("1");
-    virtualBands.push_back("3");
-    virtualBands.push_back("4");
-    virtualBands.push_back("2");
-    boundaryTestCube.setVirtualBands(virtualBands);
-    boundaryTestCube.open("$TMP/IsisCube_boundary");
-
-    cerr << "Reading completely outside virtual band boundaries ... " << endl;
-    readBrick.SetBasePosition(1, 1, 6);
-    boundaryTestCube.read(readBrick);
-
-    cerr << "\tComparing results starting at band 6... " << endl;
-    for(int i = 0; i < readBrick.size(); i++) {
-      if (readBrick[i] != Null) {
-        cerr << "\tNot all values in brick (outside cube boundary) were Null. " << i << endl;
-        return 1;
-      }
-    }
-
-    cerr << "\tComparing results starting at band 1000... " << endl;
-    readBrick.SetBasePosition(1, 1, 1000);
-    boundaryTestCube.read(readBrick);
-    for(int i = 0; i < readBrick.size(); i++) {
-      if (readBrick[i] != Null) {
-        cerr << "\tNot all values in brick (outside cube boundary) were Null." << endl;
-        return 1;
-      }
-    }
-
-    cerr << "\tComparing results starting at band -1... " << endl;
-    readBrick.SetBasePosition(1, 1, -1);
-    boundaryTestCube.read(readBrick);
-    for(int i = 0; i < readBrick.size(); i++) {
-      if (readBrick[i] != Null) {
-        cerr << "Not all values in brick (outside cube boundary) were Null. " << endl;
-        return 1;
-      }
-    }
-    cerr << endl;
-
-    // Read before the bands start in the cube.
-    cerr << "Reading partially within virtual band boundaries ... " << endl;
-    readBrick.SetBasePosition(1, 1, 0);
-    boundaryTestCube.read(readBrick);
-
-    cerr << "Comparing results ... " << endl;
-    if (readBrick[0] != Null) {
-      cerr << "Value outside cube boundary (band 0) was not Null." << endl;
-      return 1;
-    }
-    if (readBrick[1] != 1.0) {
-      cerr << "Value inside cube boundary (band 1) was not 1.0." << endl;
-      return 1;
-    }
-
-    // Read after the bands start in the cube.
-    readBrick.SetBasePosition(1, 1, 5);
-    boundaryTestCube.read(readBrick);
-
-    if (readBrick[0] != 1.0) {
-      cerr << "Value inside cube boundary (band 5) was not 1.0." << endl;
-      return 1;
-    }
-    if (readBrick[1] != Null) {
-      cerr << "Value outside cube boundary (band 6) was not Null." << endl;
-      return 1;
-    }
-
-    // Resize the brick to be have many more bands than the cube, and position
-    // it before the start of the bands. We should get nulls, then some values,
-    // then more nulls.
-    readBrick.Resize(1, 1, 20);
-    readBrick.SetBasePosition(1, 1, -10);
-    boundaryTestCube.read(readBrick);
-    for (int i = 0; i < readBrick.size(); i++) {
-      if (i >= 11 && i <= 15) {
-        if (readBrick[i] != 1.0) {
-          cerr << "Value inside cube boundary, at brick band " << i + 1 << " was not 1.0." << endl;
-          return 1;
-        }
-      }
-      else {
-        if (readBrick[i] != Null) {
-          cerr << "Value outside cube boundary, at brick band " << i + 1
-               << " was not Null." << endl;
-          return 1;
-        }
-      }
-    }
-    cerr << endl;
-    boundaryTestCube.close();
-
-
-    // Test cube where its chunk size is the same as its buffer shape
-    cerr << "Testing one line BSQ cube (where chunk dimensions == buffer shape) ... " << endl;
-    cerr << "Constructing cube ... " << endl << endl;
-    Cube bsqOneLineTestCube;
-    bsqOneLineTestCube.setDimensions(3, 1, 3);
-    bsqOneLineTestCube.setFormat(Cube::Bsq);
-    bsqOneLineTestCube.create("$TMP/IsisCube_bsqOneLine");
-    Report(bsqOneLineTestCube);
-    LineManager oneLine(bsqOneLineTestCube);
-
-    // our cube will be 1, 2, 3
-    //                  2, 3, 4
-    //                  3, 4, 5
-    for (oneLine.begin(); !oneLine.end(); oneLine++) {
-      for (int i = 0; i < oneLine.size(); i++) {
-        oneLine[i] = 1 * i + oneLine.Band();
-      }
-      bsqOneLineTestCube.write(oneLine);
-    }
-    bsqOneLineTestCube.close();
-
-    // Simulate reading of an S x 1 x B cube
-    Brick readLineBrick(3, 1, 1, bsqOneLineTestCube.pixelType());
-
-    // Test reading repeated ascending virtual bands
-    cerr << "Testing reading ascending repeating virtual bands (1, 2, 2, 3)... " << endl;
-    virtualBands.clear();
-    virtualBands.push_back("1");
-    virtualBands.push_back("2");
-    virtualBands.push_back("2");
-    virtualBands.push_back("3");
-    bsqOneLineTestCube.setVirtualBands(virtualBands);
-    bsqOneLineTestCube.open("$TMP/IsisCube_bsqOneLine");
-    for (int sb = 1; sb <= virtualBands.size(); sb++) {
-      readLineBrick.SetBasePosition(1, 1, sb);
-      bsqOneLineTestCube.read(readLineBrick);
-      for (int i = 0; i < readLineBrick.size(); i++) {
-        if (readLineBrick[i] != (i + virtualBands[readLineBrick.Band()-1].toInt())) {
-          cerr << "Virtual bands accessed incorrectly at brick band "
-               << readLineBrick.Band() << endl;
-          return 1;
-        }
-      }
-    }
-    cerr << endl;
-    bsqOneLineTestCube.close();
-
-     // Test reading skipped ascending virtual bands
-    cerr << "Testing reading skipped ascending virtual bands (1, 3, 3)... " << endl;
-    virtualBands.clear();
-    virtualBands.push_back("1");
-    virtualBands.push_back("3");
-    virtualBands.push_back("3");
-    bsqOneLineTestCube.setVirtualBands(virtualBands);
-    bsqOneLineTestCube.open("$TMP/IsisCube_bsqOneLine");
-    for (int sb = 1; sb <= virtualBands.size(); sb++) {
-      readLineBrick.SetBasePosition(1, 1, sb);
-      bsqOneLineTestCube.read(readLineBrick);
-      for (int i = 0; i < readLineBrick.size(); i++) {
-        if (readLineBrick[i] != (i + virtualBands[readLineBrick.Band()-1].toInt())) {
-          cerr << "Virtual bands accessed incorrectly at virtual band "
-               << virtualBands[readLineBrick.Band() - 1] << endl;
-          return 1;
-        }
-      }
-    }
-    cerr << endl;
-    bsqOneLineTestCube.close();
-
-     // Test reading outside boundaries
-    cerr << "Testing reading outside of cube boundaries with virtual bands (1, 5)... " << endl;
-    virtualBands.clear();
-    virtualBands.push_back("1");
-    virtualBands.push_back("5");
-    bsqOneLineTestCube.setVirtualBands(virtualBands);
-    bsqOneLineTestCube.open("$TMP/IsisCube_bsqOneLine");
-    for (int sb = 1; sb <= virtualBands.size(); sb++) {
-      readLineBrick.SetBasePosition(1, 1, sb);
-      bsqOneLineTestCube.read(readLineBrick);
-      for (int i = 0; i < readLineBrick.size(); i++) {
-        if (readLineBrick.Band() == 1) {
-          if (readLineBrick[i] != (i + virtualBands[readLineBrick.Band()-1].toInt())) {
-            cerr << "Virtual bands accessed incorrectly at virtual band "
-                 << virtualBands[readLineBrick.Band() - 1] << endl;
-            return 1;
-          }
-        }
-        else {
-          if (readLineBrick[i] != Null) {
-            cerr << "Value outside cube boundary at virtual band "
-                 << virtualBands[readLineBrick.Band() - 1] << endl;
-          }
-        }
-      }
-    }
-    cerr << endl;
-    bsqOneLineTestCube.close();
-
-    // Test reading descending bands
-    cerr << "Testing reading descending virtual bands (3, 1, 3)... " << endl;
-    virtualBands.clear();
-    virtualBands.push_back("3");
-    virtualBands.push_back("1");
-    virtualBands.push_back("3");
-    bsqOneLineTestCube.setVirtualBands(virtualBands);
-    bsqOneLineTestCube.open("$TMP/IsisCube_bsqOneLine");
-    for (int sb = 1; sb <= virtualBands.size(); sb++) {
-      readLineBrick.SetBasePosition(1, 1, sb);
-      bsqOneLineTestCube.read(readLineBrick);
-      for (int i = 0; i < readLineBrick.size(); i++) {
-        if (readLineBrick[i] != (i + virtualBands[readLineBrick.Band()-1].toInt())) {
-          cerr << "Virtual bands accessed incorrectly at virtual band "
-               << virtualBands[readLineBrick.Band() - 1] << endl;
-          return 1;
-        }
-      }
-    }
-    cerr << endl;
-    bsqOneLineTestCube.close();
-
-
-    // Test creating a bsq cube that exceeds 1GB sample size limit to test CubeBsqHandler
-    cerr << "Testing creating large BSQ where samples exceed 1GB chunk size limit ... " << endl;
-    cerr << "Constructing cube ... " << endl << endl;
-    Cube largebsqTestCube;
-    // 2^28 x 2 x 1 cube -> 2^28 + 1 > 2^30 / (4*2^28), exceeds limit
-    int limitExceeded = (1 << 28) + 1;
-    largebsqTestCube.setDimensions(limitExceeded, 2, 1);
-    largebsqTestCube.setFormat(Cube::Bsq);
-    largebsqTestCube.create("$TMP/IsisCube_largebsq");
-    Report(largebsqTestCube);
-
-    cerr << endl;
-    largebsqTestCube.close();
-
-
-    // Test bsq cube that has a linecount > maximum chunk line size to test CubeBsqHandler
-    cerr << "Testing creating BSQ cube where size of sample pixels exceeds cube's lineCount ... "
-         << endl;
-    cerr << "Constructing cube ... " << endl << endl;
-    Cube bsqTestCube;
-    // maxLineSize = 2^30 / (4 * 15000) = 17895 < 18000
-    bsqTestCube.setDimensions(15000, 18000, 1);
-    bsqTestCube.setFormat(Cube::Bsq);
-    bsqTestCube.create("$TMP/IsisCube_bsq");
-    Report(bsqTestCube);
-
-    cerr << endl;
-    bsqTestCube.close();
-
-
-    // Check errors
-    cerr << "Testing errors ... " << endl;
-    try {
-      in.open("blah");
-    }
-    catch (IException &e) {
-      e.print();
-    }
-
-    try {
-      in.create("blah");
-    }
-    catch (IException &e) {
-      e.print();
-    }
-
-    try {
-      in.write(inLine3);
-    }
-    catch (IException &e) {
-      e.print();
-    }
-
-    try {
-      Cube in;
-      in.open("blah");
-    }
-    catch (IException &e) {
-      e.print();
-    }
-
-    try {
-      in.physicalBand(2);
-    }
-    catch (IException &e) {
-      e.print();
-    }
-
-    try {
-      in.physicalBand(0);
-    }
-    catch (IException &e) {
-      e.print();
-    }
-
-    try {
-      Cube in;
-      in.read(inLine3);
-    }
-    catch (IException &e) {
-      e.print();
-    }
-
-    try {
-      Cube in;
-      in.write(inLine3);
-    }
-    catch (IException &e) {
-      e.print();
-    }
-
-    try {
-      Cube out;
-      out.create("$TMP/IsisCube_04");
-      out.close();
-    }
-    catch (IException &e) {
-      e.print();
-    }
-
-    try {
-      Cube out;
-      out.setLabelSize(15);
-      out.setDimensions(1, 1, 1);
-      out.create("$TMP/IsisCube_04");
-      out.close();
-    }
-    catch (IException &e) {
-      e.print();
-    }
-
-    try {
-      Cube out;
-      out.setDimensions(1000000, 1000000, 9);
-      out.create("$TMP/IsisCube_05");
-      out.close();
-    }
-    catch (IException &e) {
-      e.print();
-    }
-    try {
-      Cube in;
-      in.open("$TMP/IsisCube_01", "a");
-    }
-    catch (IException &e) {
-      e.print();
-    }
-    try {
-      Cube in;
-      in.setDimensions(0, 0, 0);
-    }
-    catch (IException &e) {
-      e.print();
-    }
-    try {
-      Cube in;
-      in.setDimensions(1, 0, 0);
-    }
-    catch (IException &e) {
-      e.print();
-    }
-    try {
-      Cube in;
-      in.setDimensions(1, 1, 0);
-    }
-    catch (IException &e) {
-      e.print();
-    }
-
-    Cube in4;
-    try {
-      in4.open("$ISISTESTDATA/isis/src/base/unitTestData/$TMP/isisTruth.cub");
-    }
-    catch (IException &e) {
-      e.print();
-    }
-
-    try {
-      in4.reopen("rw");
-    }
-    catch (IException &e) {
-      QString error = e.toString();
-      error = error.replace(QRegExp("\\[[^\\]]*\\]"), "[...]");
-      cerr << error.toStdString() << endl;
-    }
-
-    in4.setPixelType(None);
-    try {
-      in4.setDimensions(1, 1, 1);
-      in4.create("shouldntExist.cub");
-    }
-    catch (IException &e) {
-      e.print();
-    }
-    try {
-      Cube externalData;
-      externalData.setDimensions(1024, 1024, 1);
-      externalData.create("$TMP/IsisCube_06");
-      externalData.reopen("r");
-      externalData.putGroup(PvlGroup("TestGroup2"));
-    }
-    catch (IException &e) {
-      e.print();
-    }
-  }
-  catch (IException &e) {
-    e.print();
-  }
-
-  cerr << endl << "Test creating an ecub" << endl;
-  {
-    Cube externalData;
-    externalData.setExternalDnData("$ISISTESTDATA/isis/src/base/unitTestData/$TMP/isisTruth.cub");
-    externalData.create("$TMP/isisTruth_external.ecub");
-    externalData.putGroup(PvlGroup("TestGroup"));
-    cerr << *externalData.label() << endl;
-
-    Brick readBrick(3, 3, 2, externalData.pixelType());
-    readBrick.SetBasePosition(1, 1, 1);
-    externalData.read(readBrick);
-    for (int index = 0; index < readBrick.size(); index++) {
-      if (readBrick[index] == Null) {
-        cerr << "N ";
-      }
-      else {
-        cerr << readBrick[index] << " ";
-      }
-    }
-    cerr << endl;
-
-    try {
-      externalData.write(readBrick);
-    }
-    catch (IException &e) {
-      e.print();
-    }
-  }
-
-  cerr << endl << "Test creating an ecub from an ecub" << endl;
-  {
-    Cube externalData;
-    externalData.setExternalDnData("$TMP/isisTruth_external.ecub");
-    externalData.create("$TMP/isisTruth_external2.ecub");
-    cerr << *externalData.label() << endl;
-
-    Brick readBrick(3, 3, 2, externalData.pixelType());
-    readBrick.SetBasePosition(1, 1, 1);
-    externalData.read(readBrick);
-    for (int index = 0; index < readBrick.size(); index++) {
-      if (readBrick[index] == Null) {
-        cerr << "N ";
-      }
-      else {
-        cerr << readBrick[index] << " ";
-      }
-    }
-    cerr << endl;
-
-    try {
-      externalData.write(readBrick);
-    }
-    catch (IException &e) {
-      e.print();
-    }
-  }
-
-  cerr << endl << "Test reading an ecub" << endl;
-  {
-    Cube externalData;
-    externalData.open("$TMP/isisTruth_external", "rw");
-    externalData.putGroup(PvlGroup("TestGroup2"));
-    externalData.reopen("r");
-    cerr << *externalData.label() << endl;
-
-    Brick readBrick(3, 3, 2, externalData.pixelType());
-    readBrick.SetBasePosition(1, 1, 1);
-    externalData.read(readBrick);
-    for (int index = 0; index < readBrick.size(); index++) {
-      if (readBrick[index] == Null) {
-        cerr << "N ";
-      }
-      else {
-        cerr << readBrick[index] << " ";
-      }
-    }
-    cerr << endl;
-
-    try {
-      externalData.write(readBrick);
-    }
-    catch (IException &e) {
-      e.print();
-    }
-  }
-
-  cerr << endl << "Test reading an ecub that points to another ecub" << endl;
-  {
-    Cube externalData;
-    externalData.open("$TMP/isisTruth_external2");
-    cerr << *externalData.label() << endl;
-
-    Brick readBrick(3, 3, 2, externalData.pixelType());
-    readBrick.SetBasePosition(1, 1, 1);
-    externalData.read(readBrick);
-    for (int index = 0; index < readBrick.size(); index++) {
-      if (readBrick[index] == Null) {
-        cerr << "N ";
-      }
-      else {
-        cerr << readBrick[index] << " ";
-      }
-    }
-    cerr << endl;
-
-    try {
-      externalData.write(readBrick);
-    }
-    catch (IException &e) {
-      e.print();
-    }
-  }
-
-//cerr << endl << "Test reading an ecub that points to detached lbl" << endl;
-//{
-//  Cube externalData;
-//  externalData.setExternalDnData("$TMP/IsisCube_02.lbl");
-//  externalData.create("$TMP/isisTruth_external3.ecub");
-//  cerr << *externalData.label() << endl;
-//
-//  Brick readBrick(3, 3, 2, externalData.pixelType());
-//  readBrick.SetBasePosition(1, 1, 1);
-//  externalData.read(readBrick);
-//  for (int index = 0; index < readBrick.size(); index++) {
-//    if (readBrick[index] == Null) {
-//      cerr << "N ";
-//    }
-//    else {
-//      cerr << readBrick[index] << " ";
-//    }
-//  }
-//  cerr << endl;
-//
-//  try {
-//    externalData.write(readBrick);
-//  }
-//  catch (IException &e) {
-//    e.print();
-//  }
-//}
-//
-//cerr << endl << "Test copying an ecub that points to detached lbl" << endl;
-//{
-//  Cube externalData;
-//  externalData.open("$TMP/isisTruth_external3.ecub");
-//  Cube *copiedCube = externalData.copy("$TMP/isisTruth_external3.copy.ecub",
-//                                       CubeAttributeOutput("+External"));
-//  cerr << *copiedCube->label() << endl;
-//
-//  Brick readBrick(3, 3, 2, copiedCube->pixelType());
-//  readBrick.SetBasePosition(1, 1, 1);
-//  copiedCube->read(readBrick);
-//  for (int index = 0; index < readBrick.size(); index++) {
-//    if (readBrick[index] == Null) {
-//      cerr << "N ";
-//    }
-//    else {
-//      cerr << readBrick[index] << " ";
-//    }
-//  }
-//  cerr << endl;
-//
-//  try {
-//    copiedCube->write(readBrick);
-//  }
-//  catch (IException &e) {
-//    e.print();
-//  }
-//  // need to deallocate our copied cube
-//  copiedCube->close();
-//  delete copiedCube;
-//  copiedCube = NULL;
-//
-//}
-
-  remove("$TMP/IsisCube_00.cub");
-  remove("$TMP/IsisCube_01.cub");
-  remove("$TMP/IsisCube_02.cub");
-  remove("$TMP/IsisCube_02.lbl");
-  remove("$TMP/IsisCube_03.cub");
-  remove("$TMP/IsisCube_04.cub");
-  remove("$TMP/IsisCube_05.cub");
-  remove("$TMP/IsisCube_06.cub");
-  remove("$TMP/IsisCube_boundary.cub");
-  remove("$TMP/IsisCube_bsq.cub");
-  remove("$TMP/IsisCube_bsqOneLine.cub");
-  remove("$TMP/IsisCube_largebsq.cub");
-  remove("$TMP/isisTruth_external.ecub");
-  remove("$TMP/isisTruth_external2.ecub");
-  // remove("$TMP/isisTruth_external3.ecub");
-  // remove("$TMP/isisTruth_external3.copy.ecub");
-
-  return 0;
-}
-
-
-void Report(Cube &c) {
-  cerr << "File   = " << IString(QFileInfo(c.fileName()).fileName()) << endl;
-  cerr << "Samps  = " << c.sampleCount() << endl;
-  cerr << "Lines  = " << c.lineCount() << endl;
-  cerr << "Bands  = " << c.bandCount() << endl;
-  cerr << "Base   = " << c.base() << endl;
-  cerr << "Mult   = " << c.multiplier() << endl;
-  cerr << "Type   = " << c.pixelType() << endl;
-//  cerr << "Order  = " << c.ByteOrder() << endl; // Needs to be system independent
-  cerr << "Atchd  = " << c.labelsAttached() << endl;
-  cerr << "Format = " << c.format() << endl;
-  cerr << "Open   = " << c.isOpen() << endl;
-  try {
-    cerr << "R/O    = ";
-    cerr.flush();
-    cerr << c.isReadOnly();
-  }
-  catch (IException &e) {
-    cerr << "N/A";
-  }
-
-  cerr << endl;
-
-  try {
-    cerr << "R/W    = ";
-    cerr.flush();
-    cerr << c.isReadWrite();
-  }
-  catch (IException &e) {
-    cerr << "N/A";
-  }
-
-  cerr << endl;
-  cerr << "Lbytes = " << c.labelSize() << endl;
-  cerr << endl;
-}
diff --git a/isis/tests/CubeBsqHandlerTests.cpp b/isis/tests/CubeBsqHandlerTests.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6b07c10e06e6901ee78f6fc60fd640f0078f9c6f
--- /dev/null
+++ b/isis/tests/CubeBsqHandlerTests.cpp
@@ -0,0 +1,563 @@
+#include <QFile>
+#include <QString>
+#include <iostream>
+
+#include <nlohmann/json.hpp>
+using json = nlohmann::json;
+
+#include "Brick.h"
+#include "CubeIoHandler.h"
+#include "CubeBsqHandler.h"
+#include "CubeTileHandler.h"
+#include "LineManager.h"
+#include "SpecialPixel.h"
+
+#include "CubeFixtures.h"
+#include "TestUtilities.h"
+
+#include "gmock/gmock.h"
+
+using namespace Isis;
+
+TEST_F(SmallCube, TestCubeBsqHandlerRead) {
+    QString path = testCube->fileName();
+    QFile dataFile(path);
+    if (!dataFile.open(QIODevice::ReadWrite)) {
+        FAIL() << "Unable to open dataFile in ReadWrite";
+    }
+    CubeBsqHandler ioHandler(&dataFile, nullptr, *testCube->label(), true);
+    Brick readBrick(1, 1, 2, testCube->pixelType());
+    readBrick.SetBasePosition(1, 1, 1);
+    ioHandler.read(readBrick);
+
+    EXPECT_EQ(readBrick.size(), 2);
+    EXPECT_EQ(readBrick[0], 0);
+    EXPECT_EQ(readBrick[1], 100);
+}
+
+TEST_F(SmallCube, TestCubeBsqHandlerReadPastBoundary) {
+    QString path = testCube->fileName();
+    QFile dataFile(path);
+    if (!dataFile.open(QIODevice::ReadWrite)) {
+        FAIL() << "Unable to open dataFile in ReadWrite";
+    }
+    CubeBsqHandler ioHandler(&dataFile, nullptr, *testCube->label(), true);
+    Brick readBrick(1, 1, 2, testCube->pixelType());
+    readBrick.SetBasePosition(1, 1, -1);
+    ioHandler.read(readBrick);
+
+    EXPECT_EQ(readBrick.size(), 2);
+    EXPECT_EQ(readBrick[0], NULL8);
+    EXPECT_EQ(readBrick[1], NULL8);
+}
+
+TEST_F(SmallCube, TestCubeBsqHandlerReadBeforeStart) {
+    QString path = testCube->fileName();
+    QFile dataFile(path);
+    if (!dataFile.open(QIODevice::ReadWrite)) {
+        FAIL() << "Unable to open dataFile in ReadWrite";
+    }
+    CubeBsqHandler ioHandler(&dataFile, nullptr, *testCube->label(), true);
+    Brick readBrick(1, 1, 2, testCube->pixelType());
+    readBrick.SetBasePosition(1, 1, 0);
+    ioHandler.read(readBrick);
+
+    EXPECT_EQ(readBrick.size(), 2);
+    EXPECT_EQ(readBrick[0], NULL8);
+    EXPECT_EQ(readBrick[1], 0);
+}
+
+TEST_F(SmallCube, TestCubeBsqHandlerReadAfterEnd) {
+    QString path = testCube->fileName();
+    QFile dataFile(path);
+    if (!dataFile.open(QIODevice::ReadWrite)) {
+        FAIL() << "Unable to open dataFile in ReadWrite";
+    }
+    CubeBsqHandler ioHandler(&dataFile, nullptr, *testCube->label(), true);
+    Brick readBrick(1, 1, 2, testCube->pixelType());
+    readBrick.SetBasePosition(1, 1, 10);
+    ioHandler.read(readBrick);
+
+    EXPECT_EQ(readBrick.size(), 2);
+    EXPECT_EQ(readBrick[0], 900);
+    EXPECT_EQ(readBrick[1], NULL8);
+}
+
+TEST_F(SmallCube, TestCubeBsqHandlerReadOutsideVirtualBands) {
+    QString path = testCube->fileName();
+    QFile dataFile(path);
+    if (!dataFile.open(QIODevice::ReadWrite)) {
+        FAIL() << "Unable to open dataFile in ReadWrite";
+    }
+    QList<int> virtualBands;
+    virtualBands.push_back(2);
+    virtualBands.push_back(1);
+    virtualBands.push_back(3);
+    virtualBands.push_back(4);
+    virtualBands.push_back(2);
+    CubeBsqHandler ioHandler(&dataFile, &virtualBands, *testCube->label(), true);
+    Brick readBrick(1, 1, 2, testCube->pixelType());
+    readBrick.SetBasePosition(1, 1, 6);
+    ioHandler.read(readBrick);
+
+    EXPECT_EQ(readBrick.size(), 2);
+    EXPECT_EQ(readBrick[0], NULL8);
+    EXPECT_EQ(readBrick[1], NULL8);
+
+    readBrick.SetBasePosition(1, 1, 1000);
+    ioHandler.read(readBrick);
+
+    EXPECT_EQ(readBrick[0], NULL8);
+    EXPECT_EQ(readBrick[1], NULL8);
+
+
+    readBrick.SetBasePosition(1, 1, -1);
+    ioHandler.read(readBrick);
+
+    EXPECT_EQ(readBrick[0], NULL8);
+    EXPECT_EQ(readBrick[1], NULL8);
+}
+
+TEST_F(SmallCube, TestCubeBsqHandlerReadEdgeVirtualBands) {
+    QString path = testCube->fileName();
+    QFile dataFile(path);
+    if (!dataFile.open(QIODevice::ReadWrite)) {
+        FAIL() << "Unable to open dataFile in ReadWrite";
+    }
+    QList<int> virtualBands;
+    virtualBands.push_back(2);
+    virtualBands.push_back(1);
+    virtualBands.push_back(3);
+    virtualBands.push_back(4);
+    virtualBands.push_back(2);
+    CubeBsqHandler ioHandler(&dataFile, &virtualBands, *testCube->label(), true);
+    Brick readBrick(1, 1, 2, testCube->pixelType());
+    readBrick.SetBasePosition(1, 1, 0);
+    ioHandler.read(readBrick);
+
+    EXPECT_EQ(readBrick.size(), 2);
+    EXPECT_EQ(readBrick[0], NULL8);
+    EXPECT_EQ(readBrick[1], 100);
+
+    readBrick.SetBasePosition(1, 1, 5);
+    ioHandler.read(readBrick);
+
+    EXPECT_EQ(readBrick.size(), 2);
+    EXPECT_EQ(readBrick[0], 100);
+    EXPECT_EQ(readBrick[1], NULL8);
+}
+
+TEST_F(SmallCube, TestCubeBsqHandlerReadVirtualBands) {
+    QString path = testCube->fileName();
+    QFile dataFile(path);
+    if (!dataFile.open(QIODevice::ReadWrite)) {
+        FAIL() << "Unable to open dataFile in ReadWrite";
+    }
+    QList<int> virtualBands;
+    virtualBands.push_back(2);
+    virtualBands.push_back(1);
+    virtualBands.push_back(3);
+    virtualBands.push_back(4);
+    virtualBands.push_back(2);
+    virtualBands.push_back(2);
+    virtualBands.push_back(1);
+    virtualBands.push_back(3);
+    virtualBands.push_back(4);
+    virtualBands.push_back(2);
+    CubeBsqHandler ioHandler(&dataFile, &virtualBands, *testCube->label(), true);
+    Brick readBrick(1, 1, 20, testCube->pixelType());
+    readBrick.SetBasePosition(1, 1, -4);
+    ioHandler.read(readBrick);
+
+    EXPECT_EQ(readBrick.size(), 20);
+    for (int i = 0; i < 5; i++) {
+        EXPECT_EQ(readBrick[i], NULL8);
+    }
+    EXPECT_EQ(readBrick[5], 100);
+    EXPECT_EQ(readBrick[6], 0);
+    EXPECT_EQ(readBrick[7], 200);
+    EXPECT_EQ(readBrick[8], 300);
+    EXPECT_EQ(readBrick[9], 100);
+    EXPECT_EQ(readBrick[10], 100);
+    EXPECT_EQ(readBrick[11], 0);
+    EXPECT_EQ(readBrick[12], 200);
+    EXPECT_EQ(readBrick[13], 300);
+    EXPECT_EQ(readBrick[14], 100);
+    for (int i = 15; i < 20; i++) {
+        EXPECT_EQ(readBrick[i], NULL8);
+    }
+}
+
+class BsqCube : public TempTestingFiles {
+    protected:
+      Cube *testCube;
+
+        void SetUp() override {
+            TempTestingFiles::SetUp();
+
+            testCube = new Cube();
+            testCube->setDimensions(3, 1, 3);
+            testCube->setFormat(Cube::Bsq);
+            QString path = tempDir.path() + "/small.cub";
+            testCube->create(path);
+
+            LineManager line(*testCube);
+            // our cube will be 1, 2, 3
+            //                  2, 3, 4
+            //                  3, 4, 5
+            for (line.begin(); !line.end(); line++) {
+                for (int i = 0; i < line.size(); i++) {
+                    line[i] = 1 * i + line.Band();
+                }
+                testCube->write(line);
+            }
+
+            // Add a BandBin group to the cube label
+            Pvl *label = testCube->label();
+            PvlObject& cubeLabel = label->findObject("IsisCube");
+            PvlGroup bandBin("BandBin");
+            PvlKeyword originalBand("OriginalBand", "1");
+            originalBand += "2";
+            originalBand += "3";
+            bandBin += originalBand;
+            cubeLabel.addGroup(bandBin);
+            testCube->close();
+            testCube->open(path, "rw");
+    }
+
+      void TearDown() override {
+        if (testCube->isOpen()) {
+            testCube->close();
+        }
+
+        if (testCube) {
+            delete testCube;
+        }
+    }
+};
+
+TEST_F(BsqCube, TestCubeBsqHandlerReadRepeatedAscendingVBands) {
+    QString path = testCube->fileName();
+    QFile dataFile(path);
+    if (!dataFile.open(QIODevice::ReadWrite)) {
+        FAIL() << "Unable to open dataFile in ReadWrite";
+    }
+    QList<int> virtualBands;
+    virtualBands.push_back(1);
+    virtualBands.push_back(2);
+    virtualBands.push_back(2);
+    virtualBands.push_back(3);
+    CubeBsqHandler ioHandler(&dataFile, &virtualBands, *testCube->label(), true);
+    Brick readBrick(3, 1, 1, testCube->pixelType());
+
+    for (int sb = 1; sb <= virtualBands.size(); sb++) {
+      readBrick.SetBasePosition(1, 1, sb);
+      ioHandler.read(readBrick);
+      for (int i = 0; i < readBrick.size(); i++) {
+        EXPECT_EQ(readBrick[i], (i + virtualBands[readBrick.Band()-1]));
+      }
+    }
+}
+
+TEST_F(BsqCube, TestCubeBsqHandlerReadSkippedAscendingVBands) {
+    QString path = testCube->fileName();
+    QFile dataFile(path);
+    if (!dataFile.open(QIODevice::ReadWrite)) {
+        FAIL() << "Unable to open dataFile in ReadWrite";
+    }
+    QList<int> virtualBands;
+    virtualBands.push_back(1);
+    virtualBands.push_back(3);
+    virtualBands.push_back(3);
+    CubeBsqHandler ioHandler(&dataFile, &virtualBands, *testCube->label(), true);
+    Brick readBrick(3, 1, 1, testCube->pixelType());
+
+    for (int sb = 1; sb <= virtualBands.size(); sb++) {
+        readBrick.SetBasePosition(1, 1, sb);
+        ioHandler.read(readBrick);
+        for (int i = 0; i < readBrick.size(); i++) {
+            EXPECT_EQ(readBrick[i], (i + virtualBands[readBrick.Band()-1]));
+        }
+    }
+}
+
+TEST_F(BsqCube, TestCubeBsqHandlerReadOutOfBoundsVBands) {
+    QString path = testCube->fileName();
+    QFile dataFile(path);
+    if (!dataFile.open(QIODevice::ReadWrite)) {
+        FAIL() << "Unable to open dataFile in ReadWrite";
+    }
+    QList<int> virtualBands;
+    virtualBands.push_back(1);
+    virtualBands.push_back(5);
+    CubeBsqHandler ioHandler(&dataFile, &virtualBands, *testCube->label(), true);
+    Brick readBrick(3, 1, 1, testCube->pixelType());
+    for (int sb = 1; sb <= virtualBands.size(); sb++) {
+        for (int i = 0; i < readBrick.size(); i++) {
+            readBrick.SetBasePosition(1, 1, sb);
+            ioHandler.read(readBrick);
+            if (readBrick.Band() == 1) {
+                EXPECT_EQ(readBrick[i], (i + virtualBands[readBrick.Band()-1]));
+            }
+            else {
+                EXPECT_EQ(readBrick[i], Null);
+            }
+        }
+    }
+}
+
+TEST_F(BsqCube, TestCubeBsqHandlerReadDescendingVBands) {
+    QString path = testCube->fileName();
+    QFile dataFile(path);
+    if (!dataFile.open(QIODevice::ReadWrite)) {
+        FAIL() << "Unable to open dataFile in ReadWrite";
+    }
+    QList<int> virtualBands;
+    virtualBands.push_back(3);
+    virtualBands.push_back(1);
+    virtualBands.push_back(3);
+    CubeBsqHandler ioHandler(&dataFile, &virtualBands, *testCube->label(), true);
+    Brick readBrick(3, 1, 1, testCube->pixelType());
+
+    for (int sb = 1; sb <= virtualBands.size(); sb++) {
+        readBrick.SetBasePosition(1, 1, sb);
+        ioHandler.read(readBrick);
+        for (int i = 0; i < readBrick.size(); i++) {
+            EXPECT_EQ(readBrick[i], (i + virtualBands[readBrick.Band()-1]));
+        }
+    }
+}
+
+TEST_F(TempTestingFiles, TestCubeBsqHandlerExceedSampleSizeLimit) {
+    std::istringstream labelStrm(R"(
+    Object = IsisCube
+        Object = Core
+            StartByte   = 65537
+            Format      = Bsq
+
+            Group = Dimensions
+                Samples = 268435457
+                Lines   = 2
+                Bands   = 1
+            End_Group
+
+            Group = Pixels
+                Type       = Real
+                ByteOrder  = Lsb
+                Base       = 0.0
+                Multiplier = 1.0
+            End_Group
+        End_Object
+
+        Group = Instrument
+            SpacecraftName       = VIKING_ORBITER_1
+            InstrumentId         = VISUAL_IMAGING_SUBSYSTEM_CAMERA_B
+            TargetName           = MARS
+            StartTime            = 1977-07-09T20:05:51
+            ExposureDuration     = 0.008480 <seconds>
+            SpacecraftClockCount = 33322515
+            FloodModeId          = ON
+            GainModeId           = HIGH
+            OffsetModeId         = ON
+        End_Group
+
+        Group = Archive
+            DataSetId       = VO1/VO2-M-VIS-2-EDR-V2.0
+            ProductId       = 387A06
+            MissonPhaseName = EXTENDED_MISSION
+            ImageNumber     = 33322515
+            OrbitNumber     = 387
+        End_Group
+
+        Group = BandBin
+            FilterName = CLEAR
+            FilterId   = 4
+        End_Group
+
+        Group = Kernels
+            NaifFrameCode             = -27002
+            LeapSecond                = $base/kernels/lsk/naif0012.tls
+            TargetAttitudeShape       = $base/kernels/pck/pck00009.tpc
+            TargetPosition            = (Table, $base/kernels/spk/de430.bsp,
+                                        $base/kernels/spk/mar097.bsp)
+            InstrumentPointing        = (Table, $viking1/kernels/ck/vo1_sedr_ck2.bc,
+                                        $viking1/kernels/fk/vo1_v10.tf)
+            Instrument                = Null
+            SpacecraftClock           = ($viking1/kernels/sclk/vo1_fict.tsc,
+                                        $viking1/kernels/sclk/vo1_fsc.tsc)
+            InstrumentPosition        = (Table, $viking1/kernels/spk/viking1a.bsp)
+            InstrumentAddendum        = $viking1/kernels/iak/vikingAddendum003.ti
+            ShapeModel                = $base/dems/molaMarsPlanetaryRadius0005.cub
+            InstrumentPositionQuality = Reconstructed
+            InstrumentPointingQuality = Reconstructed
+            CameraVersion             = 1
+        End_Group
+
+        Group = Reseaus
+            Line     = (5, 6, 8, 9, 10, 11, 12, 13, 14, 14, 15, 133, 134, 135, 137,
+                        138, 139, 140, 141, 141, 142, 143, 144, 263, 264, 266, 267,
+                        268, 269, 269, 270, 271, 272, 273, 393, 393, 395, 396, 397,
+                        398, 399, 399, 400, 401, 402, 403, 523, 524, 525, 526, 527,
+                        527, 528, 529, 530, 530, 532, 652, 652, 654, 655, 656, 657,
+                        657, 658, 659, 660, 661, 662, 781, 783, 784, 785, 786, 787,
+                        788, 788, 789, 790, 791, 911, 912, 913, 914, 915, 916, 917,
+                        918, 918, 919, 920, 921, 1040, 1041, 1043, 1044, 1045, 1045,
+                        1046, 1047, 1047, 1048, 1050)
+            Sample   = (24, 142, 259, 375, 491, 607, 723, 839, 954, 1070, 1185, 24,
+                        84, 201, 317, 433, 549, 665, 780, 896, 1011, 1127, 1183, 25,
+                        142, 259, 375, 492, 607, 722, 838, 953, 1068, 1183, 25, 84,
+                        201, 317, 433, 549, 665, 779, 895, 1010, 1125, 1182, 25, 143,
+                        259, 375, 491, 607, 722, 837, 952, 1067, 1182, 25, 84, 201,
+                        317, 433, 548, 664, 779, 894, 1009, 1124, 1181, 25, 142, 258,
+                        374, 490, 605, 720, 835, 951, 1066, 1180, 24, 83, 200, 316,
+                        431, 547, 662, 776, 892, 1007, 1122, 1179, 23, 140, 257, 373,
+                        488, 603, 718, 833, 948, 1063, 1179)
+            Type     = (1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+                        5, 6, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 4, 5, 5, 5, 5, 5, 5, 5,
+                        5, 5, 5, 6, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 4, 5, 5, 5, 5, 5,
+                        5, 5, 5, 5, 5, 6, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 4, 5, 5, 5,
+                        5, 5, 5, 5, 5, 5, 5, 6, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6)
+            Valid    = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+            Template = $viking1/reseaus/vo1.visb.template.cub
+            Status   = Nominal
+        End_Group
+    End_Object
+    End
+    )");
+
+    Pvl label;
+    labelStrm >> label;
+
+    QString path = tempDir.path() + "/test_cube.cub";
+    QFile dataFile(path);
+    if (!dataFile.open(QIODevice::Truncate | QIODevice::ReadWrite)) {
+        FAIL() << "Unable to open dataFile in ReadWrite";
+    }
+
+    CubeBsqHandler ioHandler(&dataFile, nullptr, label, false);
+    EXPECT_EQ(ioHandler.getBytesPerChunk(), 1073741828);
+    EXPECT_EQ(ioHandler.getChunkCountInSampleDimension(), 1);
+    EXPECT_EQ(ioHandler.getSampleCountInChunk(), 268435457);
+    EXPECT_EQ(ioHandler.getLineCountInChunk(), 1);
+}
+
+TEST_F(TempTestingFiles, TestCubeBsqHandlerExceedMaximumChunkLineSize) {
+    std::istringstream labelStrm(R"(
+    Object = IsisCube
+        Object = Core
+            StartByte   = 65537
+            Format      = Bsq
+
+            Group = Dimensions
+                Samples = 15000
+                Lines   = 18000
+                Bands   = 1
+            End_Group
+
+            Group = Pixels
+                Type       = Real
+                ByteOrder  = Lsb
+                Base       = 0.0
+                Multiplier = 1.0
+            End_Group
+        End_Object
+
+        Group = Instrument
+            SpacecraftName       = VIKING_ORBITER_1
+            InstrumentId         = VISUAL_IMAGING_SUBSYSTEM_CAMERA_B
+            TargetName           = MARS
+            StartTime            = 1977-07-09T20:05:51
+            ExposureDuration     = 0.008480 <seconds>
+            SpacecraftClockCount = 33322515
+            FloodModeId          = ON
+            GainModeId           = HIGH
+            OffsetModeId         = ON
+        End_Group
+
+        Group = Archive
+            DataSetId       = VO1/VO2-M-VIS-2-EDR-V2.0
+            ProductId       = 387A06
+            MissonPhaseName = EXTENDED_MISSION
+            ImageNumber     = 33322515
+            OrbitNumber     = 387
+        End_Group
+
+        Group = BandBin
+            FilterName = CLEAR
+            FilterId   = 4
+        End_Group
+
+        Group = Kernels
+            NaifFrameCode             = -27002
+            LeapSecond                = $base/kernels/lsk/naif0012.tls
+            TargetAttitudeShape       = $base/kernels/pck/pck00009.tpc
+            TargetPosition            = (Table, $base/kernels/spk/de430.bsp,
+                                        $base/kernels/spk/mar097.bsp)
+            InstrumentPointing        = (Table, $viking1/kernels/ck/vo1_sedr_ck2.bc,
+                                        $viking1/kernels/fk/vo1_v10.tf)
+            Instrument                = Null
+            SpacecraftClock           = ($viking1/kernels/sclk/vo1_fict.tsc,
+                                        $viking1/kernels/sclk/vo1_fsc.tsc)
+            InstrumentPosition        = (Table, $viking1/kernels/spk/viking1a.bsp)
+            InstrumentAddendum        = $viking1/kernels/iak/vikingAddendum003.ti
+            ShapeModel                = $base/dems/molaMarsPlanetaryRadius0005.cub
+            InstrumentPositionQuality = Reconstructed
+            InstrumentPointingQuality = Reconstructed
+            CameraVersion             = 1
+        End_Group
+
+        Group = Reseaus
+            Line     = (5, 6, 8, 9, 10, 11, 12, 13, 14, 14, 15, 133, 134, 135, 137,
+                        138, 139, 140, 141, 141, 142, 143, 144, 263, 264, 266, 267,
+                        268, 269, 269, 270, 271, 272, 273, 393, 393, 395, 396, 397,
+                        398, 399, 399, 400, 401, 402, 403, 523, 524, 525, 526, 527,
+                        527, 528, 529, 530, 530, 532, 652, 652, 654, 655, 656, 657,
+                        657, 658, 659, 660, 661, 662, 781, 783, 784, 785, 786, 787,
+                        788, 788, 789, 790, 791, 911, 912, 913, 914, 915, 916, 917,
+                        918, 918, 919, 920, 921, 1040, 1041, 1043, 1044, 1045, 1045,
+                        1046, 1047, 1047, 1048, 1050)
+            Sample   = (24, 142, 259, 375, 491, 607, 723, 839, 954, 1070, 1185, 24,
+                        84, 201, 317, 433, 549, 665, 780, 896, 1011, 1127, 1183, 25,
+                        142, 259, 375, 492, 607, 722, 838, 953, 1068, 1183, 25, 84,
+                        201, 317, 433, 549, 665, 779, 895, 1010, 1125, 1182, 25, 143,
+                        259, 375, 491, 607, 722, 837, 952, 1067, 1182, 25, 84, 201,
+                        317, 433, 548, 664, 779, 894, 1009, 1124, 1181, 25, 142, 258,
+                        374, 490, 605, 720, 835, 951, 1066, 1180, 24, 83, 200, 316,
+                        431, 547, 662, 776, 892, 1007, 1122, 1179, 23, 140, 257, 373,
+                        488, 603, 718, 833, 948, 1063, 1179)
+            Type     = (1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+                        5, 6, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 4, 5, 5, 5, 5, 5, 5, 5,
+                        5, 5, 5, 6, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 4, 5, 5, 5, 5, 5,
+                        5, 5, 5, 5, 5, 6, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 4, 5, 5, 5,
+                        5, 5, 5, 5, 5, 5, 5, 6, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6)
+            Valid    = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+            Template = $viking1/reseaus/vo1.visb.template.cub
+            Status   = Nominal
+        End_Group
+    End_Object
+    End
+    )");
+
+    Pvl label;
+    labelStrm >> label;
+
+    QString path = tempDir.path() + "/test_cube.cub";
+    QFile dataFile(path);
+    if (!dataFile.open(QIODevice::Truncate | QIODevice::ReadWrite)) {
+        FAIL() << "Unable to open dataFile in ReadWrite";
+    }
+
+    CubeBsqHandler ioHandler(&dataFile, nullptr, label, false);
+    EXPECT_EQ(ioHandler.getBytesPerChunk(), 540000000);
+    EXPECT_EQ(ioHandler.getChunkCountInSampleDimension(), 1);
+    EXPECT_EQ(ioHandler.getSampleCountInChunk(), 15000);
+    EXPECT_EQ(ioHandler.getLineCountInChunk(), 9000);
+}
\ No newline at end of file
diff --git a/isis/tests/CubeTests.cpp b/isis/tests/CubeTests.cpp
index 91348eb305f4957e5c0062e2ccfb3f478f80099b..7f14bb1c925941dc345dcae467f42521bf39555e 100644
--- a/isis/tests/CubeTests.cpp
+++ b/isis/tests/CubeTests.cpp
@@ -6,8 +6,13 @@
 using json = nlohmann::json;
 
 #include "Blob.h"
-#include "Cube.h"
+#include "Brick.h"
 #include "Camera.h"
+#include "Cube.h"
+#include "CubeAttribute.h"
+#include "Histogram.h"
+#include "LineManager.h"
+#include "Statistics.h"
 
 #include "CubeFixtures.h"
 #include "TestUtilities.h"
@@ -16,6 +21,38 @@ using json = nlohmann::json;
 
 using namespace Isis;
 
+
+void check_cube(Cube &cube,
+                QString &file, 
+                int sampleCount, 
+                int lineCount, 
+                int bandCount, 
+                double base, 
+                double multiplier, 
+                int pixelType, 
+                bool attached, 
+                int format,
+                int isOpen,
+                int isReadOnly,
+                int isReadWrite,
+                int labelSize) {
+  EXPECT_EQ(cube.fileName().toStdString(), file.toStdString());
+  EXPECT_EQ(cube.sampleCount(), sampleCount);
+  EXPECT_EQ(cube.lineCount(), lineCount);
+  EXPECT_EQ(cube.bandCount(), bandCount);
+  EXPECT_EQ(cube.base(), base);
+  EXPECT_EQ(cube.multiplier(), multiplier);
+  EXPECT_EQ(cube.pixelType(), pixelType);
+  EXPECT_EQ(cube.labelsAttached(), attached);
+  EXPECT_EQ(cube.format(), format);
+  EXPECT_EQ(cube.isOpen(), isOpen);
+  if (cube.isOpen()) {
+    EXPECT_EQ(cube.isReadOnly(), isReadOnly);
+    EXPECT_EQ(cube.isReadWrite(), isReadWrite);
+  }
+  EXPECT_EQ(cube.labelSize(), labelSize);
+}
+
 TEST(CubeTest, TestCubeAttachSpiceFromIsd) {
   std::istringstream labelStrm(R"(
     Object = IsisCube
@@ -239,3 +276,587 @@ TEST_F(SmallCube, TestCubeHasBlob) {
   EXPECT_TRUE(testCube->hasBlob("TestBlob", "SomeBlob"));
   EXPECT_FALSE(testCube->hasBlob("SomeOtherTestBlob", "SomeBlob"));
 }
+
+TEST_F(TempTestingFiles, TestCubeCreateWriteCopy) {
+  Cube out;
+  QString file = "";
+  check_cube(out, file, 0, 0, 0, 0, 1, 7, 1, 1, 0, 0, 0, 65536);
+  out.setDimensions(150, 200, 2);
+  file = QString(tempDir.path() + "/IsisCube_00.cub");
+  out.create(file);
+  check_cube(out, file, 150, 200, 2, 0, 1, 7, 1, 1, 1, 0, 1, 65536);
+
+  LineManager line(out);
+  long j = 0;
+  for(line.begin(); !line.end(); line++) {
+    for(int i = 0; i < line.size(); i++) {
+      line[i] = (double) j;
+      j++;
+    }
+    j--;
+    out.write(line);
+  }
+
+  // Copy returns the resulting Cube, we don't care about it (but we need it to flush) so delete
+  QString file2 = tempDir.path() + "/IsisCube_01.cub";
+  delete out.copy(file2, CubeAttributeOutput());
+  out.close();
+
+  // Test the open and read methods
+  Cube in(file2);
+  check_cube(in, file2, 150, 200, 2, 0, 1, 7, 1, 1, 1, 1, 0, 6563);
+
+  LineManager inLine(in);
+  j = 0;
+  for(inLine.begin(); !inLine.end(); inLine++) {
+    in.read(inLine);
+    for(int i = 0; i < inLine.size(); i++) {
+      EXPECT_NEAR(inLine[i], (double) j, 1e-15);
+      j++;
+    }
+    j--;
+  }
+  in.close();
+}
+
+TEST_F(TempTestingFiles, TestCubeCreateWrite8bit) {
+  Cube out;
+  QString file = "";
+  check_cube(out, file, 0, 0, 0, 0, 1, 7, 1, 1, 0, 0, 0, 65536);
+  out.setDimensions(150, 200, 1);
+  out.setLabelsAttached(0);
+  out.setBaseMultiplier(200.0, -1.0);
+  out.setByteOrder(ISIS_LITTLE_ENDIAN ? Msb : Lsb);
+  out.setFormat(Cube::Bsq);
+  out.setLabelSize(1000);
+  out.setPixelType(UnsignedByte);
+  check_cube(out, file, 150, 200, 1, 200, -1, 1, 0, 0, 0, 0, 0, 1000);
+  file = QString(tempDir.path() + "/IsisCube_00.cub");
+  out.create(file);
+
+  long j = 0;
+  LineManager oline(out);
+  for(oline.begin(); !oline.end(); oline++) {
+    for(int i = 0; i < oline.size(); i++) {
+      oline[i] = (double) j;
+    }
+    out.clearIoCache();
+    out.write(oline);
+    j++;
+  }
+  out.close();
+
+  Cube in;
+  file = QString(tempDir.path() + "/IsisCube_00.lbl");
+  try {
+    in.open(file);
+  }
+  catch (IException &e) {
+    e.print();
+  }
+  check_cube(in, file, 150, 200, 1, 200, -1, 1, 0, 0, 1, 1, 0, 419);
+  j = 0;
+  LineManager inLine(in);
+  for(inLine.begin(); !inLine.end(); inLine++) {
+    in.read(inLine );
+    for(int i = 0; i < inLine.size(); i++) {
+      EXPECT_NEAR(inLine[i], (double) j, 1e-15);
+    }
+    in.clearIoCache();
+    j++;
+  }
+  in.close();
+}
+
+TEST_F(TempTestingFiles, TestCubeCreateWrite16bit) {
+  Cube out;
+  QString file = "";
+  check_cube(out, file, 0, 0, 0, 0, 1, 7, 1, 1, 0, 0, 0, 65536);
+  out.setDimensions(150, 200, 2);
+  out.setBaseMultiplier(30000.0, -1.0);
+  out.setByteOrder(ISIS_LITTLE_ENDIAN ? Msb : Lsb);
+  out.setPixelType(SignedWord);
+  check_cube(out, file, 150, 200, 2, 30000, -1, 4, 1, 1, 0, 0, 0, 65536);
+  file = QString(tempDir.path() + "/IsisCube.cub");
+  out.create(file);
+
+  long j = 0;
+  LineManager oline(out);
+  for(oline.begin(); !oline.end(); oline++) {
+    for(int i = 0; i < oline.size(); i++) {
+      oline[i] = (double) j;
+    }
+    out.clearIoCache();
+    out.write(oline);
+    j++;
+  }
+  out.close();
+
+  Cube in;
+  try {
+    in.open(file);
+  }
+  catch (IException &e) {
+    e.print();
+  }
+  check_cube(in, file, 150, 200, 2, 30000, -1, 4, 1, 1, 1, 1, 0, 65536);
+  j = 0;
+  LineManager inLine(in);
+  for(inLine.begin(); !inLine.end(); inLine++) {
+    in.read(inLine );
+    for(int i = 0; i < inLine.size(); i++) {
+      EXPECT_NEAR(inLine[i], (double) j, 1e-15);
+    }
+    in.clearIoCache();
+    j++;
+  }
+  in.close();
+}
+
+TEST_F(SmallCube, TestCubeHistorgramBand1) {
+  Histogram *bandHist = testCube->histogram(1);
+  EXPECT_DOUBLE_EQ(bandHist->Average(), 49.5);
+  EXPECT_DOUBLE_EQ(bandHist->StandardDeviation(), 29.011491975882016);
+  EXPECT_DOUBLE_EQ(bandHist->Mode(), 0);
+  EXPECT_DOUBLE_EQ(bandHist->TotalPixels(), 100);
+  EXPECT_DOUBLE_EQ(bandHist->NullPixels(), 0);
+  delete bandHist;
+}
+
+TEST_F(SmallCube, TestCubeHistorgramAll) {
+  Histogram *bandHist = testCube->histogram(0);
+  EXPECT_DOUBLE_EQ(bandHist->Average(), 499.5);
+  EXPECT_DOUBLE_EQ(bandHist->StandardDeviation(), 288.81943609574938);
+  EXPECT_DOUBLE_EQ(bandHist->Mode(), 0);
+  EXPECT_DOUBLE_EQ(bandHist->TotalPixels(), 1000);
+  EXPECT_DOUBLE_EQ(bandHist->NullPixels(), 0);
+  delete bandHist;
+}
+
+TEST_F(SmallCube, TestCubeStatisticsBand1) {
+  Statistics *bandHist = testCube->statistics(1);
+  EXPECT_DOUBLE_EQ(bandHist->Average(), 49.5);
+  EXPECT_DOUBLE_EQ(bandHist->StandardDeviation(), 29.011491975882016);
+  EXPECT_DOUBLE_EQ(bandHist->TotalPixels(), 100);
+  EXPECT_DOUBLE_EQ(bandHist->NullPixels(), 0);
+  delete bandHist;
+}
+
+TEST_F(SmallCube, TestCubeStatisticsAll) {
+  Statistics *bandHist = testCube->statistics(0);
+  EXPECT_DOUBLE_EQ(bandHist->Average(), 499.5);
+  EXPECT_DOUBLE_EQ(bandHist->StandardDeviation(), 288.81943609574938);
+  EXPECT_DOUBLE_EQ(bandHist->TotalPixels(), 1000);
+  EXPECT_DOUBLE_EQ(bandHist->NullPixels(), 0);
+  delete bandHist;
+}
+
+TEST_F(SmallCube, TestCubeNegativeHistStatsBand) {
+  try {
+    testCube->histogram(-1);
+    FAIL() << "Expected an exception to be thrown";
+  }
+  catch (IException &e) {
+    EXPECT_TRUE(e.toString().toLatin1().contains("Invalid band in [CubeInfo::Histogram]"))
+      << e.toString().toStdString();
+  }
+
+  try {
+    testCube->statistics(-1);
+    FAIL() << "Expected an exception to be thrown";
+  }
+  catch (IException &e) {
+    EXPECT_TRUE(e.toString().toLatin1().contains("Invalid band in [CubeInfo::Statistics]"))
+      << e.toString().toStdString();
+  }
+}
+
+TEST(CubeTest, TestCubeNoHistStats) {
+  Cube cube;
+  try {
+    cube.histogram();
+    FAIL() << "Expected an exception to be thrown";
+  }
+  catch (IException &e) {
+    EXPECT_TRUE(e.toString().toLatin1().contains("Cannot create histogram object for an unopened cube"))
+      << e.toString().toStdString();
+  }
+
+  try {
+    cube.statistics();
+    FAIL() << "Expected an exception to be thrown";
+  }
+  catch (IException &e) {
+    EXPECT_TRUE(e.toString().toLatin1().contains("Cannot create statistics object for an unopened cube"))
+      << e.toString().toStdString();
+  }
+}
+
+TEST_F(SmallCube, TestCubePhyscialBands) {
+  EXPECT_EQ(testCube->bandCount(), 10);
+  for (int i = 0; i < testCube->bandCount(); i++) {
+    EXPECT_EQ(testCube->physicalBand(i), i);
+  }
+}
+
+TEST_F(SmallCube, TestCubeVirutalBands) {
+  QString path = testCube->fileName();
+  testCube->close();
+  QList<QString> vbands = {"2", "3", "4", "5", "6", "7", "8", "9", "10"};
+  testCube->setVirtualBands(vbands);
+  testCube->open(path);
+  EXPECT_EQ(testCube->bandCount(), 9);
+  for (int i = 1; i < vbands.size() + 1; i++) {
+    EXPECT_EQ(testCube->physicalBand(i), i + 1);
+  }
+}
+
+TEST_F(SmallCube, TestCubeReopenRW) {
+  QString path = testCube->fileName();
+  check_cube(*testCube, path, 10, 10, 10, 0, 1, 7, 1, 1, 1, 0, 1, 65536);
+  testCube->reopen("rw");
+  check_cube(*testCube, path, 10, 10, 10, 0, 1, 7, 1, 1, 1, 0, 1, 65536);
+}
+
+TEST_F(SmallCube, TestCubeReopenR) {
+  QString path = testCube->fileName();
+  check_cube(*testCube, path, 10, 10, 10, 0, 1, 7, 1, 1, 1, 0, 1, 65536);
+  testCube->reopen("r");
+  check_cube(*testCube, path, 10, 10, 10, 0, 1, 7, 1, 1, 1, 1, 0, 65536);
+}
+
+TEST_F(SmallCube, TestCubeAlreadyOpenOpen) {
+  try {
+    testCube->open("blah");
+    FAIL() << "Expected an exception to be thrown";
+  }
+  catch(IException &e) {
+    EXPECT_TRUE(e.toString().toLatin1().contains("You already have a cube opened."))
+      << e.toString().toStdString();
+  }
+}
+
+TEST_F(SmallCube, TestCubeAlreadyOpenCreate) {
+  try {
+    testCube->create("blah");
+    FAIL() << "Expected an exception to be thrown";
+  }
+  catch(IException &e) {
+    EXPECT_TRUE(e.toString().toLatin1().contains("You already have a cube opened."))
+      << e.toString().toStdString();
+  }
+}
+
+TEST_F(TempTestingFiles, TestCubeWriteToReadOnly) {
+  Cube testCube;
+  QString file = QString(tempDir.path() + "/IsisCube_00.cub");
+  testCube.setDimensions(10, 10, 1);
+  testCube.create(file);
+  testCube.close();
+  testCube.open(file, "r");
+  LineManager line(testCube);
+  double pixelValue = 0.0;
+  for(int i = 0; i < line.size(); i++) {
+    line[i] = (double) pixelValue++;
+  }
+
+  try {
+    testCube.write(line);
+    FAIL() << "Expected an exception to be thrown";
+  }
+  catch(IException &e) {
+    EXPECT_TRUE(e.toString().toLatin1().contains("Cannot write to the cube [IsisCube_00.cub] because it is opened read-only."))
+      << e.toString().toStdString();
+  }
+}
+
+TEST(CubeTest, TestCubeOpenNonexistentCube) {
+  try {
+    Cube testCube;
+    testCube.open("blah");
+    FAIL() << "Expected an exception to be thrown";
+  }
+  catch(IException &e) {
+    EXPECT_TRUE(e.toString().toLatin1().contains("Unable to open [blah]."))
+      << e.toString().toStdString();
+  }
+}
+
+TEST_F(SmallCube, TestCubePhyscialBandOutOfBounds) {
+  QString path = testCube->fileName();
+  testCube->close();
+  QList<QString> vbands = {"1", "2", "3", "4", "5"};
+  testCube->setVirtualBands(vbands);
+  testCube->open(path);
+  try {
+    std::cout << testCube->bandCount() << std::endl;
+    int band = testCube->physicalBand(6);
+    std::cout << band << std::endl;
+    FAIL() << "Expected an exception to be thrown";
+  }
+  catch(IException &e) {
+    EXPECT_TRUE(e.toString().toLatin1().contains("Out of array bounds [6]."))
+      << e.toString().toStdString();
+  }
+
+  try {
+    testCube->physicalBand(0);
+    FAIL() << "Expected an exception to be thrown";
+  }
+  catch(IException &e) {
+    EXPECT_TRUE(e.toString().toLatin1().contains("Out of array bounds [0]."))
+      << e.toString().toStdString();
+  }
+}
+
+TEST(CubeTest, TestCubeReadBlankCube) {
+  Cube testCube;
+  testCube.setDimensions(10, 10, 1);
+  LineManager line(testCube);
+  try {
+    testCube.read(line);
+    FAIL() << "Expected an exception to be thrown";
+  }
+  catch(IException &e) {
+    EXPECT_TRUE(e.toString().toLatin1().contains("Try opening a file before you read it."))
+      << e.toString().toStdString();
+  }
+}
+
+TEST(CubeTest, TestCubeWriteBlankCube) {
+  Cube testCube;
+  testCube.setDimensions(10, 10, 1);
+  LineManager line(testCube);
+  double pixelValue = 0.0;
+  for(int i = 0; i < line.size(); i++) {
+    line[i] = (double) pixelValue++;
+  }
+  try {
+    testCube.write(line);
+    FAIL() << "Expected an exception to be thrown";
+  }
+  catch(IException &e) {
+    EXPECT_TRUE(e.toString().toLatin1().contains("Tried to write to a cube before opening/creating it."))
+      << e.toString().toStdString();
+  }
+}
+
+TEST_F(TempTestingFiles, TestCubeCreateZeroDimCube) {
+  Cube testCube;
+  try {
+    testCube.create(tempDir.path() + "/IsisCube_00.cub");
+    testCube.close();
+    FAIL() << "Expected an exception to be thrown";
+  }
+  catch(IException &e) {
+    EXPECT_TRUE(e.toString().toLatin1().contains("Number of samples [0], lines [0], or bands [0] cannot be less than 1."))
+      << e.toString().toStdString();
+  }
+}
+
+TEST_F(TempTestingFiles, TestCubeCreateSmallLabel) {
+  Cube testCube;
+  try {
+    testCube.setLabelSize(15);
+    testCube.setDimensions(1, 1, 1);
+    testCube.create(tempDir.path() + "/IsisCube_00.cub");
+    testCube.close();
+    FAIL() << "Expected an exception to be thrown";
+  }
+  catch(IException &e) {
+    EXPECT_TRUE(e.toString().toLatin1().contains("Label space is full in [IsisCube_00.cub] unable to write labels."))
+      << e.toString().toStdString();
+  }
+}
+
+TEST_F(TempTestingFiles, TestCubeCreateTooBig) {
+  Cube testCube;
+  try {
+    testCube.setDimensions(1000000, 1000000, 9);
+    testCube.create("IsisCube_00.cub");
+    testCube.close();
+    FAIL() << "Expected an exception to be thrown";
+  }
+  catch(IException &e) {
+    EXPECT_TRUE(e.toString().toLatin1().contains("The cube you are attempting to create [IsisCube_00.cub] is [33527GB]. "
+                                                  "This is larger than the current allowed size of [12GB]. The cube "
+                                                  "dimensions were (S,L,B) [1000000, 1000000, 9] with [4] bytes per pixel. "
+                                                  "If you still wish to create this cube, the maximum value can be changed "
+                                                  "in your personal preference file located in [~/.Isis/IsisPreferences] "
+                                                  "within the group CubeCustomization, keyword MaximumSize. If you do not have "
+                                                  "an ISISPreference file, please refer to the documentation 'Environment and Preference Setup'. Error."))
+      << e.toString().toStdString();
+  }
+}
+
+TEST_F(SmallCube, TestCubeOpenBadAccessor) {
+  try {
+    Cube localTestCube;
+    localTestCube.open(testCube->fileName(), "a");
+    FAIL() << "Expected an exception to be thrown";
+  }
+  catch(IException &e) {
+    EXPECT_TRUE(e.toString().toLatin1().contains("Unknown value for access [a]. Expected 'r'  or 'rw'."))
+      << e.toString().toStdString();
+  }
+}
+
+TEST(CubeTest, TestCubeInvalidDimSamples) {
+  try {
+    Cube testCube;
+    testCube.setDimensions(0, 1, 1);
+    FAIL() << "Expected an exception to be thrown";
+  }
+  catch(IException &e) {
+    EXPECT_TRUE(e.toString().toLatin1().contains("SetDimensions:  Invalid number of sample, lines or bands."))
+      << e.toString().toStdString();
+  }
+}
+
+TEST(CubeTest, TestCubeInvalidDimLines) {
+  try {
+    Cube testCube;
+    testCube.setDimensions(1, 0, 1);
+    FAIL() << "Expected an exception to be thrown";
+  }
+  catch(IException &e) {
+    EXPECT_TRUE(e.toString().toLatin1().contains("SetDimensions:  Invalid number of sample, lines or bands."))
+      << e.toString().toStdString();
+  }
+}
+
+TEST(CubeTest, TestCubeInvalidDimBands) {
+  try {
+    Cube testCube;
+    testCube.setDimensions(1, 1, 0);
+    FAIL() << "Expected an exception to be thrown";
+  }
+  catch(IException &e) {
+    EXPECT_TRUE(e.toString().toLatin1().contains("SetDimensions:  Invalid number of sample, lines or bands."))
+      << e.toString().toStdString();
+  }
+}
+
+TEST(CubeTest, TestCubeNonePixelType) {
+  try {
+    Cube testCube;
+    testCube.setPixelType(None);
+    testCube.setDimensions(1, 1, 1);
+    testCube.create("IsisCube_00.cub");
+    FAIL() << "Expected an exception to be thrown";
+  }
+  catch(IException &e) {
+    EXPECT_TRUE(e.toString().toLatin1().contains("Cannot create the cube [IsisCube_00.cub] with a pixel type set to None."))
+      << e.toString().toStdString();
+  }
+}
+
+TEST_F(TempTestingFiles, TestCubeAddGroupReadOnly) {
+  try {
+    Cube testCube;
+    testCube.setDimensions(1024, 1024, 1);
+    testCube.create(tempDir.path() + "/IsisCube_00.cub");
+    testCube.reopen("r");
+    testCube.putGroup(PvlGroup("TestGroup2"));
+    FAIL() << "Expected an exception to be thrown";
+  }
+  catch(IException &e) {
+    EXPECT_TRUE(e.toString().toLatin1().contains("Cannot add a group to the label of cube [IsisCube_00.cub] because it is opened read-only."))
+      << e.toString().toStdString();
+  }
+}
+
+TEST_F(SmallCube, TestCubeCreateECube) {
+  Cube localTestCube;
+  QString path = testCube->fileName();
+  localTestCube.setExternalDnData(path);
+  localTestCube.create(tempDir.path() + "/isisTruth_external.ecub");
+  localTestCube.putGroup(PvlGroup("TestGroup"));
+  EXPECT_EQ(localTestCube.realDataFileName().expanded(), path);
+  EXPECT_TRUE(localTestCube.hasGroup("TestGroup"));
+
+  path = localTestCube.fileName();
+  check_cube(localTestCube, path, 10, 10, 10, 0, 1, 7, 2, 1, 1, 0, 1, 65536);
+}
+
+class ECube : public SmallCube {
+    protected:
+      Cube * testECube;
+
+        void SetUp() override {
+            SmallCube::SetUp();
+            testECube = new Cube();
+            testECube->setExternalDnData(testCube->fileName());
+            QString path = tempDir.path() + "/external.ecub";
+            testECube->create(path);
+
+            testECube->close();
+            testECube->open(path, "rw");
+    }
+
+      void TearDown() override {
+        if (testECube->isOpen()) {
+            testECube->close();
+        }
+
+        if (testECube) {
+            delete testECube;
+        }
+        SmallCube::TearDown();
+    }
+};
+
+TEST_F(ECube, TestCubeCreateECubeFromECube) {
+  QString path1 = testECube->fileName();
+
+  Cube localTestCube;
+  localTestCube.setExternalDnData(path1);
+  QString path2 = tempDir.path() + "/isisTruth_external2.ecub";
+  localTestCube.create(path2);
+  EXPECT_EQ(localTestCube.realDataFileName().expanded(), testCube->fileName());
+
+  check_cube(localTestCube, path2, 10, 10, 10, 0, 1, 7, 2, 1, 1, 0, 1, 65536);
+}
+
+TEST_F(ECube, TestCubeECubeRead) {
+    Brick readBrick(3, 3, 2, testECube->pixelType());
+    readBrick.SetBasePosition(1, 1, 1);
+    testECube->read(readBrick);
+    std::vector<int> truth = {0, 1, 2, 10, 11, 12, 20, 21, 22, 100, 101, 102, 110, 111, 112, 120, 121, 122};
+    for (int index = 0; index < readBrick.size(); index++) {
+      EXPECT_EQ(readBrick[index], truth[index]);
+    }
+}
+
+TEST_F(ECube, TestCubeECubeWrite) {
+    Brick writeBrick(3, 3, 2, testECube->pixelType());
+    writeBrick.SetBasePosition(1, 1, 1);
+    for (int index = 0; index < writeBrick.size(); index++) {
+      writeBrick[index] = 1.0;
+    }
+    try {
+      testECube->write(writeBrick);
+      FAIL();
+    }
+    catch(IException &e) {
+      EXPECT_TRUE(e.toString().toLatin1().contains("The cube [external.ecub] does not support storing DN data because it is using an external file for DNs."))
+        << e.toString().toStdString();
+    }
+}
+
+TEST_F(ECube, TestCubeECubeFromECubeRead) {
+    QString path1 = testECube->fileName();
+
+    Cube localTestCube;
+    localTestCube.setExternalDnData(path1);
+    QString path2 = tempDir.path() + "/isisTruth_external2.ecub";
+    localTestCube.create(path2);
+
+    Brick readBrick(3, 3, 2, localTestCube.pixelType());
+    readBrick.SetBasePosition(1, 1, 1);
+    localTestCube.read(readBrick);
+    std::vector<int> truth = {0, 1, 2, 10, 11, 12, 20, 21, 22, 100, 101, 102, 110, 111, 112, 120, 121, 122};
+    for (int index = 0; index < readBrick.size(); index++) {
+      EXPECT_EQ(readBrick[index], truth[index]);
+    }
+}