diff --git a/.travis.yml b/.travis.yml
index 4cdb558eff..5bb3658730 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,3 +1,4 @@
+dist: trusty
 language: java
 
 # Previously, we were seeing a failure in :it:appBeforeIntegrationTest:
diff --git a/build.gradle b/build.gradle
index 1253707ef2..25fe78a0db 100644
--- a/build.gradle
+++ b/build.gradle
@@ -69,7 +69,7 @@ ext {
     javaProjects = subprojects.findAll { it.plugins.withType(JavaPlugin) }
     
     internalProjects = subprojects.findAll { it.path in [
-            ':dap4', ':opendap:dtswar', ':docs', ':cdm-test', ':testUtil'
+            ':dap4', ':dap4:d4tests', ':docs', ':cdm-test', ':testUtil'
     ] }
     
     publishedProjects = subprojects - internalProjects
diff --git a/dap4/d4cdm/src/main/java/dap4/cdm/dsp/CDMCursor.java b/dap4/d4cdm/src/main/java/dap4/cdm/dsp/CDMCursor.java
deleted file mode 100644
index 033d97003a..0000000000
--- a/dap4/d4cdm/src/main/java/dap4/cdm/dsp/CDMCursor.java
+++ /dev/null
@@ -1,292 +0,0 @@
-/* Copyright 2012, UCAR/Unidata.
-   See the LICENSE file for more information.
-*/
-
-package dap4.cdm.dsp;
-
-import dap4.cdm.CDMTypeFcns;
-import dap4.cdm.CDMUtil;
-import dap4.core.dmr.*;
-import dap4.core.util.*;
-import dap4.core.util.Index;
-import dap4.dap4lib.AbstractCursor;
-import ucar.ma2.*;
-
-import java.util.List;
-
-public class CDMCursor extends AbstractCursor
-{
-    //////////////////////////////////////////////////
-    // Instance variables
-
-    protected ucar.ma2.Array array = null;
-    protected ucar.ma2.StructureData structdata = null; // scheme == STRUCTURE
-    ucar.ma2.StructureMembers.Member member = null; // for field cursors
-
-    //////////////////////////////////////////////////
-    // Constructor(s)
-
-    public CDMCursor(Scheme scheme, CDMDSP dsp, DapNode template, CDMCursor container)
-            throws DapException
-    {
-        super(scheme, dsp, template, container);
-    }
-
-    public CDMCursor(CDMCursor c)
-    {
-        super(c);
-        assert false;
-        this.array = c.array;
-        this.structdata = c.structdata;
-        this.member = c.member;
-
-    }
-
-    //////////////////////////////////////////////////
-    // AbstractCursor Abstract Methods
-
-    @Override
-    public Object
-    read(List<Slice> slices)
-            throws DapException
-    {
-        switch (this.scheme) {
-        case ATOMIC:
-            return readAtomic(slices);
-        case STRUCTURE:
-            if(((DapVariable) this.getTemplate()).getRank() > 0
-                    || DapUtil.isScalarSlices(slices))
-                throw new DapException("Cannot slice a scalar variable");
-            CDMCursor[] instances = new CDMCursor[1];
-            instances[0] = this;
-            return instances;
-        case SEQUENCE:
-            if(((DapVariable) this.getTemplate()).getRank() > 0
-                    || DapUtil.isScalarSlices(slices))
-                throw new DapException("Cannot slice a scalar variable");
-            instances = new CDMCursor[1];
-            instances[0] = this;
-            return instances;
-        case STRUCTARRAY:
-            Odometer odom = Odometer.factory(slices);
-            instances = new CDMCursor[(int) odom.totalSize()];
-            for(int i = 0; odom.hasNext(); i++) {
-                instances[i] = readStructure(odom.next());
-            }
-            return instances;
-        case SEQARRAY:
-            instances = readSequence(slices);
-            return instances;
-        default:
-            throw new DapException("Attempt to slice a scalar object");
-        }
-    }
-
-    @Override
-    public Object
-    read(Index index)
-            throws DapException
-    {
-        return read(DapUtil.indexToSlices(index));
-    }
-
-    @Override
-    public CDMCursor
-    readField(int findex)
-            throws DapException
-    {
-        if(this.scheme != scheme.RECORD && this.scheme != scheme.STRUCTURE)
-            throw new DapException("Illegal cursor scheme for readfield()");
-        DapVariable var = (DapVariable) getTemplate();
-        DapStructure basetype = (DapStructure) var.getBaseType();
-        if(findex < 0 || findex >= basetype.getFields().size())
-            throw new DapException("Field index out of range: " + findex);
-        CDMCursor fieldcursor = null;
-        if(this.scheme == Scheme.RECORD) {
-            DapSequence seq = (DapSequence) basetype;
-            DapVariable field = seq.getField(0);
-            DapType fieldtype = field.getBaseType();
-            switch (fieldtype.getTypeSort()) {
-            default: // atomic
-                DataType cdmfieldtype = CDMTypeFcns.daptype2cdmtype(fieldtype);
-                if(cdmfieldtype == null)
-                    throw new dap4.core.util.DapException("Unknown field type: " + fieldtype);
-                int ri = (int) this.recordindex;
-                Object o = array.getObject(ri);
-                Array fielddata = CDMTypeFcns.arrayify(cdmfieldtype, o); // not very efficient; should do conversion
-                fieldcursor = new CDMCursor(Scheme.ATOMIC, (CDMDSP) this.dsp, field, this);
-                fieldcursor.setArray(fielddata);
-                break;
-            case Sequence:
-            case Structure:
-                break;
-            }
-        } else { // scheme == STRUCTURE
-            assert this.structdata != null;
-            fieldcursor = getFieldCursor(this, findex);
-        }
-        return fieldcursor;
-    }
-
-    protected CDMCursor
-    getFieldCursor(CDMCursor container, int findex)
-            throws DapException
-    {
-        // Now, create a cursors for a field f this instance
-        DapVariable var = (DapVariable) getTemplate();
-        DapStructure type = (DapStructure) var.getBaseType();
-        DapVariable field = (DapVariable) type.getFields().get(findex);
-        DapType ftype = field.getBaseType();
-        Scheme scheme = schemeFor(field);
-        CDMCursor fc = new CDMCursor(scheme, (CDMDSP) this.dsp, field, this);
-        StructureMembers.Member member = this.structdata.getStructureMembers().getMember(findex);
-        fc.setMember(member);
-        fc.setArray(this.structdata.getArray(fc.member));
-        return fc;
-    }
-
-    @Override
-    public CDMCursor
-    readRecord(long i)
-            throws DapException
-    {
-        if(this.scheme != scheme.SEQUENCE)
-            throw new DapException("Attempt to read record from non-sequence cursor");
-        if(i < 0 || i >= this.recordcount)
-            throw new DapException("Record index out of bounds");
-        DapVariable var = (DapVariable) getTemplate();
-        CDMCursor c = new CDMCursor(Scheme.RECORD, (CDMDSP) this.dsp, var, this);
-        c.setArray(this.array);
-        c.setRecordIndex(i);
-        return c;
-    }
-
-    //////////////////////////////////////////////////
-    // Support Methods
-
-    protected Object
-    readAtomic(List<Slice> slices)
-            throws DapException
-    {
-        if(slices == null)
-            throw new DapException("DataCursor.read: null set of slices");
-        assert (this.scheme == scheme.ATOMIC);
-        DapVariable atomvar = (DapVariable) getTemplate();
-        assert slices != null && ((atomvar.getRank() == 0 && slices.size() == 1) || (slices.size() == atomvar.getRank()));
-        return sliceAtomic(slices, this.array, atomvar);
-    }
-
-    protected Object
-    sliceAtomic(List<Slice> slices, Array array, DapVariable var)
-            throws DapException
-    {
-        List<DapDimension> dimset = var.getDimensions();
-        DapType basetype = var.getBaseType();
-        // If content.getDataType returns object, then we
-        // really do not know its true datatype. So, as a rule,
-        // we will rely on this.basetype.
-        DataType datatype = CDMTypeFcns.daptype2cdmtype(basetype);
-        if(datatype == null)
-            throw new dap4.core.util.DapException("Unknown basetype: " + basetype);
-        Object content = array.get1DJavaArray(datatype); // not very efficient; should do conversion
-        Odometer odom = Odometer.factory(slices, dimset);
-        Object data = CDMTypeFcns.createVector(datatype, odom.totalSize());
-        for(int dstoffset = 0; odom.hasNext(); dstoffset++) {
-            Index index = odom.next();
-            long srcoffset = index.index();
-            CDMTypeFcns.vectorcopy(basetype, content, data, srcoffset, dstoffset);
-        }
-        return data;
-    }
-
-
-    protected CDMCursor
-    readStructure(Index index)
-            throws DapException
-    {
-        assert (index != null);
-        DapVariable var = (DapVariable) getTemplate();
-        DapStructure type = (DapStructure) var.getBaseType();
-        long pos = index.index();
-        if(pos < 0 || pos > var.getCount())
-            throw new IndexOutOfBoundsException("read: " + index);
-        ArrayStructure sarray = (ArrayStructure) this.array;
-        CDMCursor instance;
-        assert (this.scheme == scheme.STRUCTARRAY);
-        ucar.ma2.StructureData sd = sarray.getStructureData((int) pos);
-        assert sd != null;
-        instance = new CDMCursor(Scheme.STRUCTURE, (CDMDSP) this.dsp, var, null)
-                .setStructureData(sd);
-        instance.setIndex(index);
-        return instance;
-    }
-
-    protected CDMCursor[]
-    readSequence(List<Slice> slices)
-            throws DapException
-    {
-        assert (this.scheme == scheme.SEQARRAY);
-        DapVariable var = (DapVariable) getTemplate();
-        DapSequence type = (DapSequence) var.getBaseType();
-        // new CDMCursor(Scheme.SEQUENCE, (CDMDSP) this.dsp, var, this);
-        CDMCursor[] instances = new CDMCursor[(int) DapUtil.sliceProduct(slices)];
-        Array seqarray = this.array;
-        if(var.getRank() == 0) {// scalar
-            if(!DapUtil.isScalarSlices(slices))
-                throw new DapException("Non-scalar slice set applied to scalar variable");
-            instances[0] = new CDMCursor(Scheme.SEQUENCE, (CDMDSP) this.dsp, var, this);
-            instances[0].setArray(seqarray);
-            instances[0].setRecordCount(seqarray.getSize());
-        } else {
-            List<Range> rlist = CDMUtil.createCDMRanges(slices);
-            Array instancearray;
-            try {
-                instancearray = seqarray.section(rlist);
-            } catch (InvalidRangeException e) {
-                throw new DapException("Illegal slice set", e);
-            }
-            // extracted via List<Slice>. IN theory, this should be an array of arrays,
-            // but if the sequence field basetype is atomic, thenit is an array
-            // of atomic values.
-            int slicecount = (int) DapUtil.sliceProduct(slices);
-            for(int i = 0; i < slicecount; i++) {
-                Array ao = (Array)instancearray.getObject(i);
-                CDMCursor c = new CDMCursor(Scheme.SEQUENCE, (CDMDSP) this.dsp, var, this);
-                c.setArray(ao);
-                long rcount = ao.getSize();
-                c.setRecordCount(rcount);
-                instances[i] = c;
-            }
-        }
-        return instances;
-    }
-
-    //////////////////////////////////////////////////
-    // CDMCursor Extensions
-
-    public CDMCursor setArray(ucar.ma2.Array a)
-    {
-        this.array = a;
-        return this;
-    }
-
-    public ucar.ma2.Array
-    getArray()
-    {
-        return this.array;
-    }
-
-    public CDMCursor setStructureData(ucar.ma2.StructureData sd)
-    {
-        this.structdata = sd;
-        return this;
-    }
-
-    public CDMCursor setMember(ucar.ma2.StructureMembers.Member m)
-    {
-        this.member = m;
-        return this;
-    }
-
-
-}
diff --git a/dap4/d4cdm/src/main/java/dap4/cdm/dsp/CDMDSP.java b/dap4/d4cdm/src/main/java/dap4/cdm/dsp/CDMDSP.java
deleted file mode 100644
index e020013409..0000000000
--- a/dap4/d4cdm/src/main/java/dap4/cdm/dsp/CDMDSP.java
+++ /dev/null
@@ -1,1159 +0,0 @@
-/*
- * Copyright (c) 2012-2018 University Corporation for Atmospheric Research/Unidata
- * See LICENSE for license information.
- */
-
-package dap4.cdm.dsp;
-
-import dap4.cdm.CDMTypeFcns;
-import dap4.cdm.CDMUtil;
-import dap4.cdm.NodeMap;
-import dap4.core.data.DataCursor;
-import dap4.core.dmr.*;
-import dap4.core.util.Convert;
-import dap4.core.util.DapContext;
-import dap4.core.util.DapException;
-import dap4.core.util.DapUtil;
-import dap4.dap4lib.AbstractDSP;
-import ucar.ma2.Array;
-import ucar.ma2.DataType;
-import ucar.ma2.IndexIterator;
-import ucar.nc2.*;
-import ucar.nc2.constants.CDM;
-import ucar.nc2.dataset.*;
-import ucar.nc2.util.CancelTask;
-
-import java.io.IOException;
-import java.util.*;
-
-/**
- * Wrap CDM source (NetcdfDataset) to be a DSP
- * This basically means wrapping various (CDM)Array
- * object to look like DataVariable objects.
- * Currently only used on server side
- */
-
-public class CDMDSP extends AbstractDSP
-{
-
-    //////////////////////////////////////////////////
-    // Constants
-
-    static protected final boolean DEBUG = false;
-    static protected final boolean DUMPCDL = false;
-
-    // NetcdfDataset enhancement to use: need only coord systems
-    static protected Set<NetcdfDataset.Enhance> ENHANCEMENT = EnumSet.of(NetcdfDataset.Enhance.CoordSystems);
-
-    static final protected String FILLVALUE = "_FillValue";
-
-    //////////////////////////////////////////////////
-    // Class variables
-
-    static protected boolean nc4loaded = false;
-
-    //////////////////////////////////////////////////
-    // Class methods
-
-
-    //////////////////////////////////////////////////
-    // Instance variables
-
-    protected NetcdfDataset ncdfile = null;
-    protected boolean closed = false;
-    protected DMRFactory dmrfactory = null;
-
-    // Keep various context-dependent maps between
-    // CDMNode instances and DapNode instances
-    // package access
-
-    // Variable map
-    protected NodeMap<Variable, DapVariable> varmap = new NodeMap<>();
-
-    // Variable <-> DapStructure (basetype) map; compound types only
-    protected NodeMap<Variable, DapStructure> compoundmap = new NodeMap<>();
-
-    // Map Variable <-> DapSequence vlen type
-    protected NodeMap<Variable, DapSequence> vlenmap = new NodeMap<>();
-
-    // Map All other kinds of CDMNode <-> DapNode
-    protected NodeMap<CDMNode, DapNode> nodemap = new NodeMap<>();
-
-    //////////////////////////////////////////////////
-    // Constructor(s)
-
-    public CDMDSP()
-    {
-    }
-
-    public CDMDSP(String path)
-            throws DapException
-    {
-        super();
-        setLocation(path);
-    }
-
-    //////////////////////////////////////////////////
-    // DSP Interface
-
-    // This is intended to be the last DSP checked
-    @Override
-    public boolean dspMatch(String path, DapContext context)
-    {
-        return true;
-    }
-
-    /**
-     * @param filepath - absolute path to a file
-     * @return CDMDSP instance
-     * @throws DapException
-     */
-    @Override
-    public CDMDSP
-    open(String filepath)
-            throws DapException
-    {
-        try {
-            NetcdfFile ncfile = createNetcdfFile(filepath, null);
-            NetcdfDataset ncd = new NetcdfDataset(ncfile, ENHANCEMENT);
-            return open(ncd);
-        } catch (IOException ioe) {
-            throw new DapException("CDMDSP: cannot process: " + filepath, ioe);
-        }
-    }
-
-    /**
-     * Provide an extra API for use in testing
-     *
-     * @param ncd
-     * @return
-     * @throws DapException
-     */
-    public CDMDSP open(NetcdfDataset ncd)
-            throws DapException
-    {
-        assert this.context != null;
-        this.dmrfactory = new DMRFactory();
-        this.ncdfile = ncd;
-        setLocation(this.ncdfile.getLocation());
-        buildDMR();
-        return this;
-    }
-
-    @Override
-    public void close()
-            throws IOException
-    {
-        if (this.ncdfile != null)
-            this.ncdfile.close();
-    }
-
-
-    @Override
-    public DataCursor
-    getVariableData(DapVariable var)
-            throws DapException
-    {
-        Variable cdmvar = this.varmap.get(var);
-        if (cdmvar == null)
-            throw new DapException("Unknown variable: " + var);
-        CDMCursor vardata = (CDMCursor) super.getVariableData(var);
-        if (vardata == null) {
-            DataCursor.Scheme scheme = CDMCursor.schemeFor(var);
-            try {
-                vardata = new CDMCursor(scheme, this, var, null);
-                vardata.setArray(cdmvar.read());
-            } catch (IOException e) {
-                throw new DapException(e);
-            }
-            super.addVariableData(var, vardata);
-        }
-        return vardata;
-    }
-
-    //////////////////////////////////////////////////
-    // Abstract DSP Abstract methods
-
-    //////////////////////////////////////////////////
-    // CDMDSP Specific Accessors
-
-    public NetcdfDataset getNetcdfDataset()
-    {
-        return this.ncdfile;
-    }
-
-    //////////////////////////////////////////////////
-    // Nodemap Management
-
-    /* Make sure that we use the proper
-     * object in order to avoid identity
-     * problems.
-     */
-
-    /**
-     * Track generic CDMNode <-> DapNode
-     */
-    protected void
-    recordNode(CDMNode cdm, DapNode dap)
-    {
-        assert this.nodemap.get(cdm) == null && this.nodemap.get(dap) == null;
-        this.nodemap.put(cdm, dap);
-    }
-
-    /**
-     * Track Variable <-> DapVariable
-     */
-    protected void
-    recordVar(Variable cdm, DapVariable dap)
-    {
-        cdm = CDMUtil.unwrap(cdm);
-        assert varmap.get(cdm) == null && varmap.get(dap) == null;
-        varmap.put(cdm, dap);
-    }
-
-    /**
-     * Track Variable <-> DapStructure
-     */
-    protected void
-    recordStruct(Variable cdm, DapStructure dap)
-    {
-        cdm = CDMUtil.unwrap(cdm);
-        assert this.nodemap.get(cdm) == null && this.nodemap.get(dap) == null;
-        compoundmap.put(cdm, dap);
-    }
-
-    /**
-     * Track Variable <-> DapSequence
-     */
-    protected void
-    recordSeq(Variable cdm, DapSequence dap)
-    {
-        cdm = CDMUtil.unwrap(cdm);
-        assert this.vlenmap.get(cdm) == null && this.vlenmap.get(dap) == null;
-        vlenmap.put(cdm, dap);
-    }
-
-    /**
-     * Lookup a cdmnode in the cdmnodemap.
-     * Make sure that we use the proper
-     * object in order to avoid identity
-     * problems.
-     *
-     * @param cdmnode The CMDNode (variable, dimension, etc) to record
-     * @return The DapNode to which the cdmnode is to be mapped or null.
-     */
-/*
-    protected DapNode
-    lookupNode(CDMNode cdmnode)
-    {
-        CDMSort sort = cdmnode.getSort();
-        if(sort == CDMSort.VARIABLE || sort == CDMSort.STRUCTURE) {
-            Variable basev = CDMUtil.unwrap((Variable) cdmnode);
-            assert (basev != null) : "Unwrap() failed";
-            cdmnode = (CDMNode) basev;
-        }
-        return this.nodemap.get(cdmnode);
-    }
-*/
-
-    //////////////////////////////////////////////////
-
-    /**
-     * Extract the metadata from the NetcdfDataset
-     * and build the DMR.
-     */
-
-    public void
-    buildDMR()
-            throws DapException
-    {
-        if (getDMR() != null)
-            return;
-        try {
-            if (DUMPCDL) {
-                System.out.println("writecdl:");
-                this.ncdfile.writeCDL(System.out, false);
-                System.out.flush();
-            }
-            // Use the file path to define the dataset name
-            String name = this.ncdfile.getLocation();
-            // Normalize the name
-            name = DapUtil.canonicalpath(name);
-            // Remove any path prefix
-            int index = name.lastIndexOf('/');
-            if (index >= 0)
-                name = name.substring(index + 1, name.length());
-            // Initialize the root dataset node
-            setDMR((DapDataset) dmrfactory.newDataset(name).annotate(NetcdfDataset.class, this.ncdfile));
-            // Map the CDM root group to this group
-            recordNode(this.ncdfile.getRootGroup(), getDMR());
-            getDMR().setBase(DapUtil.canonicalpath(this.ncdfile.getLocation()));
-
-            // Now recursively build the tree. Start by
-            // Filling the dataset with the contents of the ncfile
-            // root group.
-            fillgroup(getDMR(), this.ncdfile.getRootGroup());
-
-            // Add an order index to the tree
-            getDMR().sort();
-
-            // Now locate the coordinate variables for maps
-
-            /* Walk looking for VariableDS instances */
-            processmappedvariables(this.ncdfile.getRootGroup());
-
-            // Now set the view
-            getDMR().finish();
-
-        } catch (DapException e) {
-            setDMR(null);
-            throw new DapException(e);
-        }
-    }
-
-    //////////////////////////////////////////////////
-    // Actions
-
-    protected void
-    fillgroup(DapGroup dapgroup, Group cdmgroup)
-            throws DapException
-    {
-        // Create decls in dap group for Dimensions
-        for (Dimension cdmdim : cdmgroup.getDimensions()) {
-            DapDimension dapdim = builddim(cdmdim);
-        }
-        // Create decls in dap group for Enumerations
-        for (EnumTypedef cdmenum : cdmgroup.getEnumTypedefs()) {
-            String name = cdmenum.getShortName();
-            DapEnumeration dapenum = buildenum(cdmenum);
-            dapenum.setShortName(name);
-            dapgroup.addDecl(dapenum);
-        }
-        // Create decls in dap group for vlen induced Sequences
-        // Do this before building compound types
-        for (Variable cdmvar0 : cdmgroup.getVariables()) {
-            Variable cdmvar = CDMUtil.unwrap(cdmvar0);
-            buildseqtypes(cdmvar);
-        }
-        // Create decls in dap group for Compound Types
-        for (Variable cdmvar0 : cdmgroup.getVariables()) {
-            Variable cdmvar = CDMUtil.unwrap(cdmvar0);
-            if (cdmvar.getDataType() != DataType.STRUCTURE
-                    && cdmvar.getDataType() != DataType.SEQUENCE)
-                continue;
-            DapStructure struct = buildcompoundtype(cdmvar, dapgroup);
-        }
-
-        // Create decls in dap group for Variables
-        for (Variable cdmvar0 : cdmgroup.getVariables()) {
-            Variable cdmvar = CDMUtil.unwrap(cdmvar0);
-            DapNode newvar = buildvariable(cdmvar, dapgroup, cdmvar.getDimensions());
-        }
-        // Create decls in dap group for subgroups
-        for (Group subgroup : cdmgroup.getGroups()) {
-            DapGroup newgroup = buildgroup(subgroup);
-            dapgroup.addDecl(newgroup);
-        }
-        // Create decls in dap group for group-level attributes
-        buildattributes(dapgroup, cdmgroup.getAttributes());
-    }
-
-    //////////////////////////////////////////////////
-    // Declaration Builders
-
-    protected DapDimension
-    builddim(Dimension cdmdim)
-            throws DapException
-    {
-        if (cdmdim.isVariableLength())
-            throw new DapException("* dimensions not supported");
-        DapDimension dapdim = null;
-        long cdmsize = dapsize(cdmdim);
-        String name = cdmdim.getShortName();
-        if (name != null && name.length() == 0)
-            name = null;
-        boolean shared = cdmdim.isShared();
-        if (!shared) {
-            // Unlike the parser, since we are working
-            // from a NetcdfDataset instance, there might
-            // be multiple anonymous dimension objects
-            // the same size. So, just go ahead and create
-            // multiple instances.
-            dapdim = (DapDimension) dmrfactory.newDimension(null, cdmsize);
-            getDMR().addDecl(dapdim);
-        } else { // Non anonymous; create in current group
-            dapdim = (DapDimension) dmrfactory.newDimension(name, cdmsize);
-            dapdim.setShared(true);
-            if (cdmdim.isUnlimited()) {
-                dapdim.setUnlimited(true);
-            }
-            Group cdmparent = cdmdim.getGroup();
-            DapGroup dapparent = (DapGroup) this.nodemap.get(cdmparent);
-            assert dapparent != null;
-            assert (dapparent != null);
-            dapparent.addDecl(dapdim);
-        }
-        recordNode(cdmdim, dapdim);
-        return dapdim;
-    }
-
-    protected DapEnumeration
-    buildenum(EnumTypedef cdmenum)
-            throws DapException
-    {
-        // Set the enum's basetype
-        DapType base = null;
-        switch (cdmenum.getBaseType()) {
-            case ENUM1:
-                base = DapType.INT8;
-                break;
-            case ENUM2:
-                base = DapType.INT16;
-                break;
-            case ENUM4:
-            default:
-                base = DapType.INT32;
-                break;
-        }
-        DapEnumeration dapenum = (DapEnumeration) dmrfactory.newEnumeration(cdmenum.getShortName(), base);
-        recordNode(cdmenum, dapenum);
-        // Create the enum constants
-        Map<Integer, String> ecvalues = cdmenum.getMap();
-        for (Map.Entry<Integer, String> entry : ecvalues.entrySet()) {
-            String name = entry.getValue();
-            assert (name != null);
-            int value = (int) entry.getKey();
-            dapenum.addEnumConst(dmrfactory.newEnumConst(name, new Long(value)));
-        }
-        return dapenum;
-    }
-
-    protected DapStructure
-    buildcompoundtype(Variable cdmvar, DapNode parent)
-            throws DapException
-    {
-        cdmvar = CDMUtil.unwrap(cdmvar);
-        DapStructure struct;
-        if (cdmvar.getDataType() == DataType.STRUCTURE)
-            struct = (DapStructure) dmrfactory.newStructure(cdmvar.getShortName());
-        else if (cdmvar.getDataType() == DataType.SEQUENCE)
-            struct = (DapStructure) dmrfactory.newSequence(cdmvar.getShortName());
-        else
-            throw new DapException("Internal error");
-        struct.setParent(parent);
-        recordStruct(cdmvar, struct);
-        Structure cdmstruct = (Structure) cdmvar;
-        List<Variable> fields = cdmstruct.getVariables();
-        // recurse to create compound types of any fields c
-        for (CDMNode node : fields) {
-            Variable cdmfield = (Variable) node;
-            List<Dimension> dimset = cdmfield.getDimensions();
-            // Recurse on any nested compound types
-            if (cdmfield.getDataType() == DataType.STRUCTURE
-                    || cdmfield.getDataType() == DataType.SEQUENCE) {
-                DapStructure fieldstruct = buildcompoundtype(cdmfield, struct);
-            }
-        }
-        // Add the fields to this compound type
-        for (CDMNode node : fields) {
-            Variable cdmfield = (Variable) node;
-            DapType basetype = null;
-            switch (cdmfield.getDataType()) {
-                default:
-                    basetype = CDMTypeFcns.cdmtype2daptype(cdmfield.getDataType());
-                    break;
-                case STRUCTURE:
-                case SEQUENCE:
-                    basetype = compoundmap.get(cdmfield);// since no forward references
-                    break;
-            }
-            // build the field variable
-            List<Dimension> fielddims = cdmfield.getDimensions();
-            DapVariable dapfield;
-            if (CDMUtil.hasVLEN(cdmfield)) {
-                // Get the fake sequence associated with this vlen
-                DapSequence seq = vlenmap.get(cdmfield);
-                List<Dimension> coredims = getCoreDimset(fielddims);
-                // We need to build a variable whose basetype is the
-                // fake sequence rather than the cdmfield type
-                // First, build a variable using the existing cdmfield
-                dapfield = buildvariable(cdmfield, struct, coredims);
-                // Now modify it to use the fake sequence
-                dapfield.setBaseType(seq);
-            } else {
-                dapfield = buildvariable(cdmfield, struct, fielddims);
-            }
-            struct.addField(dapfield);
-        }
-        return struct;
-    }
-
-    protected DapVariable
-    buildvariable(Variable cdmbasevar, DapNode parent, List<Dimension> cdmdims)
-            throws DapException
-    {
-        DapVariable dapvar = null;
-        CDMSort sort = cdmbasevar.getSort();
-        switch (sort) {
-            case VARIABLE:
-                switch (cdmbasevar.getDataType()) {
-                    default:
-                        dapvar = buildatomicvar(cdmbasevar, parent);
-                        break;
-                    case ENUM1:
-                    case ENUM2:
-                    case ENUM4:
-                        dapvar = buildenumvar(cdmbasevar);
-                        break;
-                    case OPAQUE:
-                        dapvar = buildopaquevar(cdmbasevar);
-                        break;
-                    case STRING:
-                        dapvar = buildstringvar(cdmbasevar);
-                        break;
-                    case STRUCTURE:
-                    case SEQUENCE:
-                        assert false : "Internal error"; // How could this ever happen?
-                        break;
-
-                }
-                builddimrefs(dapvar, cdmdims);
-                break;
-            case STRUCTURE:
-                dapvar = buildstructvar(cdmbasevar);
-                builddimrefs(dapvar, cdmdims);
-                break;
-            case SEQUENCE:
-            default:
-                assert false : "Internal Error";
-        }
-        if (parent != null)
-            addToParent(parent, dapvar);
-        return dapvar;
-    }
-
-    protected DapVariable
-    buildatomicvar(Variable cdmvar, DapNode parent)
-            throws DapException
-    {
-        // Atomic => not opaque and not enum
-        DapType basetype = CDMTypeFcns.cdmtype2daptype(cdmvar.getDataType());
-        if (basetype == null)
-            throw new DapException("DapFile: illegal CDM variable base type: " + cdmvar.getDataType());
-        DapVariable dapvar = (DapVariable) dmrfactory.newVariable(cdmvar.getShortName(), basetype);
-        recordVar(cdmvar, dapvar);
-        buildattributes(dapvar, cdmvar.getAttributes());
-        if (CDMUtil.hasVLEN(cdmvar)) {
-            // Get the fake sequence associated with this vlen
-            DapSequence seq = vlenmap.get(cdmvar);
-            List<Dimension> coredims = getCoreDimset(cdmvar.getDimensions());
-            // We need to build a variable whose basetype is the
-            // fake sequence rather than the cdmfield type
-            // First, build a variable using the existing cdmfield
-            // Now modify it to use the fake sequence
-            dapvar.setBaseType(seq);
-        }
-        return dapvar;
-    }
-
-    protected DapVariable
-    buildopaquevar(Variable cdmvar)
-            throws DapException
-    {
-        assert (cdmvar.getDataType() == DataType.OPAQUE) : "Internal error";
-        DapVariable dapvar = (DapVariable) dmrfactory.newVariable(cdmvar.getShortName(), DapType.OPAQUE);
-        recordVar(cdmvar, dapvar);
-        buildattributes(dapvar, cdmvar.getAttributes());
-        Object osize = cdmvar.annotation(UCARTAGOPAQUE);
-        if (osize != null) {
-            dapvar.addXMLAttribute(UCARTAGOPAQUE, osize.toString());
-        }
-        return dapvar;
-    }
-
-    protected DapVariable
-    buildstringvar(Variable cdmvar)
-            throws DapException
-    {
-        assert (cdmvar.getDataType() == DataType.STRING) : "Internal error";
-        DapVariable dapvar = (DapVariable) dmrfactory.newVariable(cdmvar.getShortName(), DapType.STRING);
-        recordVar(cdmvar, dapvar);
-        buildattributes(dapvar, cdmvar.getAttributes());
-        return dapvar;
-    }
-
-    protected DapVariable
-    buildenumvar(Variable cdmvar)
-            throws DapException
-    {
-        assert (
-                cdmvar.getDataType() == DataType.ENUM1
-                        || cdmvar.getDataType() == DataType.ENUM2
-                        || cdmvar.getDataType() == DataType.ENUM4
-        ) : "Internal error";
-
-        // Now, we need to locate the actual enumeration decl
-        EnumTypedef enumdef = cdmvar.getEnumTypedef();
-        EnumTypedef trueenumdef = findMatchingEnum(enumdef);
-        // Modify the cdmvar
-        cdmvar.setEnumTypedef(trueenumdef);
-        // Now, map to a DapEnumeration
-        DapEnumeration dapenum = (DapEnumeration) this.nodemap.get(trueenumdef);
-        assert (dapenum != null);
-        DapVariable dapvar = (DapVariable) dmrfactory.newVariable(cdmvar.getShortName(), dapenum);
-        recordVar(cdmvar, dapvar);
-        buildattributes(dapvar, cdmvar.getAttributes());
-        return dapvar;
-    }
-
-    protected DapVariable
-    buildstructvar(Variable cdmvar)
-            throws DapException
-    {
-        assert (cdmvar.getDataType() == DataType.STRUCTURE) : "Internal error";
-        // Find the DapStructure that is the basetype for this var
-        DapStructure struct = compoundmap.get(cdmvar);
-        assert struct != null : "Internal Error";
-        DapVariable dapvar = (DapVariable) dmrfactory.newVariable(cdmvar.getShortName(), struct);
-        recordVar(cdmvar, dapvar);
-        buildattributes(dapvar, cdmvar.getAttributes());
-        return dapvar;
-    }
-
-    /* Create a sequence from a variable with a
-       variable length last dimension.
-       Suppose we have cdm equivalent to this:
-            T var[d1]...[dn]][*]
-       We convert to the following
-           <Sequence name="var">
-             <T name="var"/>
-             <Dim name=d1/>
-             ...
-             <Dim name=dn/>
-           </Sequence>
-    */
-
-    protected DapSequence
-    buildseqtype(Variable cdmvar)
-            throws DapException
-    {
-        cdmvar = CDMUtil.unwrap(cdmvar);
-        assert (CDMUtil.hasVLEN(cdmvar));
-        DataType dt = cdmvar.getDataType();
-        DapType daptype = CDMTypeFcns.cdmtype2daptype(dt);
-        DapSequence seq = (DapSequence) dmrfactory.newSequence(cdmvar.getShortName());
-        // fill DapSequence with a single field; note that the dimensions
-        // are elided because they will attach to the sequence variable,
-        // not the field
-        DapVariable field = dmrfactory.newVariable(cdmvar.getShortName(), daptype);
-        seq.addField(field);
-        field.setParent(seq);
-        recordSeq(cdmvar, seq);
-        return seq;
-    }
-
-    /**
-     * Walk this variable, including fields, to construct sequence types
-     * for any contained vlen dimensions
-     *
-     * @param cdmvar variable to walk
-     */
-
-    protected void
-    buildseqtypes(Variable cdmvar)
-            throws DapException
-    {
-        if (CDMUtil.hasVLEN(cdmvar)) {
-            buildseqtype(cdmvar);
-        }
-        if (cdmvar.getDataType() == DataType.STRUCTURE
-                || cdmvar.getDataType() == DataType.SEQUENCE) {
-            Structure struct = (Structure) cdmvar;
-            List<Variable> fields = struct.getVariables();
-            for (int i = 0; i < fields.size(); i++) {
-                Variable field = fields.get(i);
-                buildseqtypes(field); // recurse for inner vlen dims
-            }
-        }
-    }
-
-    protected void
-    buildattributes(DapNode node, List<Attribute> attributes)
-            throws DapException
-    {
-        for (Attribute attr : attributes) {
-            if (!suppress(attr.getShortName())) {
-                DapAttribute dapattr = buildattribute(attr);
-                node.addAttribute(dapattr);
-            }
-        }
-    }
-
-    protected DapAttribute
-    buildattribute(Attribute cdmattr)
-            throws DapException
-    {
-        DapType attrtype = CDMTypeFcns.cdmtype2daptype(cdmattr.getDataType());
-        EnumTypedef cdmenum = cdmattr.getEnumType();
-        boolean enumfillvalue = (cdmattr.getShortName().equals(FILLVALUE)
-                && cdmenum != null);
-        DapEnumeration dapenum = null;
-
-        // We need to handle _FillValue specially if the
-        // the variable is enum typed.
-        if (enumfillvalue) {
-            cdmenum = findMatchingEnum(cdmenum);
-            // Make sure the cdm attribute has type enumx
-            if (!cdmenum.getBaseType().isEnum())
-                throw new DapException("CDM _FillValue attribute type is not enumX");
-            // Modify the attr
-            cdmattr.setEnumType(cdmenum);
-            // Now, map to a DapEnumeration
-            dapenum = (DapEnumeration) this.nodemap.get(cdmenum);
-            if (dapenum == null)
-                throw new DapException("Illegal CDM variable attribute type: " + cdmenum);
-            attrtype = dapenum;
-        }
-        if (attrtype == null)
-            throw new DapException("DapFile: illegal CDM variable attribute type: " + cdmattr.getDataType());
-        DapAttribute dapattr = (DapAttribute) dmrfactory.newAttribute(cdmattr.getShortName(), attrtype);
-        recordNode(cdmattr, dapattr);
-        // Transfer the values
-        Array values = cdmattr.getValues();
-        if (!validatecdmtype(cdmattr.getDataType(), values.getElementType()))
-            throw new DapException("Attr type versus attribute data mismatch: " + values.getElementType());
-        IndexIterator iter = values.getIndexIterator();
-        String[] valuelist = null;
-        Object vec = CDMTypeFcns.createVector(cdmattr.getDataType(), values.getSize());
-        for (int i = 0; iter.hasNext(); i++) {
-            java.lang.reflect.Array.set(vec, i, iter.next());
-        }
-        valuelist = (String[]) Convert.convert(DapType.STRING, attrtype, vec);
-        dapattr.setValues(valuelist);
-        return dapattr;
-    }
-
-    /**
-     * Assign dimensions to a variable
-     *
-     * @param dapvar  The variable to which we wish to assign dimensions
-     * @param cdmdims The cdm dimensions from which we will find the dimension info
-     */
-    protected void
-    builddimrefs(DapVariable dapvar, List<Dimension> cdmdims)
-            throws DapException
-    {
-        if (cdmdims == null || cdmdims.size() == 0)
-            return;
-        // It is unfortunately the case that the dimensions
-        // associated with the variable are not
-        // necessarily the same object as those dimensions
-        // as declared, so we need to use a non-trivial
-        // matching algorithm.
-        for (Dimension cdmdim : cdmdims) {
-            DapDimension dapdim = null;
-            if (cdmdim.isShared()) {
-                Dimension declareddim = finddimdecl(cdmdim);
-                if (declareddim == null)
-                    throw new DapException("Unprocessed cdm dimension: " + cdmdim);
-                dapdim = (DapDimension) this.nodemap.get(declareddim);
-                assert dapdim != null;
-            } else if (cdmdim.isVariableLength()) {// ignore
-                continue;
-            } else {//anonymous
-                dapdim = builddim(cdmdim);
-            }
-            assert (dapdim != null) : "Internal error";
-            dapvar.addDimension(dapdim);
-        }
-    }
-
-    protected void
-    processmappedvariables(Group g)
-            throws DapException
-    {
-        for (Variable v0 : g.getVariables()) {
-            Variable cdmvar = CDMUtil.unwrap(v0);
-            if (cdmvar == null)
-                throw new DapException("NetcdfDataset synthetic variable: " + v0);
-            DapNode dapvar = this.varmap.get(cdmvar);
-            if (dapvar == null)
-                throw new DapException("Unknown variable: " + cdmvar);
-            if (!(dapvar instanceof DapVariable))
-                throw new DapException("CDMVariable not mapping to dap variable: " + cdmvar);
-            buildmaps((DapVariable) dapvar, v0);
-        }
-    }
-
-
-    /**
-     * @param dapvar The variable to which we wish to assign maps
-     * @param var    The NetcdfDataset variable from which to extract coord system
-     */
-    protected void
-    buildmaps(DapVariable dapvar, Variable var)
-            throws DapException
-    {
-        // See if this cdm variable has one (or more) coordinate system
-        List<CoordinateSystem> css = null;
-        if (var.getSort() == CDMSort.VARIABLE) {
-            VariableDS vds = (VariableDS) var;
-            css = vds.getCoordinateSystems();
-        } else {
-            StructureDS sds = (StructureDS) var;
-            css = sds.getCoordinateSystems();
-        }
-        if (css != null && css.size() > 0) {
-            // Not sure what to do with multiple coordinate systems
-            // For now, only use the first
-            CoordinateSystem coordsystems = css.get(0);
-            for (CoordinateAxis axis : coordsystems.getCoordinateAxes()) {
-                // First step is to find the dap variable
-                // corresponding to the map
-                VariableDS vds = (VariableDS) axis.getOriginalVariable();
-                if (vds != null) {
-                    Variable v = CDMUtil.unwrap(vds);
-                    if (v != null) {
-                        DapVariable mapvar = varmap.get(v);
-                        if (mapvar == null)
-                            throw new DapException("Illegal map variable:" + v.toString());
-                        if (!mapvar.isAtomic())
-                            throw new DapException("Non-atomic map variable:" + v.toString());
-                        // Ignore maps where the map variable is inside this scope
-                        /*
-                            if(!mapvar.isTopLevel()) {
-                            DapNode parent = mapvar.getContainer();
-                            switch (parent.getSort()) {
-                            case SEQUENCE:
-                            case STRUCTURE:
-                                if(dapvar.getBaseType() == parent) // Do we need to do transitive closure?
-                                    throw new DapException("Map var cannot be in same structure as map");
-                                break;
-                            default:
-                                assert false : "Unexpected container type";
-                            }
-                            */
-                        DapMap map = (DapMap) dmrfactory.newMap(mapvar);
-                        dapvar.addMap(map);
-                    }
-                }
-            }
-        }
-    }
-
-    protected DapGroup
-    buildgroup(Group cdmgroup)
-            throws DapException
-    {
-        DapGroup dapgroup = (DapGroup) dmrfactory.newGroup(cdmgroup.getShortName());
-        recordNode(cdmgroup, dapgroup);
-        dapgroup.setShortName(cdmgroup.getShortName());
-        fillgroup(dapgroup, cdmgroup);
-        return dapgroup;
-    }
-
-    //////////////////////////////////////////////////
-    // Utilities
-
-    /**
-     * Unfortunately, the CDM Iosp does not
-     * actually use the declared enums. Rather,
-     * for every enum type'd variable, a new
-     * enum decl is defined. So, we need
-     * to find the original enum decl that matches
-     * the variable's enum.
-     */
-
-    protected EnumTypedef
-    findMatchingEnum(EnumTypedef varenum)
-            throws DapException
-    {
-        List<EnumTypedef> candidates = new ArrayList<>();
-        for (Map.Entry<DapNode, CDMNode> entry : this.nodemap.getCDMMap().entrySet()) {
-            CDMNode cdmnode = entry.getValue();
-            if (cdmnode.getSort() != CDMSort.ENUMERATION)
-                continue;
-            // Compare the enumeration (note names will differ)
-            EnumTypedef target = (EnumTypedef) cdmnode;
-            /* Ideally, we should test the types of the enums,
-               but, unfortunately, the var enum is always enum4.
-            if(target.getBaseType() != varenum.getBaseType())
-                continue;
-            */
-            Map<Integer, String> targetmap = target.getMap();
-            Map<Integer, String> varmap = varenum.getMap();
-            if (targetmap.size() != varmap.size())
-                continue;
-            boolean match = true; // until otherwise shown
-            for (Map.Entry<Integer, String> tpair : targetmap.entrySet()) {
-                String tname = tpair.getValue();
-                int value = (int) tpair.getKey();
-                boolean found = false;
-                for (Map.Entry<Integer, String> vpair : varmap.entrySet()) {
-                    if (tname.equals(vpair.getValue()) && value == (int) vpair.getKey()) {
-                        found = true;
-                        break;
-                    }
-                }
-                if (!found) {
-                    match = false;
-                    break;
-                }
-            }
-            if (!match)
-                continue;
-
-            // Save it unless it is shadowed by a closer enum
-            boolean shadowed = false;
-            for (EnumTypedef etd : candidates) {
-                if (shadows(etd.getGroup(), target.getGroup())) {
-                    shadowed = true;
-                    break;
-                }
-            }
-            if (!shadowed)
-                candidates.add(target);
-        }
-
-        switch (candidates.size()) {
-            case 0:
-                throw new DapException("CDMDSP: No matching enum type decl: " + varenum.getShortName());
-            case 1:
-                break;
-            default:
-                throw new DapException("CDMDSP: Multiple matching enum type decls: " + varenum.getShortName());
-        }
-        return candidates.get(0);
-    }
-
-    protected boolean
-    shadows(Group parent, Group child)
-    {
-        if (child == parent)
-            return true;
-        Group candidate = child;
-        do {
-            candidate = candidate.getGroup();
-        } while (candidate != null && candidate != parent);
-        return (candidate == parent);
-    }
-
-    // Convert cdm size to DapDimension size
-    protected long
-    dapsize(Dimension cdmdim)
-    {
-        assert (!cdmdim.isVariableLength());
-        return (long) cdmdim.getLength();
-    }
-
-    protected boolean
-    validatecdmtype(DataType datatype, Class typeclass)
-    {
-        switch (datatype) {
-            case CHAR:
-                return typeclass == char.class;
-            case BYTE:
-            case UBYTE:
-                return typeclass == byte.class;
-            case SHORT:
-            case USHORT:
-                return typeclass == short.class;
-            case INT:
-            case UINT:
-                return typeclass == int.class;
-            case LONG:
-            case ULONG:
-                return typeclass == long.class;
-            case FLOAT:
-                return typeclass == float.class;
-            case DOUBLE:
-                return typeclass == double.class;
-            case STRING:
-                return typeclass == String.class;
-            case OPAQUE:
-                return typeclass == Byte[].class;
-            // For these, return the integer basetype
-            case ENUM1:
-                return typeclass == byte.class;
-            case ENUM2:
-                return typeclass == short.class;
-            case ENUM4:
-                return typeclass == int.class;
-
-            // Undefined
-            case SEQUENCE:
-            case STRUCTURE:
-            default:
-                break;
-        }
-        return false;
-    }
-
-
-    protected Dimension
-    finddimdecl(Dimension dimref)
-    {
-        // Search on the full name, but be careful,
-        // the rule is that the declared dimension's fqn
-        // must be a prefix of the dimension reference.
-        for (Map.Entry<DapNode, CDMNode> entry : this.nodemap.getCDMMap().entrySet()) {
-            if (entry.getValue().getSort() != CDMSort.DIMENSION)
-                continue;
-            Dimension d = (Dimension) entry.getValue();
-            if (isDimDeclFor(d, dimref))
-                return d;
-        }
-        return null;
-    }
-
-    protected boolean isDimDeclFor(Dimension decl, Dimension ref)
-    {
-        if(!decl.isShared())
-            return false; // Has no name
-        // First check shortname and size
-        if (!decl.getShortName().equals(ref.getShortName()))
-            return false;
-        if (decl.getLength() != ref.getLength())
-            return false;
-        // Make sure they are in the same group
-        String dprefix = decl.getGroup().getFullName();
-        String rprefix = ref.getGroup().getFullName();
-        return (dprefix.equals(rprefix));
-    }
-
-    /*protected String
-    fixvalue(Object o, DapType datatype)
-    {
-        TypeSort atype = datatype.getTypeSort();
-        if(o instanceof Character) {
-            long l = (long) ((Character) o).charValue();
-            if(atype.isUnsigned())
-                l = l & 0xffL;
-            o = Long.valueOf(l);
-        } else if(o instanceof Float || o instanceof Double) {
-            if(atype == TypeSort.Float32)
-                o = Float.valueOf(((Number) o).floatValue());
-            else if(atype == TypeSort.Float64)
-                o = Double.valueOf(((Number) o).doubleValue());
-            else
-                assert false : "Internal error";
-        } else if(o instanceof Number) {
-            long l = ((Number) o).longValue();
-            switch (atype) {
-            case Char:
-            case UInt8:
-                l = l & 0xffL;
-                break;
-            case UInt16:
-                l = l & 0xffffL;
-                break;
-            case UInt32:
-                l = l & 0xffffffffL;
-                break;
-            default:
-                break;
-            }
-            o = Long.valueOf(l);
-        } else if(o instanceof String) {
-            o = o.toString();
-        } else if(o instanceof ByteBuffer) {
-            // leave it unchanged
-        } else if(o instanceof byte[]) {
-            o = ByteBuffer.wrap((byte[]) o);
-        } else if(o instanceof Byte[]) {
-            Byte[] ob = (Byte[]) o;
-            byte[] bb = new byte[ob.length];
-            for(int i = 0; i < bb.length; i++) {
-                bb[i] = (byte) ob[i];
-            }
-            o = ByteBuffer.wrap(bb);
-        } //else { // leave it unchanged
-        return o;
-    } */
-
-    //////////////////////////////////////////////////
-
-    protected NetcdfFile
-    createNetcdfFile(String location, CancelTask canceltask)
-            throws DapException
-    {
-        try {
-            NetcdfFile ncfile = NetcdfFile.open(location, -1, canceltask, getContext());
-            return ncfile;
-        } catch (DapException de) {
-            if (DEBUG)
-                de.printStackTrace();
-            throw de;
-        } catch (Exception e) {
-            if (DEBUG)
-                e.printStackTrace();
-            throw new DapException(e);
-        }
-    }
-
-    //////////////////////////////////////////////////
-    // Utilities
-
-    /**
-     * Strip vlen dimensions from a set of dimensions
-     *
-     * @param dimset
-     * @return subset of dimset with (trailing) vlen removed
-     * @throws DapException
-     */
-    static List<Dimension>
-    getCoreDimset(List<Dimension> dimset)
-            throws DapException
-    {
-        if (dimset == null) return null;
-        List<Dimension> core = new ArrayList<>();
-        int pos = -1;
-        int count = 0;
-        for (int i = 0; i < dimset.size(); i++) {
-            if (dimset.get(i).isVariableLength()) {
-                pos = i;
-                count++;
-            } else
-                core.add(dimset.get(i));
-        }
-        if ((pos != dimset.size() - 1) || count > 1)
-            throw new DapException("Unsupported use of (*) Dimension");
-        return core;
-    }
-
-    /**
-     * Some attributes that are added by the NetcdfDataset
-     * need to be kept out of the DMR. This function
-     * defines that set.
-     *
-     * @param attrname A non-escaped attribute name to be tested for suppression
-     * @return true if the attribute should be suppressed, false otherwise.
-     */
-    protected boolean suppress(String attrname)
-    {
-        if (attrname.startsWith("_Coord")) return true;
-        if (attrname.equals(CDM.UNSIGNED))
-            return true;
-        return false;
-    }
-
-    protected void
-    addToParent(DapNode parent, DapVariable dapvar)
-            throws DapException
-    {
-        assert (parent != null);
-        switch (parent.getSort()) {
-            case GROUP:
-            case DATASET:
-                ((DapGroup) parent).addDecl(dapvar);
-                break;
-            case SEQUENCE:
-            case STRUCTURE:
-                dapvar.setParent(parent);
-                break;
-            default:
-                assert (false) : "Internal error";
-        }
-    }
-
-}
diff --git a/dap4/d4tests/build.gradle b/dap4/d4tests/build.gradle
new file mode 100644
index 0000000000..1ba553d4b4
--- /dev/null
+++ b/dap4/d4tests/build.gradle
@@ -0,0 +1,55 @@
+apply from: "$rootDir/gradle/any/dependencies.gradle"
+apply from: "$rootDir/gradle/any/java.gradle"
+apply from: "$rootDir/gradle/any/testing.gradle"
+apply from: "$rootDir/gradle/any/coverage.gradle"
+// d4tests is not published
+apply from: "$rootDir/gradle/any/gretty.gradle"
+
+dependencies {
+    // A lot of these dependencies should be in the testRuntime config, not testCompile.
+
+    testCompile project(':dap4:d4core')
+    testCompile project(':dap4:d4lib')
+    testCompile project(':dap4:d4cdm')
+    testCompile project(':cdm')
+    testCompile project(':httpservices')
+    
+    testCompile libraries["javax.servlet-api"]
+    testCompile libraries["slf4j-api"]
+
+    compile libraries["slf4j-api"]
+    runtime libraries["log4j-slf4j-impl"]
+    runtime libraries["log4j-web"]
+    testRuntime libraries["logback-classic"]
+
+    // Spring
+    compile libraries["spring-test"]
+    compile libraries["spring-core"]
+    compile libraries["spring-context"]
+    compile libraries["spring-beans"]
+    compile libraries["spring-web"]
+    compile libraries["spring-webmvc"]
+}
+
+test {
+    systemProperties['testargs'] = System.getProperty("testargs", "")
+    
+    include 'dap4/test/TestCDMClient.class'
+    include 'dap4/test/TestConstraints.class'
+    include 'dap4/test/TestDSP.class'
+    include 'dap4/test/TestDSR.class'
+    include 'dap4/test/TestNc4Iosp.class'
+    include 'dap4/test/TestParserCE.class'
+    include 'dap4/test/TestParserDMR.class'
+    include 'dap4/test/TestServlet.class'
+    include 'dap4/test/TestServletConstraints.class'
+    include 'dap4/test/TestFrontPage.class'
+    //include 'dap4/test/TestFilters.class'
+    //include 'dap4/test/TestH5Iosp.class'
+    //include 'dap4/test/TestHyrax.class'
+    //include 'dap4/test/TestPrinter.class'
+    //include 'dap4/test/TestSerial.class'
+
+    dependsOn("farmBeforeIntegrationTest")
+    finalizedBy("farmAfterIntegrationTest")
+}
\ No newline at end of file
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_anon_dim.syn.2.raw.txt b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_anon_dim.syn.2.raw.txt
new file mode 100644
index 0000000000..3aec08b1c9
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_anon_dim.syn.2.raw.txt
@@ -0,0 +1,12 @@
+netcdf test_anon_dim.syn.2 {
+  variables:
+    int vu32(4);
+      string vu32:_DAP4_Checksum_CRC32 = "0x417bc794";
+
+  // global attributes:
+  string :_dap4.ce = "/vu32[0:3]";
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+vu32 =
+  {-1169720286, -920699049, -2088732436, 1060190036}
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_anon_dim.syn.raw.txt b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_anon_dim.syn.raw.txt
new file mode 100644
index 0000000000..0819467d8f
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_anon_dim.syn.raw.txt
@@ -0,0 +1,11 @@
+netcdf test_anon_dim.syn {
+  variables:
+    int vu32(6);
+      string vu32:_DAP4_Checksum_CRC32 = "0x1aca2718";
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+vu32 =
+  {-1169720286, -920699049, -2088732436, 1060190036, -1123468835, 922940053}
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_atomic_array.nc.5.raw.txt b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_atomic_array.nc.5.raw.txt
new file mode 100644
index 0000000000..bfc1a9a698
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_atomic_array.nc.5.raw.txt
@@ -0,0 +1,30 @@
+netcdf test_atomic_array.nc.5 {
+  variables:
+    ubyte vu8(1, 2);
+      string vu8:_DAP4_Checksum_CRC32 = "0x1a9eb5b3";
+
+    double vd(1);
+      string vd:_DAP4_Checksum_CRC32 = "0x74c1a1f1";
+
+    string vs(1, 1);
+      string vs:_DAP4_Checksum_CRC32 = "0x15293f21";
+
+    opaque vo(1, 1);
+      string vo:_DAP4_Checksum_CRC32 = "0x225778dc";
+
+  // global attributes:
+  string :_dap4.ce = "/vu8[1][0:2:2];/vd[1];/vs[1][0];/vo[0][1]";
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+vu8 =
+  {
+    {3, 5}
+  }
+vd =
+  {1024.8}
+vs =
+  {  "Καλημέα"
+  }
+vo =  0xabcdef0000000000;
+
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_atomic_array.nc.8.raw.txt b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_atomic_array.nc.8.raw.txt
new file mode 100644
index 0000000000..8c33c36312
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_atomic_array.nc.8.raw.txt
@@ -0,0 +1,12 @@
+netcdf test_atomic_array.nc.8 {
+  variables:
+    short v16(3);
+      string v16:_DAP4_Checksum_CRC32 = "0xb4fb7f89";
+
+  // global attributes:
+  string :_dap4.ce = "/v16[0:1,3]";
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+v16 =
+  {1, 2, 4}
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_atomic_array.nc.9.raw.txt b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_atomic_array.nc.9.raw.txt
new file mode 100644
index 0000000000..7137b40bd6
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_atomic_array.nc.9.raw.txt
@@ -0,0 +1,12 @@
+netcdf test_atomic_array.nc.9 {
+  variables:
+    short v16(3);
+      string v16:_DAP4_Checksum_CRC32 = "0xa0d9e652";
+
+  // global attributes:
+  string :_dap4.ce = "/v16[3,0:1]";
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+v16 =
+  {4, 1, 2}
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_atomic_array.nc.raw.txt b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_atomic_array.nc.raw.txt
new file mode 100644
index 0000000000..4aafbcac3b
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_atomic_array.nc.raw.txt
@@ -0,0 +1,63 @@
+netcdf test_atomic_array {
+  types:
+    byte enum cloud_class_t { Clear = 0, Cumulonimbus = 1, Stratus = 2, Stratocumulus = 3, Cumulus = 4, Altostratus = 5, Nimbostratus = 6, Altocumulus = 7, Cirrostratus = 8, Cirrocumulus = 9, Cirrus = 10, Missing = 127};
+
+  dimensions:
+    d1 = 1;
+    d2 = 2;
+    d3 = 3;
+    d4 = 4;
+    d5 = 5;
+  variables:
+    ubyte vu8(d2, d3);
+      string vu8:_DAP4_Checksum_CRC32 = "0xd42f6486";
+
+    short v16(d4);
+      string v16:_DAP4_Checksum_CRC32 = "0x92991416";
+
+    uint vu32(d2, d3);
+      string vu32:_DAP4_Checksum_CRC32 = "0x0c56f0f2";
+
+    double vd(d2);
+      string vd:_DAP4_Checksum_CRC32 = "0x7c09cbae";
+
+    char vc(d2);
+      string vc:_DAP4_Checksum_CRC32 = "0x63add807";
+
+    string vs(d2, d2);
+      string vs:_DAP4_Checksum_CRC32 = "0x672f70c4";
+
+    opaque vo(d1, d2);
+      string vo:_DAP4_Checksum_CRC32 = "0x2757560d";
+
+    enum cloud_class_t primary_cloud(d5);
+      string primary_cloud:_FillValue = "Missing";
+      string primary_cloud:_DAP4_Checksum_CRC32 = "0xb58a627a";
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+vu8 =
+  {
+    {255, 1, 2},
+    {3, 4, 5}
+  }
+v16 =
+  {1, 2, 3, 4}
+vu32 =
+  {
+    {5, 4, 3},
+    {2, 1, 0}
+  }
+vd =
+  {17.9, 1024.8}
+vc =  "@&"
+vs =
+  {  "hello	world",   "hello	world",  "hello	world",   "hello	world"
+  }
+vo =  0x0123456789abcdef,
+  0x0123456789abcdef;
+
+primary_cloud =
+  {0, 2, 0, 1, 127}
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_atomic_array.syn.raw.txt b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_atomic_array.syn.raw.txt
new file mode 100644
index 0000000000..e1388d3f78
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_atomic_array.syn.raw.txt
@@ -0,0 +1,63 @@
+netcdf test_atomic_array.syn {
+  types:
+    byte enum cloud_class_t { Clear = 0, Cumulonimbus = 1, Stratus = 2, Stratocumulus = 3, Cumulus = 4, Altostratus = 5, Nimbostratus = 6, Altocumulus = 7, Cirrostratus = 8, Cirrocumulus = 9, Cirrus = 10, Missing = 127};
+
+  dimensions:
+    d1 = 1;
+    d2 = 2;
+    d3 = 3;
+    d4 = 4;
+    d5 = 5;
+  variables:
+    ubyte vu8(d2, d3);
+      string vu8:_DAP4_Checksum_CRC32 = "0xd79bd598";
+
+    short v16(d4);
+      string v16:_DAP4_Checksum_CRC32 = "0xa40ee271";
+
+    uint vu32(d2, d3);
+      string vu32:_DAP4_Checksum_CRC32 = "0xa06ca308";
+
+    double vd(d2);
+      string vd:_DAP4_Checksum_CRC32 = "0x7ee0fb67";
+
+    char vc(d2);
+      string vc:_DAP4_Checksum_CRC32 = "0x7cee5238";
+
+    string vs(d2, d2);
+      string vs:_DAP4_Checksum_CRC32 = "0x9d474c4c";
+
+    opaque vo(d1, d2);
+      string vo:_DAP4_Checksum_CRC32 = "0xd4809521";
+
+    enum cloud_class_t primary_cloud(d5);
+      string primary_cloud:_FillValue = "Missing";
+      string primary_cloud:_DAP4_Checksum_CRC32 = "0x94b74cf7";
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+vu8 =
+  {
+    {186, 201, 131},
+    {63, 189, 55}
+  }
+v16 =
+  {-341, -21899, -13413, -22144}
+vu32 =
+  {
+    {2367803413, 3586730583, 511843988},
+    {3754752863, 2950934681, 2366232135}
+  }
+vd =
+  {0.21787008119279183, 0.6024507919967678}
+vc =  "CO"
+vs =
+  {  "{S",   "{S",  "{S",   "{S"
+  }
+vo =  0xa2177aa7287c04fa8bb57bcdf76ec80f,
+  0xa2177aa7287c04fa8bb57bcdf76ec80f;
+
+primary_cloud =
+  {2, 9, 6, 8, 3}
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_atomic_types.nc.raw.txt b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_atomic_types.nc.raw.txt
new file mode 100644
index 0000000000..a6cd1e1933
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_atomic_types.nc.raw.txt
@@ -0,0 +1,72 @@
+netcdf test_atomic_types {
+  types:
+    byte enum cloud_class_t { Clear = 0, Cumulonimbus = 1, Stratus = 2, Stratocumulus = 3, Cumulus = 4, Altostratus = 5, Nimbostratus = 6, Altocumulus = 7, Cirrostratus = 8, Cirrocumulus = 9, Cirrus = 10, Missing = 127};
+
+  variables:
+    byte v8;
+      string v8:_DAP4_Checksum_CRC32 = "0x3fba6cad";
+
+    ubyte vu8;
+      string vu8:_DAP4_Checksum_CRC32 = "0xff000000";
+
+    short v16;
+      string v16:_DAP4_Checksum_CRC32 = "0xac6191df";
+
+    ushort vu16;
+      string vu16:_DAP4_Checksum_CRC32 = "0xffff0000";
+
+    int v32;
+      string v32:_DAP4_Checksum_CRC32 = "0x12477cdf";
+
+    uint vu32;
+      string vu32:_DAP4_Checksum_CRC32 = "0xffffffff";
+
+    long v64;
+      string v64:_DAP4_Checksum_CRC32 = "0xccfc5c3c";
+
+    ulong vu64;
+      string vu64:_DAP4_Checksum_CRC32 = "0x2144df1c";
+
+    float vf;
+      string vf:_DAP4_Checksum_CRC32 = "0x8c2a1365";
+
+    double vd;
+      string vd:_DAP4_Checksum_CRC32 = "0xf2bacb72";
+
+    char vc;
+      string vc:_DAP4_Checksum_CRC32 = "0xa4deae1d";
+
+    string vs;
+      string vs:_DAP4_Checksum_CRC32 = "0x3691a6d4";
+
+    opaque vo;
+      string vo:_DAP4_Checksum_CRC32 = "0xd24ddadd";
+
+    enum cloud_class_t primary_cloud;
+      string primary_cloud:_FillValue = "Missing";
+      string primary_cloud:_DAP4_Checksum_CRC32 = "0x3c0c8ea1";
+
+    enum cloud_class_t secondary_cloud;
+      string secondary_cloud:_FillValue = "Missing";
+      string secondary_cloud:_DAP4_Checksum_CRC32 = "0x12b88320";
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+v8 =-128
+vu8 =255
+v16 =-32768
+vu16 =65535
+v32 =2147483647
+vu32 =4294967295
+v64 =9223372036854775807
+vu64 =18446744073709551615
+vf =3.1415927
+vd =3.141592653589793
+vc =@
+vs =  "hello	world"
+vo =  0x0123456789abcdef;
+
+primary_cloud =2
+secondary_cloud =127
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_atomic_types.syn.raw.txt b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_atomic_types.syn.raw.txt
new file mode 100644
index 0000000000..3c302ef4a6
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_atomic_types.syn.raw.txt
@@ -0,0 +1,72 @@
+netcdf test_atomic_types.syn {
+  types:
+    byte enum cloud_class_t { Clear = 0, Cumulonimbus = 1, Stratus = 2, Stratocumulus = 3, Cumulus = 4, Altostratus = 5, Nimbostratus = 6, Altocumulus = 7, Cirrostratus = 8, Cirrocumulus = 9, Cirrus = 10, Missing = 127};
+
+  variables:
+    byte v8;
+      string v8:_DAP4_Checksum_CRC32 = "0x140e363f";
+
+    ubyte vu8;
+      string vu8:_DAP4_Checksum_CRC32 = "0x30ba9599";
+
+    short v16;
+      string v16:_DAP4_Checksum_CRC32 = "0xe353db0e";
+
+    ushort vu16;
+      string vu16:_DAP4_Checksum_CRC32 = "0x31e23870";
+
+    int v32;
+      string v32:_DAP4_Checksum_CRC32 = "0xbad2143f";
+
+    uint vu32;
+      string vu32:_DAP4_Checksum_CRC32 = "0x32e54381";
+
+    long v64;
+      string v64:_DAP4_Checksum_CRC32 = "0x915dfe6e";
+
+    ulong vu64;
+      string vu64:_DAP4_Checksum_CRC32 = "0x9233006a";
+
+    float vf;
+      string vf:_DAP4_Checksum_CRC32 = "0x3d571922";
+
+    double vd;
+      string vd:_DAP4_Checksum_CRC32 = "0xffd91cad";
+
+    char vc;
+      string vc:_DAP4_Checksum_CRC32 = "0x09b9265b";
+
+    string vs;
+      string vs:_DAP4_Checksum_CRC32 = "0x81827ad8";
+
+    opaque vo;
+      string vo:_DAP4_Checksum_CRC32 = "0x2d29db8e";
+
+    enum cloud_class_t primary_cloud;
+      string primary_cloud:_FillValue = "Missing";
+      string primary_cloud:_DAP4_Checksum_CRC32 = "0x4c667a2e";
+
+    enum cloud_class_t secondary_cloud;
+      string secondary_cloud:_FillValue = "Missing";
+      string secondary_cloud:_DAP4_Checksum_CRC32 = "0x4b0bbe37";
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+v8 =58
+vu8 =201
+v16 =896
+vu16 =16177
+v32 =-1123468835
+vu32 =2125143125
+v64 =3059391736915381031
+vu64 =11577488182652895291
+vf =0.5512972
+vd =0.7902673011288164
+vc =*
+vs =  "O,L?c8A%V"
+vo =  0x46f169ef23cbaf9b1febd99e4e16cec9;
+
+primary_cloud =7
+secondary_cloud =3
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_enum.nc.raw.txt b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_enum.nc.raw.txt
new file mode 100644
index 0000000000..b666139c20
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_enum.nc.raw.txt
@@ -0,0 +1,14 @@
+netcdf test_enum {
+  types:
+    byte enum cloud_class_t { Clear = 0, Cumulonimbus = 1, Stratus = 2, Stratocumulus = 3, Cumulus = 4, Altostratus = 5, Nimbostratus = 6, Altocumulus = 7, Cirrostratus = 8, Cirrocumulus = 9, Cirrus = 10, Missing = 127};
+
+  variables:
+    enum cloud_class_t primary_cloud;
+      string primary_cloud:_FillValue = "Missing";
+      string primary_cloud:_DAP4_Checksum_CRC32 = "0x3c0c8ea1";
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+primary_cloud =2
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_enum_2.nc.raw.txt b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_enum_2.nc.raw.txt
new file mode 100644
index 0000000000..62ee4d281a
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_enum_2.nc.raw.txt
@@ -0,0 +1,17 @@
+netcdf test_enum_2 {
+  types:
+    byte enum cloud_class_t { Clear = 0, Cumulonimbus = 1, Stratus = 2, Stratocumulus = 3, Cumulus = 4, Altostratus = 5, Nimbostratus = 6, Altocumulus = 7, Cirrostratus = 8, Cirrocumulus = 9, Cirrus = 10, Missing = 127};
+
+
+  group: h {
+    variables:
+      enum cloud_class_t primary_cloud;
+        string primary_cloud:_FillValue = "Missing";
+        string primary_cloud:_DAP4_Checksum_CRC32 = "0x3c0c8ea1";
+
+  }
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+h/primary_cloud =2
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_enum_array.nc.4.raw.txt b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_enum_array.nc.4.raw.txt
new file mode 100644
index 0000000000..82933a50d3
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_enum_array.nc.4.raw.txt
@@ -0,0 +1,16 @@
+netcdf test_enum_array.nc.4 {
+  types:
+    byte enum cloud_class_t { Clear = 0, Cumulonimbus = 1, Stratus = 2, Stratocumulus = 3, Cumulus = 4, Altostratus = 5, Nimbostratus = 6, Altocumulus = 7, Cirrostratus = 8, Cirrocumulus = 9, Cirrus = 10, Missing = 127};
+
+  variables:
+    enum cloud_class_t primary_cloud(2);
+      string primary_cloud:_FillValue = "Missing";
+      string primary_cloud:_DAP4_Checksum_CRC32 = "0x04e840eb";
+
+  // global attributes:
+  string :_dap4.ce = "/primary_cloud[1:2:4]";
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+primary_cloud =
+  {2, 1}
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_enum_array.nc.raw.txt b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_enum_array.nc.raw.txt
new file mode 100644
index 0000000000..0a2c146f56
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_enum_array.nc.raw.txt
@@ -0,0 +1,17 @@
+netcdf test_enum_array {
+  types:
+    byte enum cloud_class_t { Clear = 0, Cumulonimbus = 1, Stratus = 2, Stratocumulus = 3, Cumulus = 4, Altostratus = 5, Nimbostratus = 6, Altocumulus = 7, Cirrostratus = 8, Cirrocumulus = 9, Cirrus = 10, Missing = 127};
+
+  dimensions:
+    d5 = 5;
+  variables:
+    enum cloud_class_t primary_cloud(d5);
+      string primary_cloud:_FillValue = "Missing";
+      string primary_cloud:_DAP4_Checksum_CRC32 = "0xb58a627a";
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+primary_cloud =
+  {0, 2, 0, 1, 127}
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_fill.nc.raw.txt b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_fill.nc.raw.txt
new file mode 100644
index 0000000000..839f800bfe
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_fill.nc.raw.txt
@@ -0,0 +1,19 @@
+netcdf test_fill {
+  variables:
+    ubyte uv8;
+      string uv8:_DAP4_Checksum_CRC32 = "0x6fbf1d91";
+
+    short v16;
+      string v16:_DAP4_Checksum_CRC32 = "0xc9139fe6";
+
+    uint uv32;
+      uv32:_FillValue = 17;
+      string uv32:_DAP4_Checksum_CRC32 = "0x8437b331";
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+uv8 =240
+v16 =32700
+uv32 =111000
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_groups1.nc.raw.txt b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_groups1.nc.raw.txt
new file mode 100644
index 0000000000..253a698474
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_groups1.nc.raw.txt
@@ -0,0 +1,44 @@
+netcdf test_groups1 {
+  dimensions:
+    dim1 = 5;
+
+  group: g {
+    dimensions:
+      dim2 = 3;
+
+    group: h {
+      dimensions:
+        dim3 = 7;
+      variables:
+        int v1(dim1);
+          string v1:_DAP4_Checksum_CRC32 = "0x1d1d272c";
+
+        float v2(dim2);
+          string v2:_DAP4_Checksum_CRC32 = "0x0fe72d43";
+
+    }
+
+    group: i {
+      dimensions:
+        dim3 = 7;
+      variables:
+        int v1(dim1);
+          string v1:_DAP4_Checksum_CRC32 = "0xa9b4a0fb";
+
+        float v3(dim3);
+          string v3:_DAP4_Checksum_CRC32 = "0x29f1e312";
+
+    }
+  }
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+g/h/v1 =
+  {-876354855, -1761252264, 1723477387, -46827465, 1475147969}
+g/h/v2 =
+  {12.0, -100.0, 9.96921E36}
+g/i/v1 =
+  {2, 3, 5, 7, 11}
+g/i/v3 =
+  {23.0, 29.0, 19.0, 31.0, 17.0, 37.0, 13.0}
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_one_var.nc.raw.txt b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_one_var.nc.raw.txt
new file mode 100644
index 0000000000..2b376e08ab
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_one_var.nc.raw.txt
@@ -0,0 +1,10 @@
+netcdf test_one_var {
+  variables:
+    int t;
+      string t:_DAP4_Checksum_CRC32 = "0xc9e1efe6";
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+t =17
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_one_vararray.nc.1.raw.txt b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_one_vararray.nc.1.raw.txt
new file mode 100644
index 0000000000..4b380edb65
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_one_vararray.nc.1.raw.txt
@@ -0,0 +1,12 @@
+netcdf test_one_vararray.nc.1 {
+  variables:
+    int t(1);
+      string t:_DAP4_Checksum_CRC32 = "0xb6a88010";
+
+  // global attributes:
+  string :_dap4.ce = "/t[1]";
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+t =
+  {37}
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_one_vararray.nc.3.raw.txt b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_one_vararray.nc.3.raw.txt
new file mode 100644
index 0000000000..7e65c1a454
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_one_vararray.nc.3.raw.txt
@@ -0,0 +1,14 @@
+netcdf test_one_vararray.nc.3 {
+  dimensions:
+    d2 = 2;
+  variables:
+    int t(d2);
+      string t:_DAP4_Checksum_CRC32 = "0x42dfb1d0";
+
+  // global attributes:
+  string :_dap4.ce = "/t[0:1]";
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+t =
+  {17, 37}
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_one_vararray.nc.raw.txt b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_one_vararray.nc.raw.txt
new file mode 100644
index 0000000000..f76c579e38
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_one_vararray.nc.raw.txt
@@ -0,0 +1,13 @@
+netcdf test_one_vararray {
+  dimensions:
+    d2 = 2;
+  variables:
+    int t(d2);
+      string t:_DAP4_Checksum_CRC32 = "0x42dfb1d0";
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+t =
+  {17, 37}
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_opaque.nc.raw.txt b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_opaque.nc.raw.txt
new file mode 100644
index 0000000000..54dcb52c2b
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_opaque.nc.raw.txt
@@ -0,0 +1,11 @@
+netcdf test_opaque {
+  variables:
+    opaque vo1;
+      string vo1:_DAP4_Checksum_CRC32 = "0xd24ddadd";
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+vo1 =  0x0123456789abcdef;
+
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_opaque_array.nc.7.raw.txt b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_opaque_array.nc.7.raw.txt
new file mode 100644
index 0000000000..10d45fe22b
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_opaque_array.nc.7.raw.txt
@@ -0,0 +1,13 @@
+netcdf test_opaque_array.nc.7 {
+  variables:
+    opaque vo2(1, 2);
+      string vo2:_DAP4_Checksum_CRC32 = "0xcca386bf";
+
+  // global attributes:
+  string :_dap4.ce = "/vo2[1][0:1]";
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+vo2 =  0xfedcba9876543210,
+  0xfedcba9876543210;
+
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_opaque_array.nc.raw.txt b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_opaque_array.nc.raw.txt
new file mode 100644
index 0000000000..0f2053e984
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_opaque_array.nc.raw.txt
@@ -0,0 +1,16 @@
+netcdf test_opaque_array {
+  dimensions:
+    d2 = 2;
+  variables:
+    opaque vo2(d2, d2);
+      string vo2:_DAP4_Checksum_CRC32 = "0x91581cda";
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+vo2 =  0x0123456789abcdef,
+  0x0123456789abcdef,
+  0x0123456789abcdef,
+  0x0123456789abcdef;
+
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_sequence_1.syn.raw.txt b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_sequence_1.syn.raw.txt
new file mode 100644
index 0000000000..8fd1eb64bf
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_sequence_1.syn.raw.txt
@@ -0,0 +1,23 @@
+netcdf test_sequence_1.syn {
+  variables:
+
+    Sequence {
+      int i1;
+      short sh1;
+    } s(*);
+      string s:_DAP4_Checksum_CRC32 = "0x4ac0ac5e";
+
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+  data:
+    s =
+      {
+        i1 =
+          {-920699049
+          }
+        sh1 =
+          {896
+          }
+      } s
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_struct_array.nc.6.raw.txt b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_struct_array.nc.6.raw.txt
new file mode 100644
index 0000000000..5ca77032b5
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_struct_array.nc.6.raw.txt
@@ -0,0 +1,34 @@
+netcdf test_struct_array.nc.6 {
+  variables:
+
+    Structure {
+      int x;
+        string x:_CoordinateAxisType = "GeoX";
+      int y;
+        string y:_CoordinateAxisType = "GeoY";
+    } s(2, 2);
+      string s:_DAP4_Checksum_CRC32 = "0x324d0ea6";
+
+
+  // global attributes:
+  string :_dap4.ce = "/s[0:2:3][0:1]";
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+s =
+  {
+    x =1
+    y =-1
+  } s(0)
+  {
+    x =17
+    y =37
+  } s(1)
+  {
+    x =-4
+    y =12
+  } s(2)
+  {
+    x =-8
+    y =8
+  } s(3)
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_struct_array.syn.raw.txt b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_struct_array.syn.raw.txt
new file mode 100644
index 0000000000..76531f1451
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_struct_array.syn.raw.txt
@@ -0,0 +1,78 @@
+netcdf test_struct_array.syn {
+  dimensions:
+    dx = 4;
+    dy = 3;
+  variables:
+    float z(dx);
+      string z:_DAP4_Checksum_CRC32 = "0xbef06d05";
+
+    float t(dy);
+      string t:_DAP4_Checksum_CRC32 = "0x165934f0";
+
+
+    Structure {
+      int x;
+        string x:_CoordinateAxisType = "GeoX";
+      int y;
+        string y:_CoordinateAxisType = "GeoY";
+    } s(dx, dy);
+      string s:_DAP4_Checksum_CRC32 = "0xd91a250e";
+
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+z =
+  {0.72765326, 0.785633, 0.513679, 0.24684471}
+t =
+  {0.738422, 0.21488869, 0.49479842}
+s =
+  {
+    x =712320147
+    y =1268468519
+  } s(0)
+  {
+    x =696298400
+    y =989876086
+  } s(1)
+  {
+    x =-1927163883
+    y =-900795134
+  } s(2)
+  {
+    x =-708236713
+    y =1377500019
+  } s(3)
+  {
+    x =511843988
+    y =1699265896
+  } s(4)
+  {
+    x =-540214433
+    y =-914532520
+  } s(5)
+  {
+    x =-1344032615
+    y =-871416961
+  } s(6)
+  {
+    x =-1928735161
+    y =935744880
+  } s(7)
+  {
+    x =-1509955773
+    y =-1707460853
+  } s(8)
+  {
+    x =1145911788
+    y =-415231529
+  } s(9)
+  {
+    x =-278269626
+    y =-1682978013
+  } s(10)
+  {
+    x =-1629885665
+    y =-909240754
+  } s(11)
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_struct_nested.hdf5.raw.txt b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_struct_nested.hdf5.raw.txt
new file mode 100644
index 0000000000..fdd4aa1aad
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_struct_nested.hdf5.raw.txt
@@ -0,0 +1,39 @@
+netcdf test_struct_nested.hdf5 {
+  variables:
+
+    Structure {
+
+      Structure {
+        int x;
+          string x:_CoordinateAxisType = "GeoX";
+        int y;
+          string y:_CoordinateAxisType = "GeoY";
+      } field1;
+
+
+      Structure {
+        int x;
+        int y;
+      } field2;
+
+    } x;
+      string x:_DAP4_Checksum_CRC32 = "0xdfa7461b";
+
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+  data:
+    x =
+      {
+        field1 =
+          {
+            x = 1
+            y = -2
+          } field1(0)
+        field2 =
+          {
+            x = 255
+            y = 90
+          } field2(0)
+      } x(0)
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_struct_nested3.hdf5.raw.txt b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_struct_nested3.hdf5.raw.txt
new file mode 100644
index 0000000000..a165d7033e
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_struct_nested3.hdf5.raw.txt
@@ -0,0 +1,31 @@
+netcdf test_struct_nested3.hdf5 {
+  variables:
+
+    Structure {
+
+      Structure {
+
+        Structure {
+          int field1;
+        } field2;
+
+      } field3;
+
+    } x;
+      string x:_DAP4_Checksum_CRC32 = "0xc9e1efe6";
+
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+  data:
+    x =
+      {
+        field3 =
+          {
+            field2 =
+              {
+                field1 = 17
+              } field2(0)
+          } field3(0)
+      } x(0)
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_struct_type.nc.raw.txt b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_struct_type.nc.raw.txt
new file mode 100644
index 0000000000..64832f765e
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_struct_type.nc.raw.txt
@@ -0,0 +1,21 @@
+netcdf test_struct_type {
+  variables:
+
+    Structure {
+      int x;
+        string x:_CoordinateAxisType = "GeoX";
+      int y;
+        string y:_CoordinateAxisType = "GeoY";
+    } s;
+      string s:_DAP4_Checksum_CRC32 = "0xcf8f9871";
+
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+  data:
+    s =
+      {
+        x = 1
+        y = -2
+      } s(0)
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_utf8.nc.raw.txt b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_utf8.nc.raw.txt
new file mode 100644
index 0000000000..e99cf54c4a
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestCDMClient/baseline/test_utf8.nc.raw.txt
@@ -0,0 +1,12 @@
+netcdf test_utf8 {
+  dimensions:
+    d2 = 2;
+  variables:
+    string vs(d2);
+      string vs:_DAP4_Checksum_CRC32 = "0xfce3cd28";
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+vs =  "Καλημέα",   "Καλημέα"
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_anon_dim.syn.2.raw b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_anon_dim.syn.2.raw
new file mode 100644
index 0000000000..02521f8b96
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_anon_dim.syn.2.raw differ
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_anon_dim.syn.raw b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_anon_dim.syn.raw
new file mode 100644
index 0000000000..90cf83423e
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_anon_dim.syn.raw differ
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_atomic_array.nc.5.raw b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_atomic_array.nc.5.raw
new file mode 100644
index 0000000000..64f2028ca3
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_atomic_array.nc.5.raw differ
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_atomic_array.nc.8.raw b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_atomic_array.nc.8.raw
new file mode 100644
index 0000000000..9c55a80646
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_atomic_array.nc.8.raw differ
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_atomic_array.nc.9.raw b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_atomic_array.nc.9.raw
new file mode 100644
index 0000000000..6f17241329
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_atomic_array.nc.9.raw differ
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_atomic_array.nc.raw b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_atomic_array.nc.raw
new file mode 100644
index 0000000000..9a6e307575
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_atomic_array.nc.raw differ
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_atomic_array.syn.raw b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_atomic_array.syn.raw
new file mode 100644
index 0000000000..30138ab7b1
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_atomic_array.syn.raw differ
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_atomic_types.nc.raw b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_atomic_types.nc.raw
new file mode 100644
index 0000000000..97ddca1028
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_atomic_types.nc.raw differ
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_atomic_types.syn.raw b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_atomic_types.syn.raw
new file mode 100644
index 0000000000..906759bc74
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_atomic_types.syn.raw differ
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_enum.nc.raw b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_enum.nc.raw
new file mode 100644
index 0000000000..ec69756822
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_enum.nc.raw differ
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_enum_2.nc.raw b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_enum_2.nc.raw
new file mode 100644
index 0000000000..d38f5337ff
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_enum_2.nc.raw differ
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_enum_array.nc.4.raw b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_enum_array.nc.4.raw
new file mode 100644
index 0000000000..e89b3c55fd
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_enum_array.nc.4.raw differ
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_enum_array.nc.raw b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_enum_array.nc.raw
new file mode 100644
index 0000000000..60a17c7524
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_enum_array.nc.raw differ
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_fill.nc.raw b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_fill.nc.raw
new file mode 100644
index 0000000000..151559c495
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_fill.nc.raw differ
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_groups1.nc.raw b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_groups1.nc.raw
new file mode 100644
index 0000000000..fc6a4a66d7
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_groups1.nc.raw differ
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_one_var.nc.raw b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_one_var.nc.raw
new file mode 100644
index 0000000000..8b29a0bd17
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_one_var.nc.raw differ
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_one_vararray.nc.1.raw b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_one_vararray.nc.1.raw
new file mode 100644
index 0000000000..814c0ed7bb
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_one_vararray.nc.1.raw differ
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_one_vararray.nc.3.raw b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_one_vararray.nc.3.raw
new file mode 100644
index 0000000000..42ed5d7347
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_one_vararray.nc.3.raw differ
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_one_vararray.nc.raw b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_one_vararray.nc.raw
new file mode 100644
index 0000000000..15ca928b3d
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_one_vararray.nc.raw differ
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_opaque.nc.raw b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_opaque.nc.raw
new file mode 100644
index 0000000000..983427b986
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_opaque.nc.raw differ
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_opaque_array.nc.7.raw b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_opaque_array.nc.7.raw
new file mode 100644
index 0000000000..a7cfeb0f0c
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_opaque_array.nc.7.raw differ
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_opaque_array.nc.raw b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_opaque_array.nc.raw
new file mode 100644
index 0000000000..10aa455370
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_opaque_array.nc.raw differ
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_sequence_1.syn.raw b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_sequence_1.syn.raw
new file mode 100644
index 0000000000..6b83150005
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_sequence_1.syn.raw differ
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_sequence_2.syn.raw b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_sequence_2.syn.raw
new file mode 100644
index 0000000000..2b7c5072b7
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_sequence_2.syn.raw differ
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_struct_array.nc.6.raw b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_struct_array.nc.6.raw
new file mode 100644
index 0000000000..f551cc1020
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_struct_array.nc.6.raw differ
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_struct_array.syn.raw b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_struct_array.syn.raw
new file mode 100644
index 0000000000..06ce49201d
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_struct_array.syn.raw differ
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_struct_nested.hdf5.raw b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_struct_nested.hdf5.raw
new file mode 100644
index 0000000000..9e3de4050b
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_struct_nested.hdf5.raw differ
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_struct_nested3.hdf5.raw b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_struct_nested3.hdf5.raw
new file mode 100644
index 0000000000..8425a19ed3
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_struct_nested3.hdf5.raw differ
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_struct_type.nc.raw b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_struct_type.nc.raw
new file mode 100644
index 0000000000..2b3ffbf1bb
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_struct_type.nc.raw differ
diff --git a/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_utf8.nc.raw b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_utf8.nc.raw
new file mode 100644
index 0000000000..b1518cf6b8
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/TestCDMClient/testinput/test_utf8.nc.raw differ
diff --git a/dap4/d4tests/src/test/data/resources/TestConstraints/baseline/test_anon_dim.syn.2.raw.txt b/dap4/d4tests/src/test/data/resources/TestConstraints/baseline/test_anon_dim.syn.2.raw.txt
new file mode 100644
index 0000000000..3aec08b1c9
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestConstraints/baseline/test_anon_dim.syn.2.raw.txt
@@ -0,0 +1,12 @@
+netcdf test_anon_dim.syn.2 {
+  variables:
+    int vu32(4);
+      string vu32:_DAP4_Checksum_CRC32 = "0x417bc794";
+
+  // global attributes:
+  string :_dap4.ce = "/vu32[0:3]";
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+vu32 =
+  {-1169720286, -920699049, -2088732436, 1060190036}
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestConstraints/baseline/test_atomic_array.nc.5.raw.txt b/dap4/d4tests/src/test/data/resources/TestConstraints/baseline/test_atomic_array.nc.5.raw.txt
new file mode 100644
index 0000000000..bfc1a9a698
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestConstraints/baseline/test_atomic_array.nc.5.raw.txt
@@ -0,0 +1,30 @@
+netcdf test_atomic_array.nc.5 {
+  variables:
+    ubyte vu8(1, 2);
+      string vu8:_DAP4_Checksum_CRC32 = "0x1a9eb5b3";
+
+    double vd(1);
+      string vd:_DAP4_Checksum_CRC32 = "0x74c1a1f1";
+
+    string vs(1, 1);
+      string vs:_DAP4_Checksum_CRC32 = "0x15293f21";
+
+    opaque vo(1, 1);
+      string vo:_DAP4_Checksum_CRC32 = "0x225778dc";
+
+  // global attributes:
+  string :_dap4.ce = "/vu8[1][0:2:2];/vd[1];/vs[1][0];/vo[0][1]";
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+vu8 =
+  {
+    {3, 5}
+  }
+vd =
+  {1024.8}
+vs =
+  {  "Καλημέα"
+  }
+vo =  0xabcdef0000000000;
+
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestConstraints/baseline/test_atomic_array.nc.8.raw.txt b/dap4/d4tests/src/test/data/resources/TestConstraints/baseline/test_atomic_array.nc.8.raw.txt
new file mode 100644
index 0000000000..6c79c85f94
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestConstraints/baseline/test_atomic_array.nc.8.raw.txt
@@ -0,0 +1,12 @@
+netcdf test_atomic_array.nc.8 {
+  variables:
+    short v16(3);
+      string v16:_DAP4_Checksum_CRC32 = "0xc592fc85";
+
+  // global attributes:
+  string :_dap4.ce = "/v16[1:2,2]";
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+v16 =
+  {2, 3, 3}
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestConstraints/baseline/test_atomic_array.nc.9.raw.txt b/dap4/d4tests/src/test/data/resources/TestConstraints/baseline/test_atomic_array.nc.9.raw.txt
new file mode 100644
index 0000000000..b367f16522
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestConstraints/baseline/test_atomic_array.nc.9.raw.txt
@@ -0,0 +1,12 @@
+netcdf test_atomic_array.nc.9 {
+  variables:
+    short v16(3);
+      string v16:_DAP4_Checksum_CRC32 = "0xb6724845";
+
+  // global attributes:
+  string :_dap4.ce = "/v16[2,1:2]";
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+v16 =
+  {3, 2, 3}
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestConstraints/baseline/test_enum_array.nc.4.raw.txt b/dap4/d4tests/src/test/data/resources/TestConstraints/baseline/test_enum_array.nc.4.raw.txt
new file mode 100644
index 0000000000..82933a50d3
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestConstraints/baseline/test_enum_array.nc.4.raw.txt
@@ -0,0 +1,16 @@
+netcdf test_enum_array.nc.4 {
+  types:
+    byte enum cloud_class_t { Clear = 0, Cumulonimbus = 1, Stratus = 2, Stratocumulus = 3, Cumulus = 4, Altostratus = 5, Nimbostratus = 6, Altocumulus = 7, Cirrostratus = 8, Cirrocumulus = 9, Cirrus = 10, Missing = 127};
+
+  variables:
+    enum cloud_class_t primary_cloud(2);
+      string primary_cloud:_FillValue = "Missing";
+      string primary_cloud:_DAP4_Checksum_CRC32 = "0x04e840eb";
+
+  // global attributes:
+  string :_dap4.ce = "/primary_cloud[1:2:4]";
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+primary_cloud =
+  {2, 1}
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestConstraints/baseline/test_one_vararray.nc.1.raw.txt b/dap4/d4tests/src/test/data/resources/TestConstraints/baseline/test_one_vararray.nc.1.raw.txt
new file mode 100644
index 0000000000..4b380edb65
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestConstraints/baseline/test_one_vararray.nc.1.raw.txt
@@ -0,0 +1,12 @@
+netcdf test_one_vararray.nc.1 {
+  variables:
+    int t(1);
+      string t:_DAP4_Checksum_CRC32 = "0xb6a88010";
+
+  // global attributes:
+  string :_dap4.ce = "/t[1]";
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+t =
+  {37}
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestConstraints/baseline/test_one_vararray.nc.3.raw.txt b/dap4/d4tests/src/test/data/resources/TestConstraints/baseline/test_one_vararray.nc.3.raw.txt
new file mode 100644
index 0000000000..7e65c1a454
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestConstraints/baseline/test_one_vararray.nc.3.raw.txt
@@ -0,0 +1,14 @@
+netcdf test_one_vararray.nc.3 {
+  dimensions:
+    d2 = 2;
+  variables:
+    int t(d2);
+      string t:_DAP4_Checksum_CRC32 = "0x42dfb1d0";
+
+  // global attributes:
+  string :_dap4.ce = "/t[0:1]";
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+t =
+  {17, 37}
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestConstraints/baseline/test_opaque_array.nc.7.raw.txt b/dap4/d4tests/src/test/data/resources/TestConstraints/baseline/test_opaque_array.nc.7.raw.txt
new file mode 100644
index 0000000000..f7e6996969
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestConstraints/baseline/test_opaque_array.nc.7.raw.txt
@@ -0,0 +1,13 @@
+netcdf test_opaque_array.nc.7 {
+  variables:
+    opaque vo2(1, 2);
+      string vo2:_DAP4_Checksum_CRC32 = "0x3f3fa5d4";
+
+  // global attributes:
+  string :_dap4.ce = "/vo2[1][0,0]";
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+vo2 =  0xfedcba9876543210,
+  0xfedcba9876543210;
+
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestConstraints/baseline/test_struct_array.nc.6.raw.txt b/dap4/d4tests/src/test/data/resources/TestConstraints/baseline/test_struct_array.nc.6.raw.txt
new file mode 100644
index 0000000000..5ca77032b5
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestConstraints/baseline/test_struct_array.nc.6.raw.txt
@@ -0,0 +1,34 @@
+netcdf test_struct_array.nc.6 {
+  variables:
+
+    Structure {
+      int x;
+        string x:_CoordinateAxisType = "GeoX";
+      int y;
+        string y:_CoordinateAxisType = "GeoY";
+    } s(2, 2);
+      string s:_DAP4_Checksum_CRC32 = "0x324d0ea6";
+
+
+  // global attributes:
+  string :_dap4.ce = "/s[0:2:3][0:1]";
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+s =
+  {
+    x =1
+    y =-1
+  } s(0)
+  {
+    x =17
+    y =37
+  } s(1)
+  {
+    x =-4
+    y =12
+  } s(2)
+  {
+    x =-8
+    y =8
+  } s(3)
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_anon_dim.syn.2.raw.txt b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_anon_dim.syn.2.raw.txt
new file mode 100644
index 0000000000..6075abb9cf
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_anon_dim.syn.2.raw.txt
@@ -0,0 +1,19 @@
+<Dataset
+         name="test_anon_dim.syn"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+
+    <Int32 name="vu32">
+        <Dim size="4"/>
+    </Int32>
+    <Attribute name="_dap4.ce" type="String">
+        <Value value="/vu32[0:3]"/>
+    </Attribute>
+</Dataset>
+/vu32[0] = -1169720286
+/vu32[1] = -920699049
+/vu32[2] = -2088732436
+/vu32[3] = 1060190036
+
diff --git a/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_anon_dim.syn.raw.txt b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_anon_dim.syn.raw.txt
new file mode 100644
index 0000000000..38003ca705
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_anon_dim.syn.raw.txt
@@ -0,0 +1,18 @@
+<Dataset
+         name="test_anon_dim.syn"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+
+    <Int32 name="vu32">
+        <Dim size="6"/>
+    </Int32>
+</Dataset>
+/vu32[0] = -1169720286
+/vu32[1] = -920699049
+/vu32[2] = -2088732436
+/vu32[3] = 1060190036
+/vu32[4] = -1123468835
+/vu32[5] = 922940053
+
diff --git a/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_atomic_array.nc.5.raw.txt b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_atomic_array.nc.5.raw.txt
new file mode 100644
index 0000000000..41955f367f
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_atomic_array.nc.5.raw.txt
@@ -0,0 +1,33 @@
+<Dataset
+         name="test_atomic_array.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+
+
+    <UInt8 name="vu8">
+        <Dim size="1"/>
+        <Dim size="2"/>
+    </UInt8>
+    <Float64 name="vd">
+        <Dim size="1"/>
+    </Float64>
+    <String name="vs">
+        <Dim size="1"/>
+        <Dim size="1"/>
+    </String>
+    <Opaque name="vo">
+        <Dim size="1"/>
+        <Dim size="1"/>
+    </Opaque>
+    <Attribute name="_dap4.ce" type="String">
+        <Value value="/vu8[1][0:2:2];/vd[1];/vs[1][0];/vo[0][1]"/>
+    </Attribute>
+</Dataset>
+/vu8[0,0] = 3
+/vu8[0,1] = 5
+/vd[0] = 1024.800000
+/vs[0,0] = "Καλημέα"
+/vo[0,0] = 0xABCDEF0000000000
+
diff --git a/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_atomic_array.nc.8.raw.txt b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_atomic_array.nc.8.raw.txt
new file mode 100644
index 0000000000..e4cbdafb4c
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_atomic_array.nc.8.raw.txt
@@ -0,0 +1,18 @@
+<Dataset
+         name="test_atomic_array.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+
+    <Int16 name="v16">
+        <Dim size="3"/>
+    </Int16>
+    <Attribute name="_dap4.ce" type="String">
+        <Value value="/v16[0:1,3]"/>
+    </Attribute>
+</Dataset>
+/v16[0] = 1
+/v16[1] = 2
+/v16[2] = 4
+
diff --git a/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_atomic_array.nc.9.raw.txt b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_atomic_array.nc.9.raw.txt
new file mode 100644
index 0000000000..a25d9f0227
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_atomic_array.nc.9.raw.txt
@@ -0,0 +1,18 @@
+<Dataset
+         name="test_atomic_array.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+
+    <Int16 name="v16">
+        <Dim size="3"/>
+    </Int16>
+    <Attribute name="_dap4.ce" type="String">
+        <Value value="/v16[3,0:1]"/>
+    </Attribute>
+</Dataset>
+/v16[0] = 4
+/v16[1] = 1
+/v16[2] = 2
+
diff --git a/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_atomic_array.nc.raw.txt b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_atomic_array.nc.raw.txt
new file mode 100644
index 0000000000..09f8183c46
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_atomic_array.nc.raw.txt
@@ -0,0 +1,89 @@
+<Dataset
+         name="test_atomic_array.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d1" size="1"/>
+    <Dimension name="d2" size="2"/>
+    <Dimension name="d3" size="3"/>
+    <Dimension name="d4" size="4"/>
+    <Dimension name="d5" size="5"/>
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <UInt8 name="vu8">
+        <Dim name="/d2"/>
+        <Dim name="/d3"/>
+    </UInt8>
+    <Int16 name="v16">
+        <Dim name="/d4"/>
+    </Int16>
+    <UInt32 name="vu32">
+        <Dim name="/d2"/>
+        <Dim name="/d3"/>
+    </UInt32>
+    <Float64 name="vd">
+        <Dim name="/d2"/>
+    </Float64>
+    <Char name="vc">
+        <Dim name="/d2"/>
+    </Char>
+    <String name="vs">
+        <Dim name="/d2"/>
+        <Dim name="/d2"/>
+    </String>
+    <Opaque name="vo">
+        <Dim name="/d1"/>
+        <Dim name="/d2"/>
+    </Opaque>
+    <Enum name="primary_cloud" enum="/cloud_class_t">
+        <Dim name="/d5"/>
+        <Attribute name="_FillValue" type="/cloud_class_t">
+            <Value value="Missing"/>
+        </Attribute>
+    </Enum>
+</Dataset>
+/vu8[0,0] = 255
+/vu8[0,1] = 1
+/vu8[0,2] = 2
+/vu8[1,0] = 3
+/vu8[1,1] = 4
+/vu8[1,2] = 5
+/v16[0] = 1
+/v16[1] = 2
+/v16[2] = 3
+/v16[3] = 4
+/vu32[0,0] = 5
+/vu32[0,1] = 4
+/vu32[0,2] = 3
+/vu32[1,0] = 2
+/vu32[1,1] = 1
+/vu32[1,2] = 0
+/vd[0] = 17.900000
+/vd[1] = 1024.800000
+/vc[0] = '@'
+/vc[1] = '&'
+/vs[0,0] = "hello\tworld"
+/vs[0,1] = "\r\n"
+/vs[1,0] = "Καλημέα"
+/vs[1,1] = "abc"
+/vo[0,0] = 0x0123456789ABCDEF
+/vo[0,1] = 0xABCDEF0000000000
+/primary_cloud[0] = Clear
+/primary_cloud[1] = Stratus
+/primary_cloud[2] = Clear
+/primary_cloud[3] = Cumulonimbus
+/primary_cloud[4] = Missing
+
diff --git a/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_atomic_array.syn.raw.txt b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_atomic_array.syn.raw.txt
new file mode 100644
index 0000000000..36a790fe02
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_atomic_array.syn.raw.txt
@@ -0,0 +1,89 @@
+<Dataset
+         name="test_atomic_array.syn"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d1" size="1"/>
+    <Dimension name="d2" size="2"/>
+    <Dimension name="d3" size="3"/>
+    <Dimension name="d4" size="4"/>
+    <Dimension name="d5" size="5"/>
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <UInt8 name="vu8">
+        <Dim name="/d2"/>
+        <Dim name="/d3"/>
+    </UInt8>
+    <Int16 name="v16">
+        <Dim name="/d4"/>
+    </Int16>
+    <UInt32 name="vu32">
+        <Dim name="/d2"/>
+        <Dim name="/d3"/>
+    </UInt32>
+    <Float64 name="vd">
+        <Dim name="/d2"/>
+    </Float64>
+    <Char name="vc">
+        <Dim name="/d2"/>
+    </Char>
+    <String name="vs">
+        <Dim name="/d2"/>
+        <Dim name="/d2"/>
+    </String>
+    <Opaque name="vo">
+        <Dim name="/d1"/>
+        <Dim name="/d2"/>
+    </Opaque>
+    <Enum name="primary_cloud" enum="/cloud_class_t">
+        <Dim name="/d5"/>
+        <Attribute name="_FillValue" type="/cloud_class_t">
+            <Value value="Missing"/>
+        </Attribute>
+    </Enum>
+</Dataset>
+/vu8[0,0] = 186
+/vu8[0,1] = 201
+/vu8[0,2] = 131
+/vu8[1,0] = 63
+/vu8[1,1] = 189
+/vu8[1,2] = 55
+/v16[0] = -341
+/v16[1] = -21899
+/v16[2] = -13413
+/v16[3] = -22144
+/vu32[0,0] = 2367803413
+/vu32[0,1] = 3586730583
+/vu32[0,2] = 511843988
+/vu32[1,0] = 3754752863
+/vu32[1,1] = 2950934681
+/vu32[1,2] = 2366232135
+/vd[0] = 0.217870
+/vd[1] = 0.602451
+/vc[0] = 'C'
+/vc[1] = 'O'
+/vs[0,0] = "{S"
+/vs[0,1] = "gb8^OE$"
+/vs[1,0] = "4a/q%n9;5Y"
+/vs[1,1] = "{fIl?T"\A["
+/vo[0,0] = 0xA2177AA7287C04FA8BB57BCDF76EC80F
+/vo[0,1] = 0x34FA472AA9404DD543143CADED303A75
+/primary_cloud[0] = Stratus
+/primary_cloud[1] = Cirrocumulus
+/primary_cloud[2] = Nimbostratus
+/primary_cloud[3] = Cirrostratus
+/primary_cloud[4] = Stratocumulus
+
diff --git a/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_atomic_types.nc.raw.txt b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_atomic_types.nc.raw.txt
new file mode 100644
index 0000000000..765dba4c4f
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_atomic_types.nc.raw.txt
@@ -0,0 +1,60 @@
+<Dataset
+         name="test_atomic_types.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <Int8 name="v8"/>
+    <UInt8 name="vu8"/>
+    <Int16 name="v16"/>
+    <UInt16 name="vu16"/>
+    <Int32 name="v32"/>
+    <UInt32 name="vu32"/>
+    <Int64 name="v64"/>
+    <UInt64 name="vu64"/>
+    <Float32 name="vf"/>
+    <Float64 name="vd"/>
+    <Char name="vc"/>
+    <String name="vs"/>
+    <Opaque name="vo"/>
+    <Enum name="primary_cloud" enum="/cloud_class_t">
+        <Attribute name="_FillValue" type="/cloud_class_t">
+            <Value value="Missing"/>
+        </Attribute>
+    </Enum>
+    <Enum name="secondary_cloud" enum="/cloud_class_t">
+        <Attribute name="_FillValue" type="/cloud_class_t">
+            <Value value="Missing"/>
+        </Attribute>
+    </Enum>
+</Dataset>
+/v8 = -128
+/vu8 = 255
+/v16 = -32768
+/vu16 = 65535
+/v32 = 2147483647
+/vu32 = 4294967295
+/v64 = 9223372036854775807
+/vu64 = 18446744073709551615
+/vf = 3.141593
+/vd = 3.141593
+/vc = '@'
+/vs = "hello\tworld"
+/vo = 0x0123456789ABCDEF
+/primary_cloud = Stratus
+/secondary_cloud = Missing
+
diff --git a/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_atomic_types.syn.raw.txt b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_atomic_types.syn.raw.txt
new file mode 100644
index 0000000000..a9a08a4564
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_atomic_types.syn.raw.txt
@@ -0,0 +1,60 @@
+<Dataset
+         name="test_atomic_types.syn"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <Int8 name="v8"/>
+    <UInt8 name="vu8"/>
+    <Int16 name="v16"/>
+    <UInt16 name="vu16"/>
+    <Int32 name="v32"/>
+    <UInt32 name="vu32"/>
+    <Int64 name="v64"/>
+    <UInt64 name="vu64"/>
+    <Float32 name="vf"/>
+    <Float64 name="vd"/>
+    <Char name="vc"/>
+    <String name="vs"/>
+    <Opaque name="vo"/>
+    <Enum name="primary_cloud" enum="/cloud_class_t">
+        <Attribute name="_FillValue" type="/cloud_class_t">
+            <Value value="Missing"/>
+        </Attribute>
+    </Enum>
+    <Enum name="secondary_cloud" enum="/cloud_class_t">
+        <Attribute name="_FillValue" type="/cloud_class_t">
+            <Value value="Missing"/>
+        </Attribute>
+    </Enum>
+</Dataset>
+/v8 = 58
+/vu8 = 201
+/v16 = 896
+/vu16 = 16177
+/v32 = -1123468835
+/vu32 = 2125143125
+/v64 = 3059391736915381031
+/vu64 = 11577488182652895291
+/vf = 0.551297
+/vd = 0.790267
+/vc = '*'
+/vs = "O,L?c8A%V"
+/vo = 0x46F169EF23CBAF9B1FEBD99E4E16CEC9
+/primary_cloud = Altocumulus
+/secondary_cloud = Stratocumulus
+
diff --git a/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_enum.nc.raw.txt b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_enum.nc.raw.txt
new file mode 100644
index 0000000000..65ce345aa1
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_enum.nc.raw.txt
@@ -0,0 +1,28 @@
+<Dataset
+         name="test_enum.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <Enum name="primary_cloud" enum="/cloud_class_t">
+        <Attribute name="_FillValue" type="/cloud_class_t">
+            <Value value="Missing"/>
+        </Attribute>
+    </Enum>
+</Dataset>
+/primary_cloud = Stratus
+
diff --git a/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_enum_2.nc.raw.txt b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_enum_2.nc.raw.txt
new file mode 100644
index 0000000000..e1b6095537
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_enum_2.nc.raw.txt
@@ -0,0 +1,30 @@
+<Dataset
+         name="test_enum_2.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <Group name="h">
+        <Enum name="primary_cloud" enum="/cloud_class_t">
+            <Attribute name="_FillValue" type="/cloud_class_t">
+                <Value value="Missing"/>
+            </Attribute>
+        </Enum>
+    </Group>
+</Dataset>
+/h/primary_cloud = Stratus
+
diff --git a/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_enum_array.nc.4.raw.txt b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_enum_array.nc.4.raw.txt
new file mode 100644
index 0000000000..8e99dccdb1
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_enum_array.nc.4.raw.txt
@@ -0,0 +1,34 @@
+<Dataset
+         name="test_enum_array.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <Enum name="primary_cloud" enum="/cloud_class_t">
+        <Dim size="2"/>
+        <Attribute name="_FillValue" type="/cloud_class_t">
+            <Value value="Missing"/>
+        </Attribute>
+    </Enum>
+    <Attribute name="_dap4.ce" type="String">
+        <Value value="/primary_cloud[1:2:4]"/>
+    </Attribute>
+</Dataset>
+/primary_cloud[0] = Stratus
+/primary_cloud[1] = Cumulonimbus
+
diff --git a/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_enum_array.nc.raw.txt b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_enum_array.nc.raw.txt
new file mode 100644
index 0000000000..e25f35477f
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_enum_array.nc.raw.txt
@@ -0,0 +1,34 @@
+<Dataset
+         name="test_enum_array.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d5" size="5"/>
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <Enum name="primary_cloud" enum="/cloud_class_t">
+        <Dim name="/d5"/>
+        <Attribute name="_FillValue" type="/cloud_class_t">
+            <Value value="Missing"/>
+        </Attribute>
+    </Enum>
+</Dataset>
+/primary_cloud[0] = Clear
+/primary_cloud[1] = Stratus
+/primary_cloud[2] = Clear
+/primary_cloud[3] = Cumulonimbus
+/primary_cloud[4] = Missing
+
diff --git a/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_fill.nc.raw.txt b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_fill.nc.raw.txt
new file mode 100644
index 0000000000..8158af3960
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_fill.nc.raw.txt
@@ -0,0 +1,18 @@
+<Dataset
+         name="test_fill.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <UInt8 name="uv8"/>
+    <Int16 name="v16"/>
+    <UInt32 name="uv32">
+        <Attribute name="_FillValue" type="UInt32">
+            <Value value="17"/>
+        </Attribute>
+    </UInt32>
+</Dataset>
+/uv8 = 240
+/v16 = 32700
+/uv32 = 111000
+
diff --git a/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_groups1.nc.raw.txt b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_groups1.nc.raw.txt
new file mode 100644
index 0000000000..dc4213e407
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_groups1.nc.raw.txt
@@ -0,0 +1,50 @@
+<Dataset
+         name="test_groups1.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="dim1" size="5"/>
+    <Group name="g">
+        <Dimension name="dim2" size="3"/>
+        <Group name="h">
+            <Dimension name="dim3" size="7"/>
+            <Int32 name="v1">
+                <Dim name="/dim1"/>
+            </Int32>
+            <Float32 name="v2">
+                <Dim name="/g/dim2"/>
+            </Float32>
+        </Group>
+        <Group name="i">
+            <Dimension name="dim3" size="7"/>
+            <Int32 name="v1">
+                <Dim name="/dim1"/>
+            </Int32>
+            <Float32 name="v3">
+                <Dim name="/g/i/dim3"/>
+            </Float32>
+        </Group>
+    </Group>
+</Dataset>
+/g/h/v1[0] = -876354855
+/g/h/v1[1] = -1761252264
+/g/h/v1[2] = 1723477387
+/g/h/v1[3] = -46827465
+/g/h/v1[4] = 1475147969
+/g/h/v2[0] = 12.000000
+/g/h/v2[1] = -100.000000
+/g/h/v2[2] = 9969209968386869000000000000000000000.000000
+/g/i/v1[0] = 2
+/g/i/v1[1] = 3
+/g/i/v1[2] = 5
+/g/i/v1[3] = 7
+/g/i/v1[4] = 11
+/g/i/v3[0] = 23.000000
+/g/i/v3[1] = 29.000000
+/g/i/v3[2] = 19.000000
+/g/i/v3[3] = 31.000000
+/g/i/v3[4] = 17.000000
+/g/i/v3[5] = 37.000000
+/g/i/v3[6] = 13.000000
+
diff --git a/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_one_var.nc.raw.txt b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_one_var.nc.raw.txt
new file mode 100644
index 0000000000..3ae968ce18
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_one_var.nc.raw.txt
@@ -0,0 +1,10 @@
+<Dataset
+         name="test_one_var.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Int32 name="t"/>
+</Dataset>
+/t = 17
+
diff --git a/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_one_vararray.nc.1.raw.txt b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_one_vararray.nc.1.raw.txt
new file mode 100644
index 0000000000..388b6a9543
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_one_vararray.nc.1.raw.txt
@@ -0,0 +1,16 @@
+<Dataset
+         name="test_one_vararray.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+
+    <Int32 name="t">
+        <Dim size="1"/>
+    </Int32>
+    <Attribute name="_dap4.ce" type="String">
+        <Value value="/t[1]"/>
+    </Attribute>
+</Dataset>
+/t[0] = 37
+
diff --git a/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_one_vararray.nc.3.raw.txt b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_one_vararray.nc.3.raw.txt
new file mode 100644
index 0000000000..db2eb9faae
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_one_vararray.nc.3.raw.txt
@@ -0,0 +1,17 @@
+<Dataset
+         name="test_one_vararray.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d2" size="2"/>
+    <Int32 name="t">
+        <Dim name="/d2"/>
+    </Int32>
+    <Attribute name="_dap4.ce" type="String">
+        <Value value="/t[0:1]"/>
+    </Attribute>
+</Dataset>
+/t[0] = 17
+/t[1] = 37
+
diff --git a/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_one_vararray.nc.raw.txt b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_one_vararray.nc.raw.txt
new file mode 100644
index 0000000000..5cf94b8fd8
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_one_vararray.nc.raw.txt
@@ -0,0 +1,14 @@
+<Dataset
+         name="test_one_vararray.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d2" size="2"/>
+    <Int32 name="t">
+        <Dim name="/d2"/>
+    </Int32>
+</Dataset>
+/t[0] = 17
+/t[1] = 37
+
diff --git a/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_opaque.nc.raw.txt b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_opaque.nc.raw.txt
new file mode 100644
index 0000000000..fc47433248
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_opaque.nc.raw.txt
@@ -0,0 +1,10 @@
+<Dataset
+         name="test_opaque.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Opaque name="vo1"/>
+</Dataset>
+/vo1 = 0x0123456789ABCDEF
+
diff --git a/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_opaque_array.nc.7.raw.txt b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_opaque_array.nc.7.raw.txt
new file mode 100644
index 0000000000..8cf7b6abea
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_opaque_array.nc.7.raw.txt
@@ -0,0 +1,19 @@
+<Dataset
+         name="test_opaque_array.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+
+
+    <Opaque name="vo2">
+        <Dim size="1"/>
+        <Dim size="2"/>
+    </Opaque>
+    <Attribute name="_dap4.ce" type="String">
+        <Value value="/vo2[1][0:1]"/>
+    </Attribute>
+</Dataset>
+/vo2[0,0] = 0xFEDCBA9876543210
+/vo2[0,1] = 0xFEDCBA9999999999
+
diff --git a/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_opaque_array.nc.raw.txt b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_opaque_array.nc.raw.txt
new file mode 100644
index 0000000000..2f01be294b
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_opaque_array.nc.raw.txt
@@ -0,0 +1,17 @@
+<Dataset
+         name="test_opaque_array.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d2" size="2"/>
+    <Opaque name="vo2">
+        <Dim name="/d2"/>
+        <Dim name="/d2"/>
+    </Opaque>
+</Dataset>
+/vo2[0,0] = 0x0123456789ABCDEF
+/vo2[0,1] = 0xABCDEF0000000000
+/vo2[1,0] = 0xFEDCBA9876543210
+/vo2[1,1] = 0xFEDCBA9999999999
+
diff --git a/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_sequence_1.syn.raw.txt b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_sequence_1.syn.raw.txt
new file mode 100644
index 0000000000..d1ac8673b7
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_sequence_1.syn.raw.txt
@@ -0,0 +1,17 @@
+<Dataset
+         name="test_sequence_1.syn"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Sequence name="s">
+        <Int32 name="i1"/>
+        <Int16 name="sh1"/>
+    </Sequence>
+</Dataset>
+/s = {
+    [
+        /s.i1 = -920699049
+        /s.sh1 = 896
+    ]}
+
diff --git a/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_sequence_2.syn.raw.txt b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_sequence_2.syn.raw.txt
new file mode 100644
index 0000000000..8161b6bfae
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_sequence_2.syn.raw.txt
@@ -0,0 +1,33 @@
+<Dataset
+         name="test_sequence_2.syn"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+
+    <Sequence name="s">
+        <Int32 name="i1"/>
+        <Int16 name="sh1"/>
+        <Dim size="2"/>
+    </Sequence>
+</Dataset>
+/s[0] = {
+    [
+        /s.i1 = -920699049
+        /s.sh1 = 896
+    ]}
+/s[1] = {
+    [
+        /s.i1 = -1123468835
+        /s.sh1 = -18686
+    ]    [
+        /s.i1 = 2125143125
+        /s.sh1 = -21899
+    ]    [
+        /s.i1 = 1268468519
+        /s.sh1 = -22144
+    ]    [
+        /s.i1 = 989876086
+        /s.sh1 = 3361
+    ]}
+
diff --git a/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_struct_array.nc.6.raw.txt b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_struct_array.nc.6.raw.txt
new file mode 100644
index 0000000000..ad651a2820
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_struct_array.nc.6.raw.txt
@@ -0,0 +1,34 @@
+<Dataset
+         name="test_struct_array.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+
+    <Structure name="s">
+        <Int32 name="x"/>
+        <Int32 name="y"/>
+        <Dim size="2"/>
+        <Dim size="2"/>
+    </Structure>
+    <Attribute name="_dap4.ce" type="String">
+        <Value value="/s[0:2:3][0:1]"/>
+    </Attribute>
+</Dataset>
+/s[0,0] = {
+    /s.x = 1
+    /s.y = -1
+}
+/s[0,1] = {
+    /s.x = 17
+    /s.y = 37
+}
+/s[1,0] = {
+    /s.x = -4
+    /s.y = 12
+}
+/s[1,1] = {
+    /s.x = -8
+    /s.y = 8
+}
+
diff --git a/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_struct_array.syn.raw.txt b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_struct_array.syn.raw.txt
new file mode 100644
index 0000000000..0b937690d6
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_struct_array.syn.raw.txt
@@ -0,0 +1,77 @@
+<Dataset
+         name="test_struct_array.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="dx" size="4"/>
+    <Dimension name="dy" size="3"/>
+    <Float32 name="z">
+        <Dim name="/dx"/>
+    </Float32>
+    <Float32 name="t">
+        <Dim name="/dy"/>
+    </Float32>
+    <Structure name="s">
+        <Int32 name="x"/>
+        <Int32 name="y"/>
+        <Dim name="/dx"/>
+        <Dim name="/dy"/>
+    </Structure>
+</Dataset>
+/z[0] = 0.727653
+/z[1] = 0.785633
+/z[2] = 0.513679
+/z[3] = 0.246845
+/t[0] = 0.738422
+/t[1] = 0.214889
+/t[2] = 0.494798
+/s[0,0] = {
+    /s.x = 712320147
+    /s.y = 1268468519
+}
+/s[0,1] = {
+    /s.x = 696298400
+    /s.y = 989876086
+}
+/s[0,2] = {
+    /s.x = -1927163883
+    /s.y = -900795134
+}
+/s[1,0] = {
+    /s.x = -708236713
+    /s.y = 1377500019
+}
+/s[1,1] = {
+    /s.x = 511843988
+    /s.y = 1699265896
+}
+/s[1,2] = {
+    /s.x = -540214433
+    /s.y = -914532520
+}
+/s[2,0] = {
+    /s.x = -1344032615
+    /s.y = -871416961
+}
+/s[2,1] = {
+    /s.x = -1928735161
+    /s.y = 935744880
+}
+/s[2,2] = {
+    /s.x = -1509955773
+    /s.y = -1707460853
+}
+/s[3,0] = {
+    /s.x = 1145911788
+    /s.y = -415231529
+}
+/s[3,1] = {
+    /s.x = -278269626
+    /s.y = -1682978013
+}
+/s[3,2] = {
+    /s.x = -1629885665
+    /s.y = -909240754
+}
+
diff --git a/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_struct_nested.hdf5.raw.txt b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_struct_nested.hdf5.raw.txt
new file mode 100644
index 0000000000..ba8ad35e38
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_struct_nested.hdf5.raw.txt
@@ -0,0 +1,28 @@
+<Dataset
+         name="test_struct_nested.hdf5"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Structure name="x">
+        <Structure name="field1">
+            <Int32 name="x"/>
+            <Int32 name="y"/>
+        </Structure>
+        <Structure name="field2">
+            <Int32 name="x"/>
+            <Int32 name="y"/>
+        </Structure>
+    </Structure>
+</Dataset>
+/x = {
+    /x.field1 =     {
+        /x.field1.x = 1
+        /x.field1.y = -2
+    }
+    /x.field2 =     {
+        /x.field2.x = 255
+        /x.field2.y = 90
+    }
+}
+
diff --git a/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_struct_nested3.hdf5.raw.txt b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_struct_nested3.hdf5.raw.txt
new file mode 100644
index 0000000000..70620ffd25
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_struct_nested3.hdf5.raw.txt
@@ -0,0 +1,22 @@
+<Dataset
+         name="test_struct_nested3.hdf5"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Structure name="x">
+        <Structure name="field3">
+            <Structure name="field2">
+                <Int32 name="field1"/>
+            </Structure>
+        </Structure>
+    </Structure>
+</Dataset>
+/x = {
+    /x.field3 =     {
+        /x.field3.field2 =         {
+            /x.field3.field2.field1 = 17
+        }
+    }
+}
+
diff --git a/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_struct_type.nc.raw.txt b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_struct_type.nc.raw.txt
new file mode 100644
index 0000000000..93536d063d
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_struct_type.nc.raw.txt
@@ -0,0 +1,16 @@
+<Dataset
+         name="test_struct_type.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Structure name="s">
+        <Int32 name="x"/>
+        <Int32 name="y"/>
+    </Structure>
+</Dataset>
+/s = {
+    /s.x = 1
+    /s.y = -2
+}
+
diff --git a/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_utf8.nc.raw.txt b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_utf8.nc.raw.txt
new file mode 100644
index 0000000000..8567416be7
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestDSP/baseline/test_utf8.nc.raw.txt
@@ -0,0 +1,14 @@
+<Dataset
+         name="test_utf8.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d2" size="2"/>
+    <String name="vs">
+        <Dim name="/d2"/>
+    </String>
+</Dataset>
+/vs[0] = "Καλημέα"
+/vs[1] = "abc"
+
diff --git a/dap4/d4tests/src/test/data/resources/TestDSR/baseline/test1.dsr b/dap4/d4tests/src/test/data/resources/TestDSR/baseline/test1.dsr
new file mode 100644
index 0000000000..125939c27c
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestDSR/baseline/test1.dsr
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<DatasetServices
+        xmlns="http://xml.opendap.org/ns/DAP/4.0/dataset-services#">
+    <DapVersion>4.0</DapVersion>
+    <ServerSoftwareVersion>TDS-4</ServerSoftwareVersion>
+    <Service title="DAP4 Dataset Services"
+                role="http://services.opendap.org/dap4/dataset-services">
+        <link type="application/vnd.opendap.dap4.dataset-services+xml"
+                href="http://localhost/d4ts/test1">
+            <alt type="text/xml"/>
+        </link>
+        <link type="text/xml"
+                href="http://localhost/d4ts/test1.xml"/>
+    </Service>
+    <Service title="DAP4 Dataset Metadata"
+                role="http://services.opendap.org/dap4/dataset-metadata">
+        <link type="application/vnd.opendap.dap4.dataset-metadata+xml"
+                href="http://localhost/d4ts/test1.dmr">
+            <alt type="text/xml"/>
+        </link>
+        <link type="text/xml"
+                href="http://localhost/d4ts/test1.dmr.xml"/>
+    </Service>
+    <Service title="DAP4 Dataset Data"
+            role="http://services.opendap.org/dap4/data">
+        <link type="application/vnd.opendap.dap4.data"
+                href="http://localhost/d4ts/test1.dap"/>
+    </Service>
+</DatasetServices>
diff --git a/dap4/d4tests/src/test/data/resources/TestFilters/baseline/test_sequence_1.syn.1.dap b/dap4/d4tests/src/test/data/resources/TestFilters/baseline/test_sequence_1.syn.1.dap
new file mode 100644
index 0000000000..f36a08093f
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestFilters/baseline/test_sequence_1.syn.1.dap
@@ -0,0 +1,3 @@
+count=5
+ -1169720286 18719 -2088732436 -16591 -1123468835 -18686 2125143125 -21899 1268468519 -22144
+	checksum = 4aad97d4
diff --git a/dap4/d4tests/src/test/data/resources/TestFilters/baseline/test_sequence_1.syn.1.dmr b/dap4/d4tests/src/test/data/resources/TestFilters/baseline/test_sequence_1.syn.1.dmr
new file mode 100644
index 0000000000..29109a2c04
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestFilters/baseline/test_sequence_1.syn.1.dmr
@@ -0,0 +1,11 @@
+<Dataset
+         name="test_sequence_1.syn"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Sequence name="s">
+        <Int32 name="i1"/>
+        <Int16 name="sh1"/>
+    </Sequence>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestFilters/baseline/test_sequence_1.syn.2.dap b/dap4/d4tests/src/test/data/resources/TestFilters/baseline/test_sequence_1.syn.2.dap
new file mode 100644
index 0000000000..7d7d18b90f
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestFilters/baseline/test_sequence_1.syn.2.dap
@@ -0,0 +1,3 @@
+count=3
+ -1169720286 18719 -2088732436 -16591 -1123468835 -18686
+	checksum = 6a9c6608
diff --git a/dap4/d4tests/src/test/data/resources/TestFrontPage/baseline/test_frontpage.html b/dap4/d4tests/src/test/data/resources/TestFrontPage/baseline/test_frontpage.html
new file mode 100644
index 0000000000..2f658c19ea
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestFrontPage/baseline/test_frontpage.html
@@ -0,0 +1,296 @@
+<html>
+<head>
+<title>DAP4 Test Files</title>
+<meta http-equiv="Content-Type" content="text/html">
+</meta>
+<body bgcolor="#FFFFFF">
+<h1>DAP4 Test Files</h1>
+<h2>http://remotetest.unidata.ucar.edu/d4ts/{testfiles}</h2>
+<hr>
+<h3>netCDF Based Test Files</h3>
+<table>
+<tr>
+<td halign='right'><b>test_atomic_array.nc:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_atomic_array.nc.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_atomic_array.nc.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_atomic_array.nc.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_atomic_types.nc:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_atomic_types.nc.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_atomic_types.nc.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_atomic_types.nc.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_enum.nc:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_enum.nc.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_enum.nc.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_enum.nc.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_enum1.nc:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_enum1.nc.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_enum1.nc.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_enum1.nc.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_enum_2.nc:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_enum_2.nc.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_enum_2.nc.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_enum_2.nc.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_enum_array.nc:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_enum_array.nc.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_enum_array.nc.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_enum_array.nc.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_fill.nc:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_fill.nc.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_fill.nc.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_fill.nc.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_groups1.nc:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_groups1.nc.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_groups1.nc.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_groups1.nc.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_misc1.nc:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_misc1.nc.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_misc1.nc.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_misc1.nc.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_one_var.nc:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_one_var.nc.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_one_var.nc.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_one_var.nc.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_one_vararray.nc:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_one_vararray.nc.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_one_vararray.nc.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_one_vararray.nc.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_opaque.nc:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_opaque.nc.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_opaque.nc.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_opaque.nc.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_opaque_array.nc:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_opaque_array.nc.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_opaque_array.nc.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_opaque_array.nc.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_struct1.nc:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_struct1.nc.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_struct1.nc.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_struct1.nc.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_struct_array.nc:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_struct_array.nc.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_struct_array.nc.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_struct_array.nc.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_struct_nested.nc:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_struct_nested.nc.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_struct_nested.nc.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_struct_nested.nc.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_struct_nested3.nc:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_struct_nested3.nc.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_struct_nested3.nc.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_struct_nested3.nc.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_struct_type.nc:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_struct_type.nc.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_struct_type.nc.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_struct_type.nc.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_test.nc:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_test.nc.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_test.nc.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_test.nc.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_unlim.nc:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_unlim.nc.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_unlim.nc.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_unlim.nc.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_unlim1.nc:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_unlim1.nc.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_unlim1.nc.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_unlim1.nc.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_utf8.nc:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_utf8.nc.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_utf8.nc.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_utf8.nc.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_vlen1.nc:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen1.nc.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen1.nc.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen1.nc.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_vlen10.nc:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen10.nc.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen10.nc.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen10.nc.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_vlen11.nc:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen11.nc.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen11.nc.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen11.nc.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_vlen2.nc:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen2.nc.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen2.nc.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen2.nc.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_vlen3.nc:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen3.nc.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen3.nc.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen3.nc.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_vlen4.nc:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen4.nc.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen4.nc.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen4.nc.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_vlen5.nc:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen5.nc.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen5.nc.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen5.nc.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_vlen6.nc:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen6.nc.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen6.nc.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen6.nc.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_vlen7.nc:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen7.nc.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen7.nc.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen7.nc.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_vlen8.nc:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen8.nc.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen8.nc.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen8.nc.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_vlen9.nc:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen9.nc.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen9.nc.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen9.nc.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_zerodim.nc:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_zerodim.nc.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_zerodim.nc.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_zerodim.nc.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>tst_fills.nc:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/tst_fills.nc.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/tst_fills.nc.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/tst_fills.nc.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+</table>
+<h3>HDF5 Based Test Files</h3>
+<table>
+<tr>
+<td halign='right'><b>test_struct_nested.hdf5:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_struct_nested.hdf5.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_struct_nested.hdf5.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_struct_nested.hdf5.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_struct_nested3.hdf5:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_struct_nested3.hdf5.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_struct_nested3.hdf5.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_struct_nested3.hdf5.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_vlen3.hdf5:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen3.hdf5.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen3.hdf5.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen3.hdf5.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_vlen4.hdf5:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen4.hdf5.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen4.hdf5.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen4.hdf5.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_vlen5.hdf5:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen5.hdf5.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen5.hdf5.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_vlen5.hdf5.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+</table>
+<h3>Synthetic Based Test Files</h3>
+<table>
+<tr>
+<td halign='right'><b>test_anon_dim.syn:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_anon_dim.syn.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_anon_dim.syn.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_anon_dim.syn.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_atomic_array.syn:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_atomic_array.syn.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_atomic_array.syn.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_atomic_array.syn.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_atomic_types.syn:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_atomic_types.syn.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_atomic_types.syn.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_atomic_types.syn.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_sequence_1.syn:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_sequence_1.syn.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_sequence_1.syn.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_sequence_1.syn.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_sequence_2.syn:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_sequence_2.syn.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_sequence_2.syn.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_sequence_2.syn.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+<tr>
+<td halign='right'><b>test_struct_array.syn:</b></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_struct_array.syn.dmr.xml'> DMR.XML </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_struct_array.syn.dap'> DAP </a></div></td>
+<td halign='center'><a href='http://localhost:80/d4ts/testfiles/test_struct_array.syn.dsr.xml'> DSR.XML </a></div></td>
+</tr>
+</table>
+<hr>
+</html>
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_0.1.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_0.1.xml
new file mode 100644
index 0000000000..24f33b55bd
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_0.1.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<Dataset xmlns="http://xml.opendap.org/ns/DAP/4.0#" 
+    name="DMR_0"
+    dapVersion="4.0"
+    dmrVersion="1.0">
+    <Attribute name="test" type="Int16">
+        <Value>1</Value>
+        <Value>2</Value>
+        <Value>3</Value>
+    </Attribute>
+    <Attribute name="DAP4_switches" type="Container">
+        <Attribute name="public_key" type="String">
+            <Value>some_large_hex_value</Value>
+        </Attribute>
+        <Attribute name="colors" type="String">
+            <Value>red</Value>
+            <Value>green</Value>
+            <Value>blue</Value>
+        </Attribute>
+        <Attribute name="temp" type="Float32">
+            <Value>98.6</Value>
+        </Attribute>
+        <Attribute type="OtherXML" name="xmltest">
+            <xml>barf</xml>
+        </Attribute>
+    </Attribute>
+</Dataset>   
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_0.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_0.xml
new file mode 100644
index 0000000000..e3d90ac6e0
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_0.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<Dataset xmlns="http://xml.opendap.org/ns/DAP/4.0#" 
+    name="DMR_0"
+    dapVersion="4.0"
+    dmrVersion="1.0">
+    <Attribute name="test" type="Int16">
+        <Value>1</Value>
+        <Value>2</Value>
+        <Value>3</Value>
+    </Attribute>
+</Dataset>   
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_1.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_1.xml
new file mode 100644
index 0000000000..eb2ba2bd26
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_1.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<Dataset xmlns="http://xml.opendap.org/ns/DAP/4.0#" 
+    name="DMR_1"
+    dapVersion="4.0"
+    dmrVersion="1.0">
+    <Dimension name="dim1" size="5"/>
+</Dataset>   
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_2.1.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_2.1.xml
new file mode 100644
index 0000000000..14d9b2b378
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_2.1.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<Dataset xmlns="http://xml.opendap.org/ns/DAP/4.0#" 
+    name="DMR_2.1"
+    dapVersion="4.0"
+    dmrVersion="1.0">
+
+    <Enumeration name="colors" basetype="Byte">
+        <EnumConst name="red" value="1"/>
+        <EnumConst name="green" value="2"/>
+        <EnumConst name="blue" value="3"/>
+    </Enumeration>
+    
+    <Enum name="e1" enum="colors"/>
+</Dataset>   
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_2.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_2.xml
new file mode 100644
index 0000000000..de25771186
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_2.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<Dataset xmlns="http://xml.opendap.org/ns/DAP/4.0#" 
+    name="DMR_2"
+    dapVersion="4.0"
+    dmrVersion="1.0">
+    <Dimension name="dim1" size="5"/>
+    <Enumeration name="colors" basetype="Byte">
+        <EnumConst name="red" value="1"/>
+        <EnumConst name="green" value="2"/>
+        <EnumConst name="blue" value="3"/>
+    </Enumeration>
+</Dataset>   
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_3.1.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_3.1.xml
new file mode 100644
index 0000000000..e2912f2f3c
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_3.1.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<Dataset xmlns="http://xml.opendap.org/ns/DAP/4.0#" 
+    name="DMR_3"
+    dapVersion="4.0"
+    dmrVersion="1.0">
+    <Dimension name="dim1" size="5"/>
+    <Enumeration name="colors" basetype="Byte">
+        <EnumConst name="red" value="1"/>
+        <EnumConst name="green" value="2"/>
+        <EnumConst name="blue" value="3"/>
+    </Enumeration>
+    <Byte name="b1">
+        <Attribute name="test" type="Int16">
+            <Value>1</Value>
+            <Value>2</Value>
+            <Value>3</Value>
+        </Attribute>
+        <Attribute name="DAP4_switches" type="Container">
+            <Attribute name="public_key" type="String">
+                <Value>some_large_hex_value</Value>
+            </Attribute>
+            <Attribute name="colors" type="String">
+                <Value>red</Value>
+                <Value>green</Value>
+                <Value>blue</Value>
+            </Attribute>
+            <Attribute name="temp" type="Float32">
+                <Value>98.6</Value>
+            </Attribute>
+            <Attribute type="OtherXML" name="xmltest">
+                <xml>barf</xml>
+            </Attribute>
+        </Attribute>
+    </Byte>
+</Dataset>   
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_3.2.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_3.2.xml
new file mode 100644
index 0000000000..e4bd6ea48c
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_3.2.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<Dataset xmlns="http://xml.opendap.org/ns/DAP/4.0#" 
+    name="DMR_3"
+    dapVersion="4.0"
+    dmrVersion="1.0">
+    <Byte name="b1">
+        <Dim size="10"/>
+    </Byte>
+</Dataset>   
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_3.3.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_3.3.xml
new file mode 100644
index 0000000000..b2e99a4064
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_3.3.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<Dataset xmlns="http://xml.opendap.org/ns/DAP/4.0#" 
+    name="DMR_3"
+    dapVersion="4.0"
+    dmrVersion="1.0">
+    <Dimension name="dim1" size="5"/>
+    <Enumeration name="colors" basetype="Byte">
+        <EnumConst name="red" value="1"/>
+        <EnumConst name="green" value="2"/>
+        <EnumConst name="blue" value="3"/>
+    </Enumeration>
+    <Byte name="b1">
+        <Dim size="20"/>
+        <Dim size="30"/>
+        <Attribute name="test" type="Int16">
+            <Value>1</Value>
+            <Value>2</Value>
+            <Value>3</Value>
+        </Attribute>
+        <Attribute name="DAP4_switches" type="Container">
+            <Attribute name="public_key" type="String">
+                <Value>some_large_hex_value</Value>
+            </Attribute>
+            <Attribute name="colors" type="String">
+                <Value>red</Value>
+                <Value>green</Value>
+                <Value>blue</Value>
+            </Attribute>
+            <Attribute name="temp" type="Float32">
+                <Value>98.6</Value>
+            </Attribute>
+            <Attribute type="OtherXML" name="xmltest">
+                <xml>barf</xml>
+            </Attribute>
+        </Attribute>
+    </Byte>
+</Dataset>   
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_3.4.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_3.4.xml
new file mode 100644
index 0000000000..98354ea298
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_3.4.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<Dataset xmlns="http://xml.opendap.org/ns/DAP/4.0#" 
+    name="DMR_3"
+    dapVersion="4.0"
+    dmrVersion="1.0">
+    <Dimension name="dim1" size="5"/>
+    <Enumeration name="colors" basetype="Byte">
+        <EnumConst name="red" value="1"/>
+        <EnumConst name="green" value="2"/>
+        <EnumConst name="blue" value="3"/>
+    </Enumeration>
+    <Byte name="b1">
+        <Dim name="dim1"/>
+        <Dim size="30"/>
+    </Byte>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_3.5.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_3.5.xml
new file mode 100644
index 0000000000..822345c2e6
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_3.5.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<Dataset xmlns="http://xml.opendap.org/ns/DAP/4.0#" 
+    name="DMR_3"
+    dapVersion="4.0"
+    dmrVersion="1.0">
+    <Dimension name="dim1" size="5"/>
+    <Enumeration name="colors" basetype="Byte">
+        <EnumConst name="red" value="1"/>
+        <EnumConst name="green" value="2"/>
+        <EnumConst name="blue" value="3"/>
+    </Enumeration>
+    <Byte name="b1">
+        <Dim name="dim1"/>
+        <Dim size="30"/>
+    </Byte>
+    <Group name="g1">
+        <Dimension name="dim1" size="10"/>
+        <Int32 name="thing1">
+            <Dim name="/dim1"/>
+            <Dim name="dim1"/>
+        </Int32>
+        <Int32 name="thing2">
+            <Dim name="/dim1"/>
+            <Dim name="/g1/dim1"/>
+        </Int32>
+        
+        <Group name="g2">
+            <Dimension name="dim1" size="20"/>
+            <Int32 name="thing1">
+                <Dim name="/dim1"/>
+                <Dim name="/g1/dim1"/>
+                <Dim name="dim1"/>
+            </Int32>
+        </Group> 
+        
+        <Int32 name="thing3">
+            <Dim name="/dim1"/>
+            <Dim name="dim1"/>
+            <Dim name="g2/dim1"/>
+        </Int32>
+        
+    </Group>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_3.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_3.xml
new file mode 100644
index 0000000000..7675f27e56
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_3.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<Dataset xmlns="http://xml.opendap.org/ns/DAP/4.0#" 
+    name="DMR_3"
+    dapVersion="4.0"
+    dmrVersion="1.0">
+    <Dimension name="dim1" size="5"/>
+    <Enumeration name="colors" basetype="Byte">
+        <EnumConst name="red" value="1"/>
+        <EnumConst name="green" value="2"/>
+        <EnumConst name="blue" value="3"/>
+    </Enumeration>
+    <Byte name="b1"/>
+</Dataset>   
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_4.1.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_4.1.xml
new file mode 100644
index 0000000000..e43ec4f81f
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_4.1.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<Dataset xmlns="http://xml.opendap.org/ns/DAP/4.0#" 
+    name="DMR_4.1"
+    dapVersion="4.0"
+    dmrVersion="1.0">
+    <Dimension name="d1" size="5"/>
+    <Dimension name="d2" size="3"/>
+
+    <Opaque name="o">
+        <Dim name="d1"/>
+    </Opaque>
+
+    <Opaque name="p">
+        <Dim name="d1"/>
+        <Dim name="d2"/>
+    </Opaque>
+    
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_4.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_4.xml
new file mode 100644
index 0000000000..7728abca32
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_4.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<Dataset xmlns="http://xml.opendap.org/ns/DAP/4.0#" 
+    name="DMR_4"
+    dapVersion="4.0"
+    dmrVersion="1.0">
+    <Dimension name="dim1" size="5"/>
+    <Enumeration name="colors" basetype="Byte">
+        <EnumConst name="red" value="1"/>
+        <EnumConst name="green" value="2"/>
+        <EnumConst name="blue" value="3"/>
+    </Enumeration>
+    <Byte name="b1"/>
+    <Char name  ="c1"/>
+    <Int8 name="i8"/>
+    <UInt8 name="ui8"/>
+    <Int16 name="i16"/>
+    <UInt16 name="ui16"/>
+    <Int32 name="i32"/>
+    <UInt32 name="ui32"/>
+    <Int64 name="i64"/>
+    <UInt64 name="ui64"/>
+    <Float32 name="f32"/>
+    <Float64 name="f64"/>
+    <String name="s"/>
+    <URL name="u"/>
+    <Enum name="e" enum="colors"/>
+    <Opaque name="o"/>
+
+</Dataset>   
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_5.1.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_5.1.xml
new file mode 100644
index 0000000000..8ae88fff55
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_5.1.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+    dapVersion="4.0" dmrVersion="1.0">
+    <Dimension name="dim1" size="5"/>
+    <Enumeration name="colors" basetype="Byte">
+        <EnumConst name="red" value="1"/>
+        <EnumConst name="green" value="2"/>
+        <EnumConst name="blue" value="3"/>
+    </Enumeration>
+    <Byte name="b1"/>
+    <Structure name="s">
+        <Int8 name="i8"/>
+        <UInt8 name="ui8">
+            <Attribute name="test" type="Int16">
+                <Value>1</Value>
+                <Value>2</Value>
+                <Value>3</Value>
+            </Attribute>
+            <Attribute name="DAP4_switches" type="Container">
+                <Attribute name="public_key" type="String">
+                    <Value>some_large_hex_value</Value>
+                </Attribute>
+            </Attribute>
+        </UInt8>
+        <Int16 name="i16"/>
+        <UInt16 name="ui16"/>
+        <Int32 name="i32"/>
+        <UInt32 name="ui32"/>
+        <Int64 name="i64"/>
+        <UInt64 name="ui64"/>
+        <Float32 name="f32"/>
+        <Float64 name="f64"/>
+        <String name="s"/>
+        <URL name="u"/>
+        <Attribute name="test" type="Int16">
+            <Value>1</Value>
+            <Value>2</Value>
+            <Value>3</Value>
+        </Attribute>
+        <Attribute name="DAP4_switches" type="Container">
+            <Attribute name="public_key" type="String">
+                <Value>some_large_hex_value</Value>
+            </Attribute>
+            <Attribute name="colors" type="String">
+                <Value>red</Value>
+                <Value>green</Value>
+                <Value>blue</Value>
+            </Attribute>
+            <Attribute name="temp" type="Float32">
+                <Value>98.6</Value>
+            </Attribute>
+        </Attribute>
+    </Structure>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_5.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_5.xml
new file mode 100644
index 0000000000..7900313c64
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_5.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<Dataset xmlns="http://xml.opendap.org/ns/DAP/4.0#" 
+    name="DMR_5"
+    dapVersion="4.0"
+    dmrVersion="1.0">
+    <Dimension name="dim1" size="5"/>
+    <Enumeration name="colors" basetype="Byte">
+        <EnumConst name="red" value="1"/>
+        <EnumConst name="green" value="2"/>
+        <EnumConst name="blue" value="3"/>
+    </Enumeration>
+    <Byte name="b1"/>
+    <Structure name="s">
+        <Char name="c1"/>
+        <Int8 name="i8"/>
+        <UInt8 name="ui8"/>
+        <Int16 name="i16"/>
+        <UInt16 name="ui16"/>
+        <Int32 name="i32"/>
+        <UInt32 name="ui32"/>
+        <Int64 name="i64"/>
+        <UInt64 name="ui64"/>
+        <Float32 name="f32"/>
+        <Float64 name="f64"/>
+        <String name="s"/>
+        <URL name="u"/>
+        <Enum name="e" enum="colors"/>
+        <Opaque name="o"/>
+    </Structure>
+</Dataset>   
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_6.1.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_6.1.xml
new file mode 100644
index 0000000000..0585fd7a24
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_6.1.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<Dataset xmlns="http://xml.opendap.org/ns/DAP/4.0#" 
+    name="DMR_6"
+    dapVersion="4.0"
+    dmrVersion="1.0">
+    <Dimension name="dim1" size="5"/>
+    <Enumeration name="colors" basetype="Byte">
+        <EnumConst name="red" value="1"/>
+        <EnumConst name="green" value="2"/>
+        <EnumConst name="blue" value="3"/>
+    </Enumeration>
+    <Byte name="b1"/>
+    <Group name="g1">
+        <Attribute name="test" type="Int16">
+            <Value>1</Value>
+            <Value>2</Value>
+            <Value>3</Value>
+        </Attribute>
+        <Int8 name="i8"/>
+        <Structure name="s">
+            <Int16 name="i16"/>
+            <UInt16 name="ui16"/>
+            <URL name="u"/>
+        </Structure>        
+    </Group>
+    <Group name="g2">
+        <String name="s"/>
+        <Group name="gg2">
+            <Attribute name="test" type="Int16">
+                <Value>1</Value>
+                <Value>2</Value>
+                <Value>3</Value>
+            </Attribute>
+            <Float64 name="f64"/>
+            <Structure name="s">
+                <Int32 name="i16"/>
+                <UInt32 name="ui16"/>
+                <URL name="u"/>
+            </Structure>
+        </Group>
+    </Group>
+</Dataset>   
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_6.2.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_6.2.xml
new file mode 100644
index 0000000000..92960908f8
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_6.2.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<Dataset xmlns="http://xml.opendap.org/ns/DAP/4.0#" 
+    name="DMR_6.2"
+    dapVersion="4.0"
+    dmrVersion="1.0">
+    <Dimension name="dim1" size="5"/>
+    <Enumeration name="colors" basetype="Byte">
+        <EnumConst name="red" value="1"/>
+        <EnumConst name="green" value="2"/>
+        <EnumConst name="blue" value="3"/>
+    </Enumeration>
+    
+    <Enum name="e" enum="colors"/>
+    
+    <Byte name="b1"/>
+    <Group name="g1">
+        <Attribute name="test" type="Int16">
+            <Value>1</Value>
+            <Value>2</Value>
+            <Value>3</Value>
+        </Attribute>
+        
+        <Enum name="e" enum="/colors"/>
+        
+    </Group>
+     <Group name="g2">
+        <Enumeration name="shades" basetype="UInt16">
+            <EnumConst name="white" value="1"/>
+            <EnumConst name="light" value="2"/>
+            <EnumConst name="med" value="3"/>
+            <EnumConst name="dark" value="4"/>
+            <EnumConst name="black" value="5"/>
+        </Enumeration>
+    
+        <Enum name="e" enum="shades"/>
+        
+        <Group name="gg2">
+            <Attribute name="test" type="Int16">
+                <Value>1</Value>
+                <Value>2</Value>
+                <Value>3</Value>
+            </Attribute>
+
+            <Enum name="e" enum="/g2/shades"/>
+
+        </Group>
+    </Group>
+</Dataset>   
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_6.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_6.xml
new file mode 100644
index 0000000000..a88b5bf47d
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_6.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<Dataset xmlns="http://xml.opendap.org/ns/DAP/4.0#" 
+    name="DMR_6"
+    dapVersion="4.0"
+    dmrVersion="1.0">
+    <Dimension name="dim1" size="5"/>
+    <Enumeration name="colors" basetype="Byte">
+        <EnumConst name="red" value="1"/>
+        <EnumConst name="green" value="2"/>
+        <EnumConst name="blue" value="3"/>
+    </Enumeration>
+    <Byte name="b1"/>
+    <Group name="g1">
+        <Int8 name="i8"/>
+        <Structure name="s">
+            <Int16 name="i16"/>
+            <UInt16 name="ui16"/>
+            <URL name="u"/>
+        </Structure>        
+    </Group>
+    <Group name="g2">
+        <String name="s"/>
+        <Group name="gg2">
+            <Float64 name="f64"/>
+            <Structure name="s">
+                <Int32 name="i16"/>
+                <UInt32 name="ui16"/>
+                <URL name="u"/>
+            </Structure>
+        </Group>
+    </Group>
+</Dataset>   
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_7.1.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_7.1.xml
new file mode 100644
index 0000000000..588a1ee931
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_7.1.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<Dataset xmlns="http://xml.opendap.org/ns/DAP/4.0#" 
+    name="DMR_1"
+    dapVersion="4.0"
+    dmrVersion="1.0">
+    <Dimension name="dim1" size="5"/>
+    <Dimension name="dim2" size="3"/>
+    <Byte name="a">
+        <Dim name="dim1"/>
+    </Byte>
+    <Char name="a1">
+        <Dim name="dim1"/>
+    </Char>
+    <Int8 name="b">
+        <Dim name="dim1"/>
+    </Int8>
+    <UInt8 name="c">
+        <Dim name="dim1"/>
+        <Dim name="dim2"/>
+    </UInt8>
+    <Int16 name="d">
+        <Dim name="dim1"/>
+    </Int16>
+    <UInt16 name="e">
+        <Dim size="10"/>
+    </UInt16>
+    <Int32 name="f">
+        <Dim name="dim1"/>
+    </Int32>
+    <UInt32 name="g">
+        <Dim name="dim1"/>
+    </UInt32>
+    <Int64 name="h">
+        <Dim name="dim1"/>
+    </Int64>
+    <UInt64 name="i">
+        <Dim name="dim1"/>
+    </UInt64>
+    <Float32 name="j">
+        <Dim name="dim1"/>
+    </Float32>
+    <Float64 name="k">
+        <Dim name="dim1"/>
+    </Float64>
+    
+</Dataset>   
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_7.2.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_7.2.xml
new file mode 100644
index 0000000000..25b9b59c51
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_7.2.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<Dataset xmlns="http://xml.opendap.org/ns/DAP/4.0#" 
+    name="DMR_1"
+    dapVersion="4.0"
+    dmrVersion="1.0">
+    <Dimension name="dim1" size="5"/>
+    <Dimension name="dim2" size="3"/>
+
+    <Enumeration name="colors" basetype="Byte">
+        <EnumConst name="red" value="1"/>
+        <EnumConst name="green" value="2"/>
+        <EnumConst name="blue" value="3"/>
+    </Enumeration>
+    
+    <String name="a">
+        <Dim name="dim1"/>
+    </String>
+    <URL name="b">
+        <Dim name="dim1"/>
+    </URL>
+</Dataset>   
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_7.3.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_7.3.xml
new file mode 100644
index 0000000000..5d04405d3d
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_7.3.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<Dataset xmlns="http://xml.opendap.org/ns/DAP/4.0#" 
+    name="DMR_1"
+    dapVersion="4.0"
+    dmrVersion="1.0">
+    <Dimension name="dim1" size="5"/>
+    <Dimension name="dim2" size="3"/>
+
+    <Enumeration name="colors" basetype="Byte">
+        <EnumConst name="red" value="1"/>
+        <EnumConst name="green" value="2"/>
+        <EnumConst name="blue" value="3"/>
+    </Enumeration>
+    
+    <String name="a">
+        <Dim name="dim1"/>
+    </String>
+    <URL name="b">
+        <Dim name="dim1"/>
+    </URL>
+    
+    <Int8 name="c">
+        <Dim name="dim1"/>
+    </Int8>
+    
+    <UInt8 name="d">
+        <Dim name="dim1"/>
+    </UInt8>
+    
+    <Int64 name="e">
+        <Dim name="dim1"/>
+    </Int64>
+    
+    <UInt64 name="f">
+        <Dim name="dim1"/>
+    </UInt64>
+</Dataset>   
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_7.4.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_7.4.xml
new file mode 100644
index 0000000000..aef2e07583
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_7.4.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<Dataset xmlns="http://xml.opendap.org/ns/DAP/4.0#" 
+    name="DMR_1"
+    dapVersion="4.0"
+    dmrVersion="1.0">
+    <Dimension name="dim1" size="5"/>
+    <Dimension name="dim2" size="3"/>
+
+    <Structure name="s">
+        <Dim name="dim1"/>
+
+        <Int32 name="i"/>
+        <Int32 name="j"/> 
+    </Structure>
+
+    <Structure name="t">
+        <Int32 name="i"/>
+            
+        <String name="a">
+            <Dim size="3"/>
+        </String>
+        
+        <Dim name="dim1"/>
+    </Structure>
+
+    <Structure name="u">
+        <Int32 name="i"/>
+        
+        <String name="a">
+            <Dim size="3"/>
+        </String>
+        
+        <Dim name="dim1"/>
+        <Dim name="dim2"/>
+    </Structure>
+    
+    <Structure name="v">
+        <Int32 name="i"/>
+        
+        <String name="a">
+            <Dim size="3"/>
+        </String>
+        
+        <Structure name="w">
+            <Int32 name="i"/>
+            
+            <String name="a">
+                <Dim size="3"/>
+            </String>
+            
+            <Dim name="dim1"/>
+            <Dim name="dim2"/>
+        </Structure>
+        
+        
+        <Dim name="dim1"/>
+        <Dim size="2"/>
+    </Structure>
+    
+    
+</Dataset>   
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_7.5.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_7.5.xml
new file mode 100644
index 0000000000..2e5bcacfee
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_7.5.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<Dataset xmlns="http://xml.opendap.org/ns/DAP/4.0#" 
+    name="DMR_1"
+    dapVersion="4.0"
+    dmrVersion="1.0">
+    <Dimension name="dim1" size="5"/>
+    <Dimension name="dim2" size="3"/>
+
+    <Enumeration name="colors" basetype="Byte">
+        <EnumConst name="red" value="1"/>
+        <EnumConst name="green" value="2"/>
+        <EnumConst name="blue" value="3"/>
+    </Enumeration>
+    
+    <Enum name="e" enum="colors">
+        <Dim name="dim1"/>
+    </Enum>
+    
+    <Opaque name="o">
+        <Dim name="dim1"/>
+    </Opaque>
+</Dataset>   
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_7.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_7.xml
new file mode 100644
index 0000000000..d2e55307d7
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_7.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<Dataset xmlns="http://xml.opendap.org/ns/DAP/4.0#" 
+    name="DMR_1"
+    dapVersion="4.0"
+    dmrVersion="1.0">
+    <Dimension name="dim1" size="5"/>
+    <Byte name="b1">
+        <Dim name="dim1"/>
+    </Byte>
+</Dataset>   
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_8.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_8.xml
new file mode 100644
index 0000000000..29a93fe87f
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/DMR_8.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<Dataset xmlns="http://xml.opendap.org/ns/DAP/4.0#" 
+    name="DMR_8"
+    dapVersion="4.0"
+    dmrVersion="1.0">
+    <Dimension name="x-axis" size="5"/>
+    <Float32 name="x">
+        <Dim name="x-axis"/>
+    </Float32>
+    
+    <Byte name="b1">
+        <Dim name="x-axis"/>
+        <Map name="x"/>
+    </Byte>
+    
+</Dataset>   
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_array_1.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_array_1.xml
new file mode 100644
index 0000000000..da6d955ac4
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_array_1.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- First in a series of very simple tests. jhrg 7/10/12 -->
+
+  xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+  xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+
+  <dap:Int32 name="x">
+    <Dim size="5"/>
+  </dap:Int32>
+
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_array_10.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_array_10.xml
new file mode 100644
index 0000000000..aac65a7955
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_array_10.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<Dataset xmlns="http://xml.opendap.org/ns/DAP/4.0#" 
+  name="test_simple_11"
+  dapVersion="4.0"
+  dmrVersion="1.0">
+  <Dimension name="d1" size="5"/>
+  <Dimension name="d2" size="3"/>
+  
+  <Opaque name="o">
+    <Dim name="d1"/>
+  </Opaque>
+  
+  <Opaque name="p">
+    <Dim name="d1"/>
+    <Dim name="d2"/>
+  </Opaque>
+  
+</Dataset>   
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_array_11.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_array_11.xml
new file mode 100644
index 0000000000..f661ce3517
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_array_11.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<Dataset xmlns="http://xml.opendap.org/ns/DAP/4.0#" 
+  name="test_simple_11"
+  dapVersion="4.0"
+  dmrVersion="1.0">
+  <Dimension name="d1" size="5"/>
+  <Dimension name="d2" size="3"/>
+  
+  <Enumeration name="colors" basetype="Byte">
+    <EnumConst name="red" value="1"/>
+    <EnumConst name="green" value="2"/>
+    <EnumConst name="blue" value="3"/>
+  </Enumeration>
+  
+  <Enum name="e1" enum="colors">
+    <Dim name="d1"/>
+  </Enum>
+  
+  <Enum name="e2" enum="colors">
+    <Dim name="d1"/>
+    <Dim name="d2"/>
+  </Enum>
+  
+</Dataset>   
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_array_2.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_array_2.xml
new file mode 100644
index 0000000000..45ab981649
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_array_2.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- First in a series of very simple tests. jhrg 7/10/12 -->
+
+  xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+  xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+
+  <dap:Int32 name="x">
+    <Dim size="5"/>
+    <Dim size="4"/>
+  </dap:Int32>
+
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_array_3.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_array_3.xml
new file mode 100644
index 0000000000..356785c0e4
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_array_3.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+  xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+  xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+
+  <Dimension name="row" size="5"/>   
+  
+  <dap:String name="x">
+    <Dim name="row"/>
+    <Dim size="3"/>
+  </dap:String>
+
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_array_4.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_array_4.xml
new file mode 100644
index 0000000000..e04b11ed9b
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_array_4.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+  xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+  xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+
+  <Dimension name="row" size="3"/>
+  <Dimension name="col" size="4"/>
+
+  <dap:Byte name="a">
+    <Dim name="row"/>
+    <Dim name="col"/>
+  </dap:Byte>
+
+  <dap:Int16 name="b">
+    <Dim name="row"/>
+    <Dim name="col"/>
+  </dap:Int16>
+
+  <dap:Int32 name="c">
+    <Dim name="row"/>
+    <Dim name="col"/>
+  </dap:Int32>
+
+  <dap:UInt16 name="d">
+    <Dim name="row"/>
+    <Dim name="col"/>
+  </dap:UInt16>
+
+  <dap:UInt32 name="e">
+    <Dim name="row"/>
+    <Dim name="col"/>
+  </dap:UInt32>
+
+  <dap:Float32 name="f">
+    <Dim name="row"/>
+    <Dim name="col"/>
+  </dap:Float32>
+
+  <dap:Float64 name="g">
+    <Dim name="row"/>
+    <Dim name="col"/>
+  </dap:Float64>
+
+  <dap:String name="h">
+    <Dim name="row"/>
+    <Dim name="col"/>
+  </dap:String>
+
+  <dap:URL name="i">
+    <Dim name="row"/>
+    <Dim name="col"/>
+  </dap:URL>
+
+  <dap:Int32 name="x">
+    <Dim name="row"/>
+    <Dim size="5"/>
+  </dap:Int32>
+  
+  <dap:Int32 name="y">
+    <Dim size="5"/>
+    <Dim name="col"/>
+  </dap:Int32>
+  
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_array_5.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_array_5.xml
new file mode 100644
index 0000000000..de24f7fdfa
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_array_5.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+  xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+  xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+  
+  <Dimension name="row" size="3"/>
+  <Dimension name="col" size="4"/>
+  
+  <dap:Int8 name="a">
+    <Dim name="row"/>
+    <Dim name="col"/>
+  </dap:Int8>
+  
+  <dap:UInt8 name="b">
+    <Dim name="row"/>
+    <Dim name="col"/>
+  </dap:UInt8>
+  
+  <dap:Int64 name="c">
+    <Dim name="row"/>
+    <Dim name="col"/>
+  </dap:Int64>
+  
+  <dap:UInt64 name="d">
+    <Dim name="row"/>
+    <Dim name="col"/>
+  </dap:UInt64>
+
+
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_array_6.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_array_6.xml
new file mode 100644
index 0000000000..88a4209425
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_array_6.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+  xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+  xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+  
+  <Dimension name="row" size="3"/>
+  <Dimension name="col" size="4"/>
+  
+  <Structure name="a">
+    <Int32 name="i"/>
+    <Int32 name="j"/>
+    <Dim name="row"/>
+    <Dim name="col"/>   
+  </Structure>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_array_7.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_array_7.xml
new file mode 100644
index 0000000000..00a22b0c81
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_array_7.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+  xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+  xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+  
+    <Sequence name="s">
+        <Dim size="2"/>
+        <Int32 name="i1"/>
+        <String name="s"/>
+    </Sequence>
+  
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_array_8.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_array_8.xml
new file mode 100644
index 0000000000..61919cb9d3
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_array_8.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+  xmlns="http://xml.opendap.org/ns/DAP/4.0#" xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+  <Dimension name="col" size="3"/>
+  <Sequence name="s">
+    <Dim size="2"/>
+    <Dim name="col"/>
+    <Int32 name="i1"/>
+    <String name="s"/>
+  </Sequence>
+
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_escaped_paths.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_escaped_paths.xml
new file mode 100644
index 0000000000..afd82e7bf2
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_escaped_paths.xml
@@ -0,0 +1,69 @@
+<Dataset name="example"
+       dapVersion="4.0"
+       dmrVersion="1.0"
+       xmlns="http://xml.opendap.org/ns/DAP/4.0#">
+
+<Enumeration name="e1" basetype="UInt8">
+  <EnumConst name="econst1" value="1"/>
+  <EnumConst name="econst2" value="2"/>
+</Enumeration>
+
+<Dimension name="d1" size="10"/>
+<Dimension name="lat" size="20"/>
+<Dimension name="lon" size="20"/>
+
+<Int32 name="x"/>
+<Float32 name="lat">
+  <Dim name="/lat"/>
+</Float32>
+<Float32 name="lon">
+  <Dim name="/lon"/>
+</Float32>
+<Structure name="y">
+  <Opaque name="f1"/>
+  <Attribute name="a1" type="Int32"/>
+  <Attribute name="a2" type="Float64">
+    <Value value="7.5"/>    
+    <Value>10</Value>
+  </Attribute>  
+  <!-- Structure dimensions -->
+  <Dim size="*"/>
+  <Dim name="/d1"/>
+  <Dim size="10"/>
+</Structure>
+
+<Group name="g1">
+  <Dimension name="d1" size="10"/>
+  <Dimension name="d2" size="20"/>
+
+  <Float32 name="tempb">
+    <Dim name="/lat"/>
+    <Dim name="/lon"/>
+    <Map name="/lat"/>
+    <Map name="/lon"/>
+  </Float32>
+  <Enum enum="/e1" name="evar"/>
+
+</Group>
+
+<!-- Test FQN name processing -->
+<Group name="g.@/\$">
+<!-- Provide a dimension with a name that needs escaping "lon/2.\" -->
+<Dimension name="lon/2.\" size="20"/>
+</Group>
+
+<!-- reference the dimension and group with funny names -->
+<Int32 name="funny">
+  <Dim name="/g\.@\/\\$/lon\/2\.\\"/>
+</Int32>
+
+<!-- embedded xml example; dap4.rng needs work
+<OtherXML>
+<anyelement1 name="5">
+<anyelement2>any text</anyelement2>
+</anyelement1>
+</OtherXML>
+-->
+
+
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_1.dmr b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_1.dmr
new file mode 100644
index 0000000000..503b89e031
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_1.dmr
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- First in a series of very simple tests. jhrg 7/10/12 -->
+
+  xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+  xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+
+  <dap:Int32 name="x"/>
+
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_1.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_1.xml
new file mode 100644
index 0000000000..503b89e031
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_1.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- First in a series of very simple tests. jhrg 7/10/12 -->
+
+  xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+  xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+
+  <dap:Int32 name="x"/>
+
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_10.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_10.xml
new file mode 100644
index 0000000000..e87a967368
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_10.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+  xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+  xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    
+  <Opaque name="o"/>
+  
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_2.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_2.xml
new file mode 100644
index 0000000000..78e6928d1e
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_2.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- First in a series of very simple tests. jhrg 7/10/12 -->
+
+  xmlns="http://xml.opendap.org/ns/DAP/4.0#">
+
+  <Byte name="b"/>
+  
+  <Int8 name="i8"/>
+  <UInt8 name="ui8"/>
+  
+  <Int16 name="i16"/>
+  <UInt16 name="ui16"/>
+  
+  <Int32 name="i32"/>
+  <UInt32 name="ui32"/>
+  
+  <Int64 name="i64"/>
+  <UInt64 name="ui64"/>
+  
+  <Float32 name="f32"/>
+  <Float64 name="f64"/>
+
+  <String name="s"/>
+  <URL name="u"/>
+  
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_3.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_3.xml
new file mode 100644
index 0000000000..5068261867
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_3.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<Dataset name="test_simple_3" dapVersion="4.0" dmrVersion="1.0" xmlns="http://xml.opendap.org/ns/DAP/4.0#">
+
+  <!-- Test enumeration definitions -->
+  <Enumeration name="e1" basetype="UInt8">
+    <EnumConst name="econst1" value="1"/>
+    <EnumConst name="econst2" value="2"/>
+  </Enumeration>
+
+  <Int32 name="x"/>
+
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_3_error_1.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_3_error_1.xml
new file mode 100644
index 0000000000..5686798376
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_3_error_1.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<Dataset name="example" dapVersion="4.0" dmrVersion="1.0" xmlns="http://xml.opendap.org/ns/DAP/4.0#">
+
+  <!-- Bad EnumConst; it must be an integer value -->
+  <Enumeration name="e1" basetype="UInt8">
+    <EnumConst name="econst1" value="1"/>
+    <EnumConst name="econst2" value="not_an_integer"/>
+  </Enumeration>
+
+  <Int32 name="x"/>
+
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_3_error_2.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_3_error_2.xml
new file mode 100644
index 0000000000..6f28cd48ae
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_3_error_2.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<Dataset name="example" dapVersion="4.0" dmrVersion="1.0" xmlns="http://xml.opendap.org/ns/DAP/4.0#">
+
+  <!-- Bad basetype for an Enumeration -->
+  <Enumeration name="e1" basetype="Float64">
+    <EnumConst name="econst1" value="1"/>
+    <EnumConst name="econst2" value="2"/>
+  </Enumeration>
+
+  <Int32 name="x"/>
+
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_3_error_3.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_3_error_3.xml
new file mode 100644
index 0000000000..c8d6f24d51
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_3_error_3.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<Dataset name="example" dapVersion="4.0" dmrVersion="1.0" xmlns="http://xml.opendap.org/ns/DAP/4.0#">
+
+  <!-- Bad EnumConst; the value is too big -->
+  <Enumeration name="e1" basetype="UInt8">
+    <EnumConst name="econst1" value="1"/>
+    <EnumConst name="econst2" value="257"/>
+  </Enumeration>
+
+  <Int32 name="x"/>
+
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_4.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_4.xml
new file mode 100644
index 0000000000..416f4597e5
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_4.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- Attributes -->
+
+  xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+  xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+  
+  <dap:Int32 name="x">
+    <Attribute name="long_name" type="String">
+      <Value>x_axis_value</Value>
+    </Attribute>
+  </dap:Int32>
+  
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_5.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_5.xml
new file mode 100644
index 0000000000..5c844638ef
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_5.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- Attributes -->
+
+  xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+  xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+  
+  <dap:Int8 name="i"/>
+  <dap:Int16 name="j"/>
+  <dap:Int32 name="k"/>
+  <dap:Int64 name="z"/>
+ 
+  <dap:Byte name="ui"/>
+  <dap:UInt8 name="uii"/>
+  <dap:UInt16 name="uj"/>
+  <dap:UInt32 name="uk"/>
+  <dap:UInt64 name="uz"/>
+  
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_6.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_6.xml
new file mode 100644
index 0000000000..20e14a6f6a
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_6.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+  xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+  xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+  
+    <Structure name="s">
+        <Int32 name="i1"/>
+        <String name="s"/>
+    </Structure>
+      
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_7.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_7.xml
new file mode 100644
index 0000000000..d163b92912
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_7.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+  xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+  xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+  
+    <Sequence name="s">
+        <Int32 name="i1"/>
+        <String name="s"/>
+    </Sequence>
+  
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_8.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_8.xml
new file mode 100644
index 0000000000..4db2522603
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_8.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+  xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+  xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+  
+  <Structure name="outer">
+    <Sequence name="s">
+      <Int32 name="i1"/>
+      <String name="s"/>
+    </Sequence>    
+  </Structure>
+  
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_9.1.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_9.1.xml
new file mode 100644
index 0000000000..0dacc20a66
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_9.1.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+  xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+  xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+  
+  <Enumeration name="color" basetype="Int32">
+    <EnumConst name="red" value="100"/>
+    <EnumConst name="blue" value="200"/>
+    <EnumConst name="gray" value="300"/>
+  </Enumeration>
+  
+  <Enumeration name="shade" basetype="UInt64">
+    <EnumConst name="light" value="1"/>
+    <EnumConst name="med" value="2"/>
+    <EnumConst name="dark" value="3"/>
+    
+    <EnumConst name="pitch" value="256"/>
+  </Enumeration>
+  
+  <Enum name="e" enum="color"/>
+  <Enum name="f" enum="shade"/>
+  
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_9.xml b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_9.xml
new file mode 100644
index 0000000000..fd38d284d6
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/dmr/test_simple_9.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+  xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+  xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+  
+  <Enumeration name="color" basetype="Byte">
+    <EnumConst name="red" value="1"/>
+    <EnumConst name="blue" value="2"/>
+    <EnumConst name="gray" value="3"/>
+  </Enumeration>
+  
+  <Enum name="e" enum="color"/>
+  
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestHyrax/hyrax.html b/dap4/d4tests/src/test/data/resources/TestHyrax/hyrax.html
new file mode 100644
index 0000000000..e92d923650
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestHyrax/hyrax.html
@@ -0,0 +1,380 @@
+<html>
+<head>
+<title>DAP4 Test Files</title>
+<meta http-equiv="Content-Type" content="text/html">
+</head>
+<body bgcolor="#FFFFFF">
+<h1>DAP4 Test Files</h1>
+<h2>http://amazon.com/dap/reader/dap4/dap4.html</h2>
+<hr>
+<h3>netCDF Based Test Files</h3>
+<table>
+</table>
+<h3>HDF5 Based Test Files</h3>
+<table>
+</table>
+<h3>Synthetic Based Test Files</h3>
+<table>
+<tr>
+<td halign='right'><b>test_simple_1.dmr:</b></td>
+<td halign='center'><a href='test_simple_1.dmr.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='test_simple_1.dmr.dap'> DAP </a></div></td>
+<td halign='center'><a href='test_simple_1.dmr.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>dmr-testsuite/test_array_10.xml:</b></td>
+<td halign='center'><a href='dmr-testsuite/test_array_10.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_array_10.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_array_10.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>dmr-testsuite/test_array_11.xml:</b></td>
+<td halign='center'><a href='dmr-testsuite/test_array_11.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_array_11.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_array_11.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>dmr-testsuite/test_array_1.xml:</b></td>
+<td halign='center'><a href='dmr-testsuite/test_array_1.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_array_1.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_array_1.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>dmr-testsuite/test_array_2.xml:</b></td>
+<td halign='center'><a href='dmr-testsuite/test_array_2.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_array_2.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_array_2.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>dmr-testsuite/test_array_3.xml:</b></td>
+<td halign='center'><a href='dmr-testsuite/test_array_3.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_array_3.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_array_3.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>dmr-testsuite/test_array_4.xml:</b></td>
+<td halign='center'><a href='dmr-testsuite/test_array_4.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_array_4.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_array_4.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>dmr-testsuite/test_array_5.xml:</b></td>
+<td halign='center'><a href='dmr-testsuite/test_array_5.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_array_5.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_array_5.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>dmr-testsuite/test_array_6.xml:</b></td>
+<td halign='center'><a href='dmr-testsuite/test_array_6.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_array_6.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_array_6.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>dmr-testsuite/test_array_7.xml:</b></td>
+<td halign='center'><a href='dmr-testsuite/test_array_7.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_array_7.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_array_7.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>dmr-testsuite/test_array_8.xml:</b></td>
+<td halign='center'><a href='dmr-testsuite/test_array_8.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_array_8.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_array_8.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>dmr-testsuite/test_simple_10.xml:</b></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_10.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_10.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_10.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>dmr-testsuite/test_simple_1.xml:</b></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_1.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_1.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_1.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>dmr-testsuite/test_simple_2.xml:</b></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_2.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_2.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_2.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>dmr-testsuite/test_simple_3_error_1.xml:</b></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_3_error_1.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_3_error_1.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_3_error_1.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>dmr-testsuite/test_simple_3_error_2.xml:</b></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_3_error_2.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_3_error_2.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_3_error_2.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>dmr-testsuite/test_simple_3_error_3.xml:</b></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_3_error_3.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_3_error_3.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_3_error_3.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>dmr-testsuite/test_simple_3.xml:</b></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_3.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_3.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_3.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>dmr-testsuite/test_simple_4.xml:</b></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_4.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_4.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_4.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>dmr-testsuite/test_simple_5.xml:</b></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_5.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_5.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_5.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>dmr-testsuite/test_simple_6.xml:</b></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_6.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_6.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_6.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>dmr-testsuite/test_simple_7.xml:</b></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_7.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_7.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_7.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>dmr-testsuite/test_simple_8.xml:</b></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_8.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_8.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_8.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>dmr-testsuite/test_simple_9.1.xml:</b></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_9.1.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_9.1.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_9.1.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>dmr-testsuite/test_simple_9.xml:</b></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_9.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_9.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_simple_9.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>dmr-testsuite/test_escaped_paths.xml:</b></td>
+<td halign='center'><a href='dmr-testsuite/test_escaped_paths.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_escaped_paths.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='dmr-testsuite/test_escaped_paths.xml.dsr'> DSR </a></div></td>
+</tr>
+
+
+<tr>
+<td halign='right'><b>D4-xml/DMR_0.1.xml:</b></td>
+<td halign='center'><a href='D4-xml/DMR_0.1.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_0.1.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_0.1.xml.dsr'> DSR </a></div></td>
+</tr>
+
+
+<tr>
+<td halign='right'><b>D4-xml/DMR_0.xml:</b></td>
+<td halign='center'><a href='D4-xml/DMR_0.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_0.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_0.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>D4-xml/DMR_1.xml:</b></td>
+<td halign='center'><a href='D4-xml/DMR_1.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_1.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_1.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>D4-xml/DMR_2.1.xml:</b></td>
+<td halign='center'><a href='D4-xml/DMR_2.1.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_2.1.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_2.1.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>D4-xml/DMR_2.xml:</b></td>
+<td halign='center'><a href='D4-xml/DMR_2.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_2.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_2.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>D4-xml/DMR_3.1.xml:</b></td>
+<td halign='center'><a href='D4-xml/DMR_3.1.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_3.1.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_3.1.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>D4-xml/DMR_3.2.xml:</b></td>
+<td halign='center'><a href='D4-xml/DMR_3.2.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_3.2.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_3.2.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>D4-xml/DMR_3.3.xml:</b></td>
+<td halign='center'><a href='D4-xml/DMR_3.3.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_3.3.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_3.3.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>D4-xml/DMR_3.4.xml:</b></td>
+<td halign='center'><a href='D4-xml/DMR_3.4.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_3.4.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_3.4.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>D4-xml/DMR_3.5.xml:</b></td>
+<td halign='center'><a href='D4-xml/DMR_3.5.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_3.5.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_3.5.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>D4-xml/DMR_3.xml:</b></td>
+<td halign='center'><a href='D4-xml/DMR_3.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_3.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_3.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>D4-xml/DMR_4.1.xml:</b></td>
+<td halign='center'><a href='D4-xml/DMR_4.1.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_4.1.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_4.1.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>D4-xml/DMR_4.xml:</b></td>
+<td halign='center'><a href='D4-xml/DMR_4.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_4.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_4.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>D4-xml/DMR_5.1.xml:</b></td>
+<td halign='center'><a href='D4-xml/DMR_5.1.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_5.1.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_5.1.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>D4-xml/DMR_5.xml:</b></td>
+<td halign='center'><a href='D4-xml/DMR_5.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_5.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_5.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>D4-xml/DMR_6.1.xml:</b></td>
+<td halign='center'><a href='D4-xml/DMR_6.1.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_6.1.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_6.1.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>D4-xml/DMR_6.2.xml:</b></td>
+<td halign='center'><a href='D4-xml/DMR_6.2.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_6.2.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_6.2.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>D4-xml/DMR_6.xml:</b></td>
+<td halign='center'><a href='D4-xml/DMR_6.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_6.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_6.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>D4-xml/DMR_7.1.xml:</b></td>
+<td halign='center'><a href='D4-xml/DMR_7.1.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_7.1.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_7.1.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>D4-xml/DMR_7.2.xml:</b></td>
+<td halign='center'><a href='D4-xml/DMR_7.2.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_7.2.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_7.2.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>D4-xml/DMR_7.3.xml:</b></td>
+<td halign='center'><a href='D4-xml/DMR_7.3.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_7.3.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_7.3.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>D4-xml/DMR_7.4.xml:</b></td>
+<td halign='center'><a href='D4-xml/DMR_7.4.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_7.4.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_7.4.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>D4-xml/DMR_7.5.xml:</b></td>
+<td halign='center'><a href='D4-xml/DMR_7.5.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_7.5.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_7.5.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>D4-xml/DMR_7.xml:</b></td>
+<td halign='center'><a href='D4-xml/DMR_7.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_7.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_7.xml.dsr'> DSR </a></div></td>
+</tr>
+
+<tr>
+<td halign='right'><b>D4-xml/DMR_8.xml:</b></td>
+<td halign='center'><a href='D4-xml/DMR_8.xml.dmr.xml'> DMR (XML) </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_8.xml.dap'> DAP </a></div></td>
+<td halign='center'><a href='D4-xml/DMR_8.xml.dsr'> DSR </a></div></td>
+</tr>
+
+
+</table>
+<hr>
+</html>
diff --git a/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_atomic_array.nc.nc4.dap b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_atomic_array.nc.nc4.dap
new file mode 100644
index 0000000000..a190c8fd5c
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_atomic_array.nc.nc4.dap
@@ -0,0 +1,56 @@
+netcdf test_atomic_array {
+  types:
+    byte enum cloud_class_t { Clear = 0, Cumulonimbus = 1, Stratus = 2, Stratocumulus = 3, Cumulus = 4, Altostratus = 5, Nimbostratus = 6, Altocumulus = 7, Cirrostratus = 8, Cirrocumulus = 9, Cirrus = 10, Missing = 127};
+
+  dimensions:
+    d1 = 1;
+    d2 = 2;
+    d3 = 3;
+    d4 = 4;
+    d5 = 5;
+  variables:
+    ubyte vu8(d2, d3);
+
+    short v16(d4);
+
+    uint vu32(d2, d3);
+
+    double vd(d2);
+
+    char vc(d2);
+
+    String vs(d2, d2);
+
+    opaque vo(d1, d2);
+
+    enum cloud_class_t primary_cloud(d5);
+      string primary_cloud:_FillValue = "Missing";
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+vu8 =
+  {
+    {255, 1, 2},
+    {3, 4, 5}
+  }
+v16 =
+  {1, 2, 3, 4}
+vu32 =
+  {
+    {5, 4, 3},
+    {2, 1, 0}
+  }
+vd =
+  {17.9, 1024.8}
+vc =  "@&"
+vs =
+  {  "hello	world",   "
+",  "Καλημέα",   "abc"
+  }
+vo =  0x0123456789abcdef,
+  0xabcdef0000000000;
+
+primary_cloud =
+  {0, 2, 0, 1, 127}
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_atomic_array.nc.nc4.dmr b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_atomic_array.nc.nc4.dmr
new file mode 100644
index 0000000000..822a30cbc9
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_atomic_array.nc.nc4.dmr
@@ -0,0 +1,31 @@
+netcdf test_atomic_array {
+  types:
+    byte enum cloud_class_t { Clear = 0, Cumulonimbus = 1, Stratus = 2, Stratocumulus = 3, Cumulus = 4, Altostratus = 5, Nimbostratus = 6, Altocumulus = 7, Cirrostratus = 8, Cirrocumulus = 9, Cirrus = 10, Missing = 127};
+
+  dimensions:
+    d1 = 1;
+    d2 = 2;
+    d3 = 3;
+    d4 = 4;
+    d5 = 5;
+  variables:
+    ubyte vu8(d2, d3);
+
+    short v16(d4);
+
+    uint vu32(d2, d3);
+
+    double vd(d2);
+
+    char vc(d2);
+
+    String vs(d2, d2);
+
+    opaque vo(d1, d2);
+
+    enum cloud_class_t primary_cloud(d5);
+      string primary_cloud:_FillValue = "Missing";
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_atomic_types.nc.nc4.dap b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_atomic_types.nc.nc4.dap
new file mode 100644
index 0000000000..205e48eb6d
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_atomic_types.nc.nc4.dap
@@ -0,0 +1,57 @@
+netcdf test_atomic_types {
+  types:
+    byte enum cloud_class_t { Clear = 0, Cumulonimbus = 1, Stratus = 2, Stratocumulus = 3, Cumulus = 4, Altostratus = 5, Nimbostratus = 6, Altocumulus = 7, Cirrostratus = 8, Cirrocumulus = 9, Cirrus = 10, Missing = 127};
+
+  variables:
+    byte v8;
+
+    ubyte vu8;
+
+    short v16;
+
+    ushort vu16;
+
+    int v32;
+
+    uint vu32;
+
+    long v64;
+
+    ulong vu64;
+
+    float vf;
+
+    double vd;
+
+    char vc;
+
+    String vs;
+
+    opaque vo;
+
+    enum cloud_class_t primary_cloud;
+      string primary_cloud:_FillValue = "Missing";
+
+    enum cloud_class_t secondary_cloud;
+      string secondary_cloud:_FillValue = "Missing";
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+v8 =-128
+vu8 =255
+v16 =-32768
+vu16 =65535
+v32 =2147483647
+vu32 =4294967295
+v64 =9223372036854775807
+vu64 =18446744073709551615
+vf =3.1415927
+vd =3.141592653589793
+vc =@
+vs =  "hello	world"
+vo =  0x0123456789abcdef;
+
+primary_cloud =2
+secondary_cloud =127
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_atomic_types.nc.nc4.dmr b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_atomic_types.nc.nc4.dmr
new file mode 100644
index 0000000000..d771557b7f
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_atomic_types.nc.nc4.dmr
@@ -0,0 +1,40 @@
+netcdf test_atomic_types {
+  types:
+    byte enum cloud_class_t { Clear = 0, Cumulonimbus = 1, Stratus = 2, Stratocumulus = 3, Cumulus = 4, Altostratus = 5, Nimbostratus = 6, Altocumulus = 7, Cirrostratus = 8, Cirrocumulus = 9, Cirrus = 10, Missing = 127};
+
+  variables:
+    byte v8;
+
+    ubyte vu8;
+
+    short v16;
+
+    ushort vu16;
+
+    int v32;
+
+    uint vu32;
+
+    long v64;
+
+    ulong vu64;
+
+    float vf;
+
+    double vd;
+
+    char vc;
+
+    String vs;
+
+    opaque vo;
+
+    enum cloud_class_t primary_cloud;
+      string primary_cloud:_FillValue = "Missing";
+
+    enum cloud_class_t secondary_cloud;
+      string secondary_cloud:_FillValue = "Missing";
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_enum.nc.nc4.dap b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_enum.nc.nc4.dap
new file mode 100644
index 0000000000..7723b215c7
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_enum.nc.nc4.dap
@@ -0,0 +1,13 @@
+netcdf test_enum {
+  types:
+    byte enum cloud_class_t { Clear = 0, Cumulonimbus = 1, Stratus = 2, Stratocumulus = 3, Cumulus = 4, Altostratus = 5, Nimbostratus = 6, Altocumulus = 7, Cirrostratus = 8, Cirrocumulus = 9, Cirrus = 10, Missing = 127};
+
+  variables:
+    enum cloud_class_t primary_cloud;
+      string primary_cloud:_FillValue = "Missing";
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+primary_cloud =2
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_enum.nc.nc4.dmr b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_enum.nc.nc4.dmr
new file mode 100644
index 0000000000..0b98070c42
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_enum.nc.nc4.dmr
@@ -0,0 +1,11 @@
+netcdf test_enum {
+  types:
+    byte enum cloud_class_t { Clear = 0, Cumulonimbus = 1, Stratus = 2, Stratocumulus = 3, Cumulus = 4, Altostratus = 5, Nimbostratus = 6, Altocumulus = 7, Cirrostratus = 8, Cirrocumulus = 9, Cirrus = 10, Missing = 127};
+
+  variables:
+    enum cloud_class_t primary_cloud;
+      string primary_cloud:_FillValue = "Missing";
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_enum_array.nc.nc4.dap b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_enum_array.nc.nc4.dap
new file mode 100644
index 0000000000..6bc8a7ac6d
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_enum_array.nc.nc4.dap
@@ -0,0 +1,16 @@
+netcdf test_enum_array {
+  types:
+    byte enum cloud_class_t { Clear = 0, Cumulonimbus = 1, Stratus = 2, Stratocumulus = 3, Cumulus = 4, Altostratus = 5, Nimbostratus = 6, Altocumulus = 7, Cirrostratus = 8, Cirrocumulus = 9, Cirrus = 10, Missing = 127};
+
+  dimensions:
+    d5 = 5;
+  variables:
+    enum cloud_class_t primary_cloud(d5);
+      string primary_cloud:_FillValue = "Missing";
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+primary_cloud =
+  {0, 2, 0, 1, 127}
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_enum_array.nc.nc4.dmr b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_enum_array.nc.nc4.dmr
new file mode 100644
index 0000000000..0ba318f4b9
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_enum_array.nc.nc4.dmr
@@ -0,0 +1,13 @@
+netcdf test_enum_array {
+  types:
+    byte enum cloud_class_t { Clear = 0, Cumulonimbus = 1, Stratus = 2, Stratocumulus = 3, Cumulus = 4, Altostratus = 5, Nimbostratus = 6, Altocumulus = 7, Cirrostratus = 8, Cirrocumulus = 9, Cirrus = 10, Missing = 127};
+
+  dimensions:
+    d5 = 5;
+  variables:
+    enum cloud_class_t primary_cloud(d5);
+      string primary_cloud:_FillValue = "Missing";
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_one_var.nc.nc4.dap b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_one_var.nc.nc4.dap
new file mode 100644
index 0000000000..0e0abd2601
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_one_var.nc.nc4.dap
@@ -0,0 +1,9 @@
+netcdf test_one_var {
+  variables:
+    int t;
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+t =17
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_one_var.nc.nc4.dmr b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_one_var.nc.nc4.dmr
new file mode 100644
index 0000000000..e0de669035
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_one_var.nc.nc4.dmr
@@ -0,0 +1,7 @@
+netcdf test_one_var {
+  variables:
+    int t;
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_one_vararray.nc.nc4.dap b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_one_vararray.nc.nc4.dap
new file mode 100644
index 0000000000..8c531d9081
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_one_vararray.nc.nc4.dap
@@ -0,0 +1,12 @@
+netcdf test_one_vararray {
+  dimensions:
+    d2 = 2;
+  variables:
+    int t(d2);
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+t =
+  {17, 37}
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_one_vararray.nc.nc4.dmr b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_one_vararray.nc.nc4.dmr
new file mode 100644
index 0000000000..e2854e0bef
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_one_vararray.nc.nc4.dmr
@@ -0,0 +1,9 @@
+netcdf test_one_vararray {
+  dimensions:
+    d2 = 2;
+  variables:
+    int t(d2);
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_struct_array.nc.nc4.dap b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_struct_array.nc.nc4.dap
new file mode 100644
index 0000000000..8e016581fc
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_struct_array.nc.nc4.dap
@@ -0,0 +1,67 @@
+netcdf test_struct_array {
+  dimensions:
+    dx = 4;
+    dy = 3;
+  variables:
+
+    Structure {
+      int x;
+        string x:_CoordinateAxisType = "GeoX";
+      int y;
+        string y:_CoordinateAxisType = "GeoY";
+    } s(dx, dy);
+
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+s =
+  {
+    x =1
+    y =-1
+  } s(0)
+  {
+    x =17
+    y =37
+  } s(1)
+  {
+    x =-32767
+    y =32767
+  } s(2)
+  {
+    x =-1
+    y =3
+  } s(3)
+  {
+    x =-2
+    y =2
+  } s(4)
+  {
+    x =-3
+    y =1
+  } s(5)
+  {
+    x =-4
+    y =12
+  } s(6)
+  {
+    x =-8
+    y =8
+  } s(7)
+  {
+    x =-12
+    y =4
+  } s(8)
+  {
+    x =-5
+    y =15
+  } s(9)
+  {
+    x =-10
+    y =10
+  } s(10)
+  {
+    x =-15
+    y =5
+  } s(11)
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_struct_array.nc.nc4.dmr b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_struct_array.nc.nc4.dmr
new file mode 100644
index 0000000000..da24f7ca51
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_struct_array.nc.nc4.dmr
@@ -0,0 +1,17 @@
+netcdf test_struct_array {
+  dimensions:
+    dx = 4;
+    dy = 3;
+  variables:
+
+    Structure {
+      int x;
+        string x:_CoordinateAxisType = "GeoX";
+      int y;
+        string y:_CoordinateAxisType = "GeoY";
+    } s(dx, dy);
+
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_struct_nested.nc.nc4.dap b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_struct_nested.nc.nc4.dap
new file mode 100644
index 0000000000..910c4da5be
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_struct_nested.nc.nc4.dap
@@ -0,0 +1,38 @@
+netcdf test_struct_nested {
+  variables:
+
+    Structure {
+
+      Structure {
+        int x;
+          string x:_CoordinateAxisType = "GeoX";
+        int y;
+          string y:_CoordinateAxisType = "GeoY";
+      } field1;
+
+
+      Structure {
+        int x;
+        int y;
+      } field2;
+
+    } x;
+
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+  data:
+    x =
+      {
+        field1 =
+          {
+            x = 1
+            y = -2
+          } x.field1(0)
+        field2 =
+          {
+            x = 255
+            y = 90
+          } x.field2(0)
+      } x(0)
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_struct_nested.nc.nc4.dmr b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_struct_nested.nc.nc4.dmr
new file mode 100644
index 0000000000..5c6dbc9f0e
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_struct_nested.nc.nc4.dmr
@@ -0,0 +1,24 @@
+netcdf test_struct_nested {
+  variables:
+
+    Structure {
+
+      Structure {
+        int x;
+          string x:_CoordinateAxisType = "GeoX";
+        int y;
+          string y:_CoordinateAxisType = "GeoY";
+      } field1;
+
+
+      Structure {
+        int x;
+        int y;
+      } field2;
+
+    } x;
+
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_struct_type.nc.nc4.dap b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_struct_type.nc.nc4.dap
new file mode 100644
index 0000000000..4992d822d1
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_struct_type.nc.nc4.dap
@@ -0,0 +1,21 @@
+netcdf test_struct_type {
+  variables:
+
+    Structure {
+      int x;
+        string x:_CoordinateAxisType = "GeoX";
+      int y;
+        string y:_CoordinateAxisType = "GeoY";
+    } s;
+
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+  data:
+    s =
+      {
+        x = 1
+        y = -2
+      } s(0)
+}
+
diff --git a/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_struct_type.nc.nc4.dmr b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_struct_type.nc.nc4.dmr
new file mode 100644
index 0000000000..b9ec67883a
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_struct_type.nc.nc4.dmr
@@ -0,0 +1,14 @@
+netcdf test_struct_type {
+  variables:
+
+    Structure {
+      int x;
+        string x:_CoordinateAxisType = "GeoX";
+      int y;
+        string y:_CoordinateAxisType = "GeoY";
+    } s;
+
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_vlen1.nc.nc4.dap b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_vlen1.nc.nc4.dap
new file mode 100644
index 0000000000..5d305d252d
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_vlen1.nc.nc4.dap
@@ -0,0 +1,11 @@
+netcdf test_vlen1 {
+  variables:
+    int x(*);
+      string x:_CoordinateAxisType = "GeoX";
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+x =
+  {1, 3, 5, 7}
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_vlen1.nc.nc4.dmr b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_vlen1.nc.nc4.dmr
new file mode 100644
index 0000000000..998c2beeeb
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_vlen1.nc.nc4.dmr
@@ -0,0 +1,8 @@
+netcdf test_vlen1 {
+  variables:
+    int x(*);
+      string x:_CoordinateAxisType = "GeoX";
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_vlen2.nc.nc4.dap b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_vlen2.nc.nc4.dap
new file mode 100644
index 0000000000..d3d3a93f76
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_vlen2.nc.nc4.dap
@@ -0,0 +1,21 @@
+netcdf test_vlen2 {
+  dimensions:
+    d3 = 3;
+    d2 = 2;
+  variables:
+    int x(d3, d2, *);
+      string x:_CoordinateAxisType = "GeoX";
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+  data:
+    x =
+      {
+        {1, 3, 5, 7},
+        {100, 200},
+        {-1, -2},
+        {1, 3, 5, 7},
+        {100, 200},
+        {-1, -2}
+      }
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_vlen2.nc.nc4.dmr b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_vlen2.nc.nc4.dmr
new file mode 100644
index 0000000000..3c5a459470
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_vlen2.nc.nc4.dmr
@@ -0,0 +1,11 @@
+netcdf test_vlen2 {
+  dimensions:
+    d3 = 3;
+    d2 = 2;
+  variables:
+    int x(d3, d2, *);
+      string x:_CoordinateAxisType = "GeoX";
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_vlen3.nc.nc4.dap b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_vlen3.nc.nc4.dap
new file mode 100644
index 0000000000..4378f59fec
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_vlen3.nc.nc4.dap
@@ -0,0 +1,17 @@
+netcdf test_vlen3 {
+  variables:
+
+    Structure {
+      int f1(*);
+    } v1;
+
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+  data:
+    v1 =
+      {
+        f1 =
+          {1, 3, 5, 7}
+      } v1(0)
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_vlen3.nc.nc4.dmr b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_vlen3.nc.nc4.dmr
new file mode 100644
index 0000000000..348943c043
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_vlen3.nc.nc4.dmr
@@ -0,0 +1,11 @@
+netcdf test_vlen3 {
+  variables:
+
+    Structure {
+      int f1(*);
+    } v1;
+
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_vlen4.nc.nc4.dap b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_vlen4.nc.nc4.dap
new file mode 100644
index 0000000000..98123a9714
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_vlen4.nc.nc4.dap
@@ -0,0 +1,20 @@
+netcdf test_vlen4 {
+  variables:
+
+    Structure {
+      int f1(2, *);
+    } v1;
+
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+  data:
+    v1 =
+      {
+        f1 =
+          {
+            {1, 3, 5, 7},
+            {100, 200}
+          }
+      } v1(0)
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_vlen4.nc.nc4.dmr b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_vlen4.nc.nc4.dmr
new file mode 100644
index 0000000000..066d3c44e6
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_vlen4.nc.nc4.dmr
@@ -0,0 +1,11 @@
+netcdf test_vlen4 {
+  variables:
+
+    Structure {
+      int f1(2, *);
+    } v1;
+
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_vlen5.nc.nc4.dap b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_vlen5.nc.nc4.dap
new file mode 100644
index 0000000000..c81542fb0b
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_vlen5.nc.nc4.dap
@@ -0,0 +1,23 @@
+netcdf test_vlen5 {
+  dimensions:
+    d2 = 2;
+  variables:
+
+    Structure {
+      int v(*);
+    } v1(d2);
+
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+v1 =
+  {
+    v =
+      {1, 3, 5, 7}
+  } v1(0)
+  {
+    v =
+      {100, 200}
+  } v1(1)
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_vlen5.nc.nc4.dmr b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_vlen5.nc.nc4.dmr
new file mode 100644
index 0000000000..057180f582
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestIosp/baseline/test_vlen5.nc.nc4.dmr
@@ -0,0 +1,13 @@
+netcdf test_vlen5 {
+  dimensions:
+    d2 = 2;
+  variables:
+
+    Structure {
+      int v(*);
+    } v1(d2);
+
+
+  // global attributes:
+  string :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_anon_dim.syn.dmp b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_anon_dim.syn.dmp
new file mode 100644
index 0000000000..b896565843
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_anon_dim.syn.dmp
@@ -0,0 +1,11 @@
+<Dataset
+         name="test_anon_dim.syn"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+
+    <Int32 name="vu32">
+        <Dim size="6"/>
+    </Int32>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_atomic_array.nc.dmp b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_atomic_array.nc.dmp
new file mode 100644
index 0000000000..7cf1a5e403
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_atomic_array.nc.dmp
@@ -0,0 +1,57 @@
+<Dataset
+         name="test_atomic_array.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d1" size="1"/>
+    <Dimension name="d2" size="2"/>
+    <Dimension name="d3" size="3"/>
+    <Dimension name="d4" size="4"/>
+    <Dimension name="d5" size="5"/>
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <UInt8 name="vu8">
+        <Dim name="/d2"/>
+        <Dim name="/d3"/>
+    </UInt8>
+    <Int16 name="v16">
+        <Dim name="/d4"/>
+    </Int16>
+    <UInt32 name="vu32">
+        <Dim name="/d2"/>
+        <Dim name="/d3"/>
+    </UInt32>
+    <Float64 name="vd">
+        <Dim name="/d2"/>
+    </Float64>
+    <Char name="vc">
+        <Dim name="/d2"/>
+    </Char>
+    <String name="vs">
+        <Dim name="/d2"/>
+        <Dim name="/d2"/>
+    </String>
+    <Opaque name="vo">
+        <Dim name="/d1"/>
+        <Dim name="/d2"/>
+    </Opaque>
+    <Enum name="primary_cloud" enum="/cloud_class_t">
+        <Dim name="/d5"/>
+        <Attribute name="_FillValue" type="/cloud_class_t">
+            <Value value="Missing"/>
+        </Attribute>
+    </Enum>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_atomic_array.syn.dmp b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_atomic_array.syn.dmp
new file mode 100644
index 0000000000..bd0cb4b45d
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_atomic_array.syn.dmp
@@ -0,0 +1,57 @@
+<Dataset
+         name="test_atomic_array.syn"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d1" size="1"/>
+    <Dimension name="d2" size="2"/>
+    <Dimension name="d3" size="3"/>
+    <Dimension name="d4" size="4"/>
+    <Dimension name="d5" size="5"/>
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <UInt8 name="vu8">
+        <Dim name="/d2"/>
+        <Dim name="/d3"/>
+    </UInt8>
+    <Int16 name="v16">
+        <Dim name="/d4"/>
+    </Int16>
+    <UInt32 name="vu32">
+        <Dim name="/d2"/>
+        <Dim name="/d3"/>
+    </UInt32>
+    <Float64 name="vd">
+        <Dim name="/d2"/>
+    </Float64>
+    <Char name="vc">
+        <Dim name="/d2"/>
+    </Char>
+    <String name="vs">
+        <Dim name="/d2"/>
+        <Dim name="/d2"/>
+    </String>
+    <Opaque name="vo">
+        <Dim name="/d1"/>
+        <Dim name="/d2"/>
+    </Opaque>
+    <Enum name="primary_cloud" enum="/cloud_class_t">
+        <Dim name="/d5"/>
+        <Attribute name="_FillValue" type="/cloud_class_t">
+            <Value value="Missing"/>
+        </Attribute>
+    </Enum>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_atomic_types.nc.dmp b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_atomic_types.nc.dmp
new file mode 100644
index 0000000000..4df4aa5da0
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_atomic_types.nc.dmp
@@ -0,0 +1,44 @@
+<Dataset
+         name="test_atomic_types.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <Int8 name="v8"/>
+    <UInt8 name="vu8"/>
+    <Int16 name="v16"/>
+    <UInt16 name="vu16"/>
+    <Int32 name="v32"/>
+    <UInt32 name="vu32"/>
+    <Int64 name="v64"/>
+    <UInt64 name="vu64"/>
+    <Float32 name="vf"/>
+    <Float64 name="vd"/>
+    <Char name="vc"/>
+    <String name="vs"/>
+    <Opaque name="vo"/>
+    <Enum name="primary_cloud" enum="/cloud_class_t">
+        <Attribute name="_FillValue" type="/cloud_class_t">
+            <Value value="Missing"/>
+        </Attribute>
+    </Enum>
+    <Enum name="secondary_cloud" enum="/cloud_class_t">
+        <Attribute name="_FillValue" type="/cloud_class_t">
+            <Value value="Missing"/>
+        </Attribute>
+    </Enum>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_atomic_types.syn.dmp b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_atomic_types.syn.dmp
new file mode 100644
index 0000000000..20b725a3dc
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_atomic_types.syn.dmp
@@ -0,0 +1,44 @@
+<Dataset
+         name="test_atomic_types.syn"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <Int8 name="v8"/>
+    <UInt8 name="vu8"/>
+    <Int16 name="v16"/>
+    <UInt16 name="vu16"/>
+    <Int32 name="v32"/>
+    <UInt32 name="vu32"/>
+    <Int64 name="v64"/>
+    <UInt64 name="vu64"/>
+    <Float32 name="vf"/>
+    <Float64 name="vd"/>
+    <Char name="vc"/>
+    <String name="vs"/>
+    <Opaque name="vo"/>
+    <Enum name="primary_cloud" enum="/cloud_class_t">
+        <Attribute name="_FillValue" type="/cloud_class_t">
+            <Value value="Missing"/>
+        </Attribute>
+    </Enum>
+    <Enum name="secondary_cloud" enum="/cloud_class_t">
+        <Attribute name="_FillValue" type="/cloud_class_t">
+            <Value value="Missing"/>
+        </Attribute>
+    </Enum>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_enum.nc.dmp b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_enum.nc.dmp
new file mode 100644
index 0000000000..3f1f4955af
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_enum.nc.dmp
@@ -0,0 +1,26 @@
+<Dataset
+         name="test_enum.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <Enum name="primary_cloud" enum="/cloud_class_t">
+        <Attribute name="_FillValue" type="/cloud_class_t">
+            <Value value="Missing"/>
+        </Attribute>
+    </Enum>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_enum_2.nc.dmp b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_enum_2.nc.dmp
new file mode 100644
index 0000000000..7f32c83158
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_enum_2.nc.dmp
@@ -0,0 +1,28 @@
+<Dataset
+         name="test_enum_2.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <Group name="h">
+        <Enum name="primary_cloud" enum="/cloud_class_t">
+            <Attribute name="_FillValue" type="/cloud_class_t">
+                <Value value="Missing"/>
+            </Attribute>
+        </Enum>
+    </Group>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_enum_array.nc.dmp b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_enum_array.nc.dmp
new file mode 100644
index 0000000000..10cc7cc4c6
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_enum_array.nc.dmp
@@ -0,0 +1,28 @@
+<Dataset
+         name="test_enum_array.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d5" size="5"/>
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <Enum name="primary_cloud" enum="/cloud_class_t">
+        <Dim name="/d5"/>
+        <Attribute name="_FillValue" type="/cloud_class_t">
+            <Value value="Missing"/>
+        </Attribute>
+    </Enum>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_fill.nc.dmp b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_fill.nc.dmp
new file mode 100644
index 0000000000..102ddb78f8
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_fill.nc.dmp
@@ -0,0 +1,14 @@
+<Dataset
+         name="test_fill.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <UInt8 name="uv8"/>
+    <Int16 name="v16"/>
+    <UInt32 name="uv32">
+        <Attribute name="_FillValue" type="UInt32">
+            <Value value="17"/>
+        </Attribute>
+    </UInt32>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_groups1.nc.dmp b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_groups1.nc.dmp
new file mode 100644
index 0000000000..8e5fab8c10
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_groups1.nc.dmp
@@ -0,0 +1,29 @@
+<Dataset
+         name="test_groups1.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="dim1" size="5"/>
+    <Group name="g">
+        <Dimension name="dim2" size="3"/>
+        <Group name="h">
+            <Dimension name="dim3" size="7"/>
+            <Int32 name="v1">
+                <Dim name="/dim1"/>
+            </Int32>
+            <Float32 name="v2">
+                <Dim name="/g/dim2"/>
+            </Float32>
+        </Group>
+        <Group name="i">
+            <Dimension name="dim3" size="7"/>
+            <Int32 name="v1">
+                <Dim name="/dim1"/>
+            </Int32>
+            <Float32 name="v3">
+                <Dim name="/g/i/dim3"/>
+            </Float32>
+        </Group>
+    </Group>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_one_var.nc.dmp b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_one_var.nc.dmp
new file mode 100644
index 0000000000..3c22f7dc4f
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_one_var.nc.dmp
@@ -0,0 +1,8 @@
+<Dataset
+         name="test_one_var.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Int32 name="t"/>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_one_vararray.nc.dmp b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_one_vararray.nc.dmp
new file mode 100644
index 0000000000..0ee3460abb
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_one_vararray.nc.dmp
@@ -0,0 +1,11 @@
+<Dataset
+         name="test_one_vararray.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d2" size="2"/>
+    <Int32 name="t">
+        <Dim name="/d2"/>
+    </Int32>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_opaque.nc.dmp b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_opaque.nc.dmp
new file mode 100644
index 0000000000..e6fe81a73b
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_opaque.nc.dmp
@@ -0,0 +1,8 @@
+<Dataset
+         name="test_opaque.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Opaque name="vo1"/>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_opaque_array.nc.dmp b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_opaque_array.nc.dmp
new file mode 100644
index 0000000000..83fda8f237
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_opaque_array.nc.dmp
@@ -0,0 +1,12 @@
+<Dataset
+         name="test_opaque_array.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d2" size="2"/>
+    <Opaque name="vo2">
+        <Dim name="/d2"/>
+        <Dim name="/d2"/>
+    </Opaque>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_sequence_1.syn.dmp b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_sequence_1.syn.dmp
new file mode 100644
index 0000000000..87eab777e3
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_sequence_1.syn.dmp
@@ -0,0 +1,11 @@
+<Dataset
+         name="test_sequence_1.syn"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Sequence name="s">
+        <Int32 name="i1"/>
+        <Int16 name="sh1"/>
+    </Sequence>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_sequence_2.syn.dmp b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_sequence_2.syn.dmp
new file mode 100644
index 0000000000..f048a358eb
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_sequence_2.syn.dmp
@@ -0,0 +1,13 @@
+<Dataset
+         name="test_sequence_2.syn"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+
+    <Sequence name="s">
+        <Int32 name="i1"/>
+        <Int16 name="sh1"/>
+        <Dim size="2"/>
+    </Sequence>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_struct_array.nc.dmp b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_struct_array.nc.dmp
new file mode 100644
index 0000000000..41fc6a6b0a
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_struct_array.nc.dmp
@@ -0,0 +1,15 @@
+<Dataset
+         name="test_struct_array.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="dx" size="4"/>
+    <Dimension name="dy" size="3"/>
+    <Structure name="s">
+        <Int32 name="x"/>
+        <Int32 name="y"/>
+        <Dim name="/dx"/>
+        <Dim name="/dy"/>
+    </Structure>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_struct_array.syn.dmp b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_struct_array.syn.dmp
new file mode 100644
index 0000000000..86f50d491f
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_struct_array.syn.dmp
@@ -0,0 +1,21 @@
+<Dataset
+         name="test_struct_array.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="dx" size="4"/>
+    <Dimension name="dy" size="3"/>
+    <Float32 name="z">
+        <Dim name="/dx"/>
+    </Float32>
+    <Float32 name="t">
+        <Dim name="/dy"/>
+    </Float32>
+    <Structure name="s">
+        <Int32 name="x"/>
+        <Int32 name="y"/>
+        <Dim name="/dx"/>
+        <Dim name="/dy"/>
+    </Structure>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_struct_nested.hdf5.dmp b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_struct_nested.hdf5.dmp
new file mode 100644
index 0000000000..af76ed1db2
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_struct_nested.hdf5.dmp
@@ -0,0 +1,17 @@
+<Dataset
+         name="test_struct_nested.hdf5"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Structure name="x">
+        <Structure name="field1">
+            <Int32 name="x"/>
+            <Int32 name="y"/>
+        </Structure>
+        <Structure name="field2">
+            <Int32 name="x"/>
+            <Int32 name="y"/>
+        </Structure>
+    </Structure>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_struct_nested3.hdf5.dmp b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_struct_nested3.hdf5.dmp
new file mode 100644
index 0000000000..94e98a5c0c
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_struct_nested3.hdf5.dmp
@@ -0,0 +1,14 @@
+<Dataset
+         name="test_struct_nested3.hdf5"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Structure name="x">
+        <Structure name="field3">
+            <Structure name="field2">
+                <Int32 name="field1"/>
+            </Structure>
+        </Structure>
+    </Structure>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_struct_type.nc.dmp b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_struct_type.nc.dmp
new file mode 100644
index 0000000000..bcb2fa03fe
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_struct_type.nc.dmp
@@ -0,0 +1,11 @@
+<Dataset
+         name="test_struct_type.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Structure name="s">
+        <Int32 name="x"/>
+        <Int32 name="y"/>
+    </Structure>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_utf8.nc.dmp b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_utf8.nc.dmp
new file mode 100644
index 0000000000..f4aea87c2e
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_utf8.nc.dmp
@@ -0,0 +1,11 @@
+<Dataset
+         name="test_utf8.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d2" size="2"/>
+    <String name="vs">
+        <Dim name="/d2"/>
+    </String>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_vlen1.nc.dmp b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_vlen1.nc.dmp
new file mode 100644
index 0000000000..6e48278698
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_vlen1.nc.dmp
@@ -0,0 +1,10 @@
+<Dataset
+         name="test_vlen1.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Sequence name="x">
+        <Int32 name="x"/>
+    </Sequence>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_vlen2.nc.dmp b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_vlen2.nc.dmp
new file mode 100644
index 0000000000..c3ed6dc427
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_vlen2.nc.dmp
@@ -0,0 +1,14 @@
+<Dataset
+         name="test_vlen2.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d3" size="3"/>
+    <Dimension name="d2" size="2"/>
+    <Sequence name="x">
+        <Int32 name="x"/>
+        <Dim name="/d3"/>
+        <Dim name="/d2"/>
+    </Sequence>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_vlen3.hdf5.dmp b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_vlen3.hdf5.dmp
new file mode 100644
index 0000000000..629aa6d3d1
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_vlen3.hdf5.dmp
@@ -0,0 +1,12 @@
+<Dataset
+         name="test_vlen3.hdf5"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Structure name="v1">
+        <Sequence name="f1">
+            <Int32 name="f1"/>
+        </Sequence>
+    </Structure>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_vlen5.hdf5.dmp b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_vlen5.hdf5.dmp
new file mode 100644
index 0000000000..9dc7d03d8a
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/test_vlen5.hdf5.dmp
@@ -0,0 +1,14 @@
+<Dataset
+         name="test_vlen5.hdf5"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d2" size="2"/>
+    <Structure name="v1">
+        <Sequence name="v">
+            <Int32 name="v"/>
+        </Sequence>
+        <Dim name="/d2"/>
+    </Structure>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/baseline/testall.dmp b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/testall.dmp
new file mode 100644
index 0000000000..bd3be31235
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/baseline/testall.dmp
@@ -0,0 +1,57 @@
+<Dataset
+         name="example"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d1" size="10"/>
+    <Dimension name="lat" size="20"/>
+    <Dimension name="lon" size="20"/>
+
+
+    <Enumeration name="e1" basetype="UInt8">
+        <EnumConst name="econst1" value="1"/>
+        <EnumConst name="econst2" value="2"/>
+    </Enumeration>
+    <Int32 name="x"/>
+    <Float32 name="lat">
+        <Dim name="/lat"/>
+    </Float32>
+    <Float32 name="lon">
+        <Dim name="/lon"/>
+    </Float32>
+    <Sequence name="y">
+        <Structure name="y">
+            <Opaque name="f1"/>
+            <Dim size="17"/>
+            <Attribute name="a1" type="Int32">
+                <Value value="5"/>
+            </Attribute>
+            <Attribute name="a2" type="Float64">
+                <Value value="7.5"/>
+                <Value value="10"/>
+            </Attribute>
+            <Attribute name="a3" type="String">
+                <Value value="abcd &quot;hello&quot; &quot;quoted&quot;"/>
+            </Attribute>
+        </Structure>
+        <Dim name="/d1"/>
+        <Dim size="10"/>
+    </Sequence>
+    <Int32 name="funny">
+        <Dim name="/g\.@\/\\$/lon\/2\.&quot;"/>
+    </Int32>
+    <Group name="g1">
+        <Dimension name="d1" size="10"/>
+        <Dimension name="d2" size="20"/>
+        <Float32 name="tempb">
+            <Dim name="/lat"/>
+            <Dim name="/lon"/>
+            <Dim name="/g1/d2"/>
+        </Float32>
+        <Enum name="evar" enum="/e1"/>
+    </Group>
+    <Group name="g.@/\$">
+        <Dimension name="lon/2.&quot;" size="20"/>
+    </Group>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_atomic_array.nc.dmr b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_atomic_array.nc.dmr
new file mode 100644
index 0000000000..29a61e7c8b
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_atomic_array.nc.dmr
@@ -0,0 +1,57 @@
+<Dataset
+         name="test_atomic_array.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d1" size="1"/>
+    <Dimension name="d2" size="2"/>
+    <Dimension name="d3" size="3"/>
+    <Dimension name="d4" size="4"/>
+    <Dimension name="d5" size="5"/>
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <UInt8 name="vu8">
+        <Dim name="/d2"/>
+        <Dim name="/d3"/>
+    </UInt8>
+    <Int16 name="v16">
+        <Dim name="/d4"/>
+    </Int16>
+    <UInt32 name="vu32">
+        <Dim name="/d2"/>
+        <Dim name="/d3"/>
+    </UInt32>
+    <Float64 name="vd">
+        <Dim name="/d2"/>
+    </Float64>
+    <Char name="vc">
+        <Dim name="/d2"/>
+    </Char>
+    <String name="vs">
+        <Dim name="/d2"/>
+        <Dim name="/d2"/>
+    </String>
+    <Opaque name="vo">
+        <Dim name="/d1"/>
+        <Dim name="/d2"/>
+    </Opaque>
+    <Enum name="primary_cloud" enum="/cloud_class_t">
+        <Dim name="/d5"/>
+        <Attribute name="_FillValue" type="/cloud_class_t">
+            <Value value="Missing"/>
+	</Attribute>
+    </Enum>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_atomic_array.syn.dmr b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_atomic_array.syn.dmr
new file mode 100644
index 0000000000..3519a327b0
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_atomic_array.syn.dmr
@@ -0,0 +1,57 @@
+<Dataset
+         name="test_atomic_array.syn"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d1" size="1"/>
+    <Dimension name="d2" size="2"/>
+    <Dimension name="d3" size="3"/>
+    <Dimension name="d4" size="4"/>
+    <Dimension name="d5" size="5"/>
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <UInt8 name="vu8">
+        <Dim name="/d2"/>
+        <Dim name="/d3"/>
+    </UInt8>
+    <Int16 name="v16">
+        <Dim name="/d4"/>
+    </Int16>
+    <UInt32 name="vu32">
+        <Dim name="/d2"/>
+        <Dim name="/d3"/>
+    </UInt32>
+    <Float64 name="vd">
+        <Dim name="/d2"/>
+    </Float64>
+    <Char name="vc">
+        <Dim name="/d2"/>
+    </Char>
+    <String name="vs">
+        <Dim name="/d2"/>
+        <Dim name="/d2"/>
+    </String>
+    <Opaque name="vo">
+        <Dim name="/d1"/>
+        <Dim name="/d2"/>
+    </Opaque>
+    <Enum name="primary_cloud" enum="/cloud_class_t">
+        <Dim name="/d5"/>
+        <Attribute name="_FillValue" type="/cloud_class_t">
+            <Value value="Missing"/>
+        </Attribute>
+    </Enum>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_atomic_types.nc.dmr b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_atomic_types.nc.dmr
new file mode 100644
index 0000000000..aef3b9eda0
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_atomic_types.nc.dmr
@@ -0,0 +1,44 @@
+<Dataset
+         name="test_atomic_types.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <Int8 name="v8"/>
+    <UInt8 name="vu8"/>
+    <Int16 name="v16"/>
+    <UInt16 name="vu16"/>
+    <Int32 name="v32"/>
+    <UInt32 name="vu32"/>
+    <Int64 name="v64"/>
+    <UInt64 name="vu64"/>
+    <Float32 name="vf"/>
+    <Float64 name="vd"/>
+    <Char name="vc"/>
+    <String name="vs"/>
+    <Opaque name="vo"/>
+    <Enum name="primary_cloud" enum="/cloud_class_t">
+        <Attribute name="_FillValue" type="/cloud_class_t">
+            <Value value="Missing"/>
+        </Attribute>
+    </Enum>
+    <Enum name="secondary_cloud" enum="/cloud_class_t">
+        <Attribute name="_FillValue" type="/cloud_class_t">
+            <Value value="Missing"/>
+        </Attribute>
+    </Enum>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_atomic_types.syn.dmr b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_atomic_types.syn.dmr
new file mode 100644
index 0000000000..ec5ed7d9f7
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_atomic_types.syn.dmr
@@ -0,0 +1,48 @@
+<Dataset
+         name="test_atomic_types.syn"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <Int8 name="v8"/>
+    <UInt8 name="vu8">
+    </UInt8>
+    <Int16 name="v16"/>
+    <UInt16 name="vu16">
+    </UInt16>
+    <Int32 name="v32"/>
+    <UInt32 name="vu32">
+    </UInt32>
+    <Int64 name="v64"/>
+    <UInt64 name="vu64">
+    </UInt64>
+    <Float32 name="vf"/>
+    <Float64 name="vd"/>
+    <Char name="vc"/>
+    <String name="vs"/>
+    <Opaque name="vo"/>
+    <Enum name="primary_cloud" enum="/cloud_class_t">
+        <Attribute name="_FillValue" type="/cloud_class_t">
+            <Value value="Missing"/>
+        </Attribute>
+    </Enum>
+    <Enum name="secondary_cloud" enum="/cloud_class_t">
+        <Attribute name="_FillValue" type="/cloud_class_t">
+            <Value value="Missing"/>
+        </Attribute>
+    </Enum>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_enum.nc.dmr b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_enum.nc.dmr
new file mode 100644
index 0000000000..10841fbc27
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_enum.nc.dmr
@@ -0,0 +1,26 @@
+<Dataset
+         name="test_enum.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <Enum name="primary_cloud" enum="/cloud_class_t">
+        <Attribute name="_FillValue" type="/cloud_class_t">
+            <Value value="Missing"/>
+        </Attribute>
+    </Enum>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_enum_array.nc.dmr b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_enum_array.nc.dmr
new file mode 100644
index 0000000000..bfa1765093
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_enum_array.nc.dmr
@@ -0,0 +1,28 @@
+<Dataset
+         name="test_enum_array.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d5" size="5"/>
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <Enum name="primary_cloud" enum="/cloud_class_t">
+        <Dim name="/d5"/>
+        <Attribute name="_FillValue" type="/cloud_class_t">
+            <Value value="Missing"/>
+        </Attribute>
+    </Enum>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_groups1.nc.dmr b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_groups1.nc.dmr
new file mode 100644
index 0000000000..80f918edc6
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_groups1.nc.dmr
@@ -0,0 +1,29 @@
+<Dataset
+         name="test_groups1.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="dim1" size="5"/>
+    <Group name="g">
+        <Dimension name="dim2" size="3"/>
+        <Group name="h">
+            <Dimension name="dim3" size="7"/>
+            <Int32 name="v1">
+                <Dim name="/dim1"/>
+            </Int32>
+            <Float32 name="v2">
+                <Dim name="/g/dim2"/>
+            </Float32>
+        </Group>
+        <Group name="i">
+            <Dimension name="dim3" size="7"/>
+            <Int32 name="v1">
+                <Dim name="/dim1"/>
+            </Int32>
+            <Float32 name="v3">
+                <Dim name="/g/i/dim3"/>
+            </Float32>
+        </Group>
+    </Group>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_one_var.nc.dmr b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_one_var.nc.dmr
new file mode 100644
index 0000000000..89016b1816
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_one_var.nc.dmr
@@ -0,0 +1,8 @@
+<Dataset
+         name="test_one_var.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Int32 name="t"/>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_one_vararray.nc.dmr b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_one_vararray.nc.dmr
new file mode 100644
index 0000000000..8f199d1cb1
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_one_vararray.nc.dmr
@@ -0,0 +1,11 @@
+<Dataset
+         name="test_one_vararray.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d2" size="2"/>
+    <Int32 name="t">
+        <Dim name="/d2"/>
+    </Int32>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_struct_array.nc.dmr b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_struct_array.nc.dmr
new file mode 100644
index 0000000000..8dabe14882
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_struct_array.nc.dmr
@@ -0,0 +1,15 @@
+<Dataset
+         name="test_struct_array.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="dx" size="4"/>
+    <Dimension name="dy" size="3"/>
+    <Structure name="s">
+        <Int32 name="x"/>
+        <Int32 name="y"/>
+        <Dim name="/dx"/>
+        <Dim name="/dy"/>
+    </Structure>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_struct_nested.hdf5.dmr b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_struct_nested.hdf5.dmr
new file mode 100644
index 0000000000..376824981e
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_struct_nested.hdf5.dmr
@@ -0,0 +1,17 @@
+<Dataset
+         name="test_struct_nested.hdf5"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Structure name="x">
+        <Structure name="field1">
+            <Int32 name="x"/>
+            <Int32 name="y"/>
+        </Structure>
+        <Structure name="field2">
+            <Int32 name="x"/>
+            <Int32 name="y"/>
+        </Structure>
+    </Structure>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_struct_nested3.hdf5.dmr b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_struct_nested3.hdf5.dmr
new file mode 100644
index 0000000000..03ac53d23c
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_struct_nested3.hdf5.dmr
@@ -0,0 +1,14 @@
+<Dataset
+         name="test_struct_nested3.hdf5"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Structure name="x">
+        <Structure name="field3">
+            <Structure name="field2">
+                <Int32 name="field1"/>
+            </Structure>
+        </Structure>
+    </Structure>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_struct_type.nc.dmr b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_struct_type.nc.dmr
new file mode 100644
index 0000000000..4e2adb0c1d
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_struct_type.nc.dmr
@@ -0,0 +1,11 @@
+<Dataset
+         name="test_struct_type.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Structure name="s">
+        <Int32 name="x"/>
+        <Int32 name="y"/>
+    </Structure>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_utf8.nc.dmr b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_utf8.nc.dmr
new file mode 100644
index 0000000000..74115be967
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_utf8.nc.dmr
@@ -0,0 +1,11 @@
+<Dataset
+         name="test_utf8.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d2" size="2"/>
+    <String name="vs">
+        <Dim name="/d2"/>
+    </String>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_vlen1.nc.dmr b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_vlen1.nc.dmr
new file mode 100644
index 0000000000..b30754e1b2
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_vlen1.nc.dmr
@@ -0,0 +1,10 @@
+<Dataset
+         name="test_vlen1.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Sequence name="x">
+        <Int32 name="x"/>
+    </Sequence>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_vlen2.nc.dmr b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_vlen2.nc.dmr
new file mode 100644
index 0000000000..cea92859ec
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_vlen2.nc.dmr
@@ -0,0 +1,14 @@
+<Dataset
+         name="test_vlen2.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d3" size="3"/>
+    <Dimension name="d2" size="2"/>
+    <Sequence name="x">
+        <Int32 name="x"/>
+        <Dim name="/d3"/>
+        <Dim name="/d2"/>
+    </Sequence>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_vlen3.hdf5.dmr b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_vlen3.hdf5.dmr
new file mode 100644
index 0000000000..dbad545664
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_vlen3.hdf5.dmr
@@ -0,0 +1,12 @@
+<Dataset
+         name="test_vlen3.hdf5"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Structure name="v1">
+        <Sequence name="f1">
+            <Int32 name="f1"/>
+        </Sequence>
+    </Structure>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_vlen5.hdf5.dmr b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_vlen5.hdf5.dmr
new file mode 100644
index 0000000000..20cc09a17b
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/test_vlen5.hdf5.dmr
@@ -0,0 +1,14 @@
+<Dataset
+         name="test_vlen5.hdf5"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d2" size="2"/>
+    <Structure name="v1">
+        <Sequence name="v">
+            <Int32 name="v"/>
+        </Sequence>
+        <Dim name="/d2"/>
+    </Structure>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/testall.dmr b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/testall.dmr
new file mode 100644
index 0000000000..0e2bf5de38
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/dmrset/testall.dmr
@@ -0,0 +1,78 @@
+<Dataset name="example"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+        >
+
+<Dimension name="d1" size="10"/>
+<Dimension name="lat" size="20"/>
+<Dimension name="lon" size="20"/>
+
+<Enumeration name="e1" basetype="UInt8">
+  <EnumConst name="econst1" value="1"/>
+  <EnumConst name="econst2" value="2"/>
+</Enumeration>
+
+<Int32 name="x"/>
+<Float32 name="lat">
+  <Dim name="/lat"/>
+</Float32>
+<Float32 name="lon">
+  <Dim name="/lon"/>
+</Float32>
+<Sequence name="y">
+  <Structure name="y">
+    <Opaque name="f1"/>
+    <Attribute name="a1" type="Int32">
+      <Value value="5"/>
+    </Attribute>
+    <Attribute name="a2" type="Float64">
+      <Value value="7.5"/>    
+      <Value>10</Value>
+    </Attribute>  
+    <Attribute name="a3" type="String">
+      <Value>abcd &quot;hello&quot; &quot;quoted&quot;</Value>
+    </Attribute>
+    <Dim size="17"/>
+  </Structure>
+  <Dim name="/d1"/>
+  <Dim size="10"/>
+</Sequence>
+  
+<Group name="g1">
+  <Dimension name="d1" size="10"/>
+  <Dimension name="d2" size="20"/>
+
+  <Float32 name="tempb">
+    <Dim name="/lat"/>
+    <Dim name="/lon"/>
+    <Dim name="/g1/d2"/>
+    <Map name="/lat"/>
+    <Map name="/lon"/>
+  </Float32>
+  <Enum enum="/e1" name="evar"/>
+
+</Group>
+
+<!-- Test FQN name processing -->
+<Group name="g.@/\$">
+<!-- Provide a dimension with a name that needs escaping 'lon/2.' -->
+<Dimension name="lon/2.&quot;" size="20"/>
+</Group>
+
+<!-- reference the dimension and group with funny names
+     remember to escape dots and forward slashes -->
+<Int32 name="funny">
+  <Dim name="/g\.@\/\\$/lon\/2\.&quot;"/>
+</Int32>
+
+<!-- embedded xml example; dap4.rng needs work
+<OtherXML>
+<anyelement1 name="5">
+<anyelement2>any text</anyelement2>
+</anyelement1>
+</OtherXML>
+-->
+
+
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/testinput/ce1.txt b/dap4/d4tests/src/test/data/resources/TestParsers/testinput/ce1.txt
new file mode 100644
index 0000000000..73b06f4c1f
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/testinput/ce1.txt
@@ -0,0 +1,8 @@
+# Constraint tests for ce1_dmr.txt
+/a[1]
+/b[10:16]
+/c[8:2:15]
+/a[1];/b[10:16];/c[8:2:15]
+/d[1][0:2:2];/a[1];/e[1][0];/f[0][1]
+/s[0:3][0:2].x;/s[0:3][0:2].y
+
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/testinput/ce1_dmr.txt b/dap4/d4tests/src/test/data/resources/TestParsers/testinput/ce1_dmr.txt
new file mode 100644
index 0000000000..e3b4d952be
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/testinput/ce1_dmr.txt
@@ -0,0 +1,39 @@
+<Dataset
+         name="ce_test_dmr"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         ns="http://xml.opendap.org/ns/DAP/4.0#">
+  <Dimension name="d10" size="10"/>
+  <Dimension name="d17" size="17"/>
+  <Int32 name="a">
+    <Dim name="/d17"/>
+  </Int32>
+  <Int32 name="b">
+    <Dim name="/d17"/>
+  </Int32>
+  <Int32 name="c">
+    <Dim name="/d17"/>
+  </Int32>
+  <Int32 name="d">
+    <Dim name="/d10"/>
+    <Dim name="/d17"/>
+  </Int32>
+  <Int32 name="e">
+    <Dim name="/d10"/>
+    <Dim name="/d17"/>
+  </Int32>
+  <Int32 name="f">
+    <Dim name="/d10"/>
+    <Dim name="/d17"/>
+  </Int32>
+  <Structure name="s">
+      <Int32 name="x"/>
+      <Int32 name="y"/>
+    <Dim name="/d10"/>
+    <Dim name="/d10"/>
+  </Structure>
+  <Sequence name="seq">
+      <Int32 name="i32"/>
+      <Int16 name="i16"/>
+  </Sequence>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/testinput/test_misc1.xml b/dap4/d4tests/src/test/data/resources/TestParsers/testinput/test_misc1.xml
new file mode 100644
index 0000000000..16d8b476e3
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/testinput/test_misc1.xml
@@ -0,0 +1,18 @@
+<Dataset name="example"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+        >
+
+<Dimension name="d1" size="10"/>
+
+<Structure name="y">
+  <Opaque name="f1"/>
+  <!--Dim size="*"/-->
+  <Dim name="/d1"/>
+  <Dim size="10"/>
+</Structure>
+
+</Dataset>
+
+
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/testinput/test_misc2.xml b/dap4/d4tests/src/test/data/resources/TestParsers/testinput/test_misc2.xml
new file mode 100644
index 0000000000..e92d76698d
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/testinput/test_misc2.xml
@@ -0,0 +1,37 @@
+<Dataset
+         name="test_atomic_array.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         ns="http://xml.opendap.org/ns/DAP/4.0#">
+    <Byte name="vu8">
+        <Dim name="/d2"/>
+        <Dim name="/d3"/>
+    </Byte>
+    <Int16 name="v16">
+        <Dim name="/d4"/>
+    </Int16>
+    <UInt32 name="vu32">
+        <Dim name="/d2"/>
+        <Dim name="/d3"/>
+    </UInt32>
+    <Float64 name="vd">
+        <Dim name="/d2"/>
+    </Float64>
+    <Char name="vc">
+        <Dim name="/d2"/>
+    </Char>
+    <String name="vs">
+        <Dim name="/d2"/>
+        <Dim name="/d2"/>
+    </String>
+    <Opaque name="vo">
+        <Dim name="/d1"/>
+        <Dim name="/d2"/>
+    </Opaque>
+    <Enum name="primary_cloud" enum="/cloud_class_t">
+        <Dim name="/d5"/>
+        <Attribute name="_FillValue" type="/cloud_class_t">
+          <Value value="Missing"/>
+        </Attribute>
+    </Enum>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/testinput/test_simple_1.xml b/dap4/d4tests/src/test/data/resources/TestParsers/testinput/test_simple_1.xml
new file mode 100644
index 0000000000..985fb24ba0
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/testinput/test_simple_1.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- First in a series of very simple tests. jhrg 7/10/12 -->
+
+<Dataset
+  name="test_dap4_1"
+  dapVersion="4.0"
+  dmrVersion="1.0"
+  xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+  xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+
+  <dap:Int32 name="x"/>
+
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/testinput/test_simple_2.xml b/dap4/d4tests/src/test/data/resources/TestParsers/testinput/test_simple_2.xml
new file mode 100644
index 0000000000..60a1956ff4
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/testinput/test_simple_2.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- First in a series of very simple tests. jhrg 7/10/12 -->
+
+<Dataset
+        name="test_dap4_1"
+        dapVersion="4.0"
+        dmrVersion="1.0"
+        xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+        >
+
+  <Byte name="b"/>
+  
+  <Int8 name="i8"/>
+  <UInt8 name="ui8"/>
+  
+  <Int16 name="i16"/>
+  <UInt16 name="ui16"/>
+  
+  <Int32 name="i32"/>
+  <UInt32 name="ui32"/>
+  
+  <Int64 name="i64"/>
+  <UInt64 name="ui64"/>
+  
+  <Float32 name="f32"/>
+  <Float64 name="f64"/>
+
+  <String name="s"/>
+  <URL name="u"/>
+  
+</Dataset>
+
diff --git a/dap4/d4tests/src/test/data/resources/TestParsers/testinput/testall.xml b/dap4/d4tests/src/test/data/resources/TestParsers/testinput/testall.xml
new file mode 100644
index 0000000000..dfe668a95c
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestParsers/testinput/testall.xml
@@ -0,0 +1,77 @@
+<Dataset name="example"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+        >
+
+<Dimension name="d1" size="10"/>
+<Dimension name="lat" size="20"/>
+<Dimension name="lon" size="20"/>
+
+<Enumeration name="e1" basetype="UInt8">
+  <EnumConst name="econst1" value="1"/>
+  <EnumConst name="econst2" value="2"/>
+</Enumeration>
+
+<Int32 name="x"/>
+<Float32 name="lat">
+  <Dim name="/lat"/>
+</Float32>
+<Float32 name="lon">
+  <Dim name="/lon"/>
+</Float32>
+<Sequence name="y">
+  <Structure name="y">
+    <Opaque name="f1"/>
+    <Attribute name="a1" type="Int32">
+      <Value value="5"/>
+    </Attribute>
+    <Attribute name="a2" type="Float64">
+      <Value value="7.5"/>    
+      <Value>10</Value>
+    </Attribute>  
+    <Attribute name="a3" type="String">
+      <Value>abcd \"hello\" "quoted"</Value>
+    </Attribute>
+    <Dim size="17"/>
+  </Structure>
+  <Dim name="/d1"/>
+  <Dim size="10"/>
+</Sequence>
+  
+<Group name="g1">
+  <Dimension name="d1" size="10"/>
+  <Dimension name="d2" size="20"/>
+
+  <Float32 name="tempb">
+    <Dim name="/lat"/>
+    <Dim name="/lon"/>
+    <Dim name="d2"/>
+    <Map name="/lat"/>
+    <Map name="/lon"/>
+  </Float32>
+  <Enum enum="/e1" name="evar"/>
+
+</Group>
+
+<!-- Test FQN name processing -->
+<Group name="g.@/\$">
+<!-- Provide a dimension with a name that needs escaping "lon/2.\" -->
+<Dimension name="lon/2.\" size="20"/>
+</Group>
+
+<!-- reference the dimension and group with funny names -->
+<Int32 name="funny">
+  <Dim name="/g\.@\/\\$/lon\/2\.\\"/>
+</Int32>
+
+<!-- embedded xml example; dap4.rng needs work
+<OtherXML>
+<anyelement1 name="5">
+<anyelement2>any text</anyelement2>
+</anyelement1>
+</OtherXML>
+-->
+
+
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_aaa.nc.dmp b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_aaa.nc.dmp
new file mode 100644
index 0000000000..54fdf0828f
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_aaa.nc.dmp
@@ -0,0 +1,9 @@
+<Dataset>
+    <Dimension name="d2" size="2"/>
+    <String name="vs">
+        <Dim name="d2"/>
+    </String>
+    <Attribute name="_CoordSysBuilder" type="String" value="ucar.nc2.dataset.conv.DefaultConvention"/>
+</Dataset>
+vs(0) = "Καλημέα" ;
+vs(1) = "abc" ;
diff --git a/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_atomic_array.nc.0.dmp b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_atomic_array.nc.0.dmp
new file mode 100644
index 0000000000..9ee80fe4bb
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_atomic_array.nc.0.dmp
@@ -0,0 +1,24 @@
+<Dataset>
+    <Byte name="vu8">
+        <Dim size="1"/>
+        <Dim size="2"/>
+    </Byte>
+    <Double name="vd">
+        <Dim size="1"/>
+    </Double>
+    <String name="vs">
+        <Dim size="1"/>
+        <Dim size="1"/>
+    </String>
+    <Opaque name="vo">
+        <Dim size="1"/>
+        <Dim size="1"/>
+    </Opaque>
+    <Attribute name="_CoordSysBuilder" type="String" value="ucar.nc2.dataset.conv.DefaultConvention"/>
+</Dataset>
+vu8(0,0) = 3 ;
+vu8(0,1) = 5 ;
+vd(0) = 1024.800000 ;
+vs(0,0) = "
+" ;
+vo(0,0) = 0xABCDEF0000000000 ;
diff --git a/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_atomic_array.nc.1.dmp b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_atomic_array.nc.1.dmp
new file mode 100644
index 0000000000..e076c6ee23
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_atomic_array.nc.1.dmp
@@ -0,0 +1,18 @@
+<Dataset>
+    <Byte name="vu8">
+        <Dim size="1"/>
+        <Dim size="2"/>
+    </Byte>
+    <Double name="vd">
+        <Dim size="1"/>
+    </Double>
+    <String name="vs">
+        <Dim size="1"/>
+        <Dim size="1"/>
+    </String>
+    <Opaque name="vo">
+        <Dim size="1"/>
+        <Dim size="1"/>
+    </Opaque>
+    <Attribute name="_CoordSysBuilder" type="String" value="ucar.nc2.dataset.conv.DefaultConvention"/>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_atomic_array.nc.dmp b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_atomic_array.nc.dmp
new file mode 100644
index 0000000000..bdea13973c
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_atomic_array.nc.dmp
@@ -0,0 +1,83 @@
+<Dataset>
+    <Dimension name="d1" size="1"/>
+    <Dimension name="d2" size="2"/>
+    <Dimension name="d3" size="3"/>
+    <Dimension name="d4" size="4"/>
+    <Dimension name="d5" size="5"/>
+    <Enumeration name="cloud_class_t" basetype="Byte">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Missing" value="127"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+    </Enumeration>
+    <Byte name="vu8">
+        <Dim name="d2"/>
+        <Dim name="d3"/>
+    </Byte>
+    <Short name="v16">
+        <Dim name="d4"/>
+    </Short>
+    <Int name="vu32">
+        <Dim name="d2"/>
+        <Dim name="d3"/>
+    </Int>
+    <Double name="vd">
+        <Dim name="d2"/>
+    </Double>
+    <Char name="vc">
+        <Dim name="d2"/>
+    </Char>
+    <String name="vs">
+        <Dim name="d2"/>
+        <Dim name="d2"/>
+    </String>
+    <Opaque name="vo">
+        <Dim name="d1"/>
+        <Dim name="d2"/>
+    </Opaque>
+    <Byte name="primary_cloud">
+        <Attribute name="_FillValue" type="/cloud_class_t" value="Missing"/>
+        <Dim name="d5"/>
+    </Byte>
+    <Attribute name="_CoordSysBuilder" type="String" value="ucar.nc2.dataset.conv.DefaultConvention"/>
+</Dataset>
+vu8(0,0) = 255 ;
+vu8(0,1) = 1 ;
+vu8(0,2) = 2 ;
+vu8(1,0) = 3 ;
+vu8(1,1) = 4 ;
+vu8(1,2) = 5 ;
+v16(0) = 1 ;
+v16(1) = 2 ;
+v16(2) = 3 ;
+v16(3) = 4 ;
+vu32(0,0) = 5 ;
+vu32(0,1) = 4 ;
+vu32(0,2) = 3 ;
+vu32(1,0) = 2 ;
+vu32(1,1) = 1 ;
+vu32(1,2) = 0 ;
+vd(0) = 17.900000 ;
+vd(1) = 1024.800000 ;
+vc(0) = '@' ;
+vc(1) = '&' ;
+vs(0,0) = "hello	world" ;
+vs(0,1) = "abc" ;
+vs(1,0) = "
+" ;
+vs(1,1) = "Καλημέα" ;
+vo(0,0) = 0x0123456789ABCDEF ;
+vo(0,1) = 0xABCDEF0000000000 ;
+primary_cloud(0) = Clear ;
+primary_cloud(1) = Stratus ;
+primary_cloud(2) = Clear ;
+primary_cloud(3) = Cumulonimbus ;
+primary_cloud(4) = Missing ;
diff --git a/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_atomic_array.nc.ncdump b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_atomic_array.nc.ncdump
new file mode 100644
index 0000000000..b9507deedf
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_atomic_array.nc.ncdump
@@ -0,0 +1,57 @@
+netcdf null {
+  types:
+    enum cloud_class_t { 'Clear' = 0, 'Cumulonimbus' = 1, 'Stratus' = 2, 'Stratocumulus' = 3, 'Cumulus' = 4, 'Altostratus' = 5, 'Nimbostratus' = 6, 'Altocumulus' = 7, 'Missing' = 127, 'Cirrostratus' = 8, 'Cirrocumulus' = 9, 'Cirrus' = 10};
+
+  dimensions:
+    d1 = 1;
+    d2 = 2;
+    d3 = 3;
+    d4 = 4;
+    d5 = 5;
+  variables:
+    byte vu8(d2=2, d3=3);
+      :_Unsigned = "true";
+
+    short v16(d4=4);
+
+    int vu32(d2=2, d3=3);
+      :_Unsigned = "true";
+
+    double vd(d2=2);
+
+    char vc(d2=2);
+
+    String vs(d2=2, d2=2);
+
+    opaque vo(d1=1, d2=2);
+
+    String primary_cloud(d5=5);
+      :_FillValue = "Missing";
+
+  // global attributes:
+  :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+vu8 =
+  {
+    {-1, 1, 2},
+    {3, 4, 5}
+  }
+v16 =
+  {1, 2, 3, 4}
+vu32 =
+  {
+    {5, 4, 3},
+    {2, 1, 0}
+  }
+vd =
+  {17.9, 1024.8}
+vc =  "@&"
+vs =
+  {  "hello	world",   "abc",  "
+",   "Καλημέρα"
+  }
+vo =  0x0123456789abcdef,
+  0xabcdef0000000000,
+
+primary_cloud =  "Clear",   "Clear",   "Clear",   "Clear",   "Clear"
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_atomic_types.nc.dmp b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_atomic_types.nc.dmp
new file mode 100644
index 0000000000..e26e76d516
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_atomic_types.nc.dmp
@@ -0,0 +1,53 @@
+<Dataset>
+    <Enumeration name="cloud_class_t" basetype="Byte">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Missing" value="127"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+    </Enumeration>
+    <Byte name="v8"/>
+    <Byte name="vu8"/>
+    <Short name="v16"/>
+    <Short name="vu16"/>
+    <Int32 name="v32"/>
+    <UInt32 name="vu32"/>
+    </Int>
+    <Long name="v64"/>
+    <Long name="vu64">
+    </Long>
+    <Float name="vf"/>
+    <Double name="vd"/>
+    <Char name="vc"/>
+    <String name="vs"/>
+    <Opaque name="vo"/>
+    <Byte name="primary_cloud">
+        <Attribute name="_FillValue" type="/cloud_class_t" value="Missing"/>
+    </Byte>
+    <Byte name="secondary_cloud">
+        <Attribute name="_FillValue" type="/cloud_class_t" value="Missing"/>
+    </Byte>
+    <Attribute name="_CoordSysBuilder" type="String" value="ucar.nc2.dataset.conv.DefaultConvention"/>
+</Dataset>
+v8 = -128 ;
+vu8 = 255 ;
+v16 = -32768 ;
+vu16 = 65535 ;
+v32 = 2147483647 ;
+vu32 = 4294967295 ;
+v64 = 9223372036854775807 ;
+vu64 = 18446744073709551615 ;
+vf = 3.141593 ;
+vd = 3.141593 ;
+vc = '@' ;
+vs = "hello	world" ;
+vo = 0x0123456789ABCDEF ;
+primary_cloud = Stratus ;
+secondary_cloud = Missing ;
diff --git a/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_atomic_types.nc.ncdump b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_atomic_types.nc.ncdump
new file mode 100644
index 0000000000..62a82936ef
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_atomic_types.nc.ncdump
@@ -0,0 +1,61 @@
+netcdf null {
+  types:
+    enum cloud_class_t { 'Clear' = 0, 'Cumulonimbus' = 1, 'Stratus' = 2, 'Stratocumulus' = 3, 'Cumulus' = 4, 'Altostratus' = 5, 'Nimbostratus' = 6, 'Altocumulus' = 7, 'Missing' = 127, 'Cirrostratus' = 8, 'Cirrocumulus' = 9, 'Cirrus' = 10};
+
+  variables:
+    byte v8;
+
+    byte vu8;
+      :_Unsigned = "true";
+
+    short v16;
+
+    short vu16;
+      :_Unsigned = "true";
+
+    int v32;
+
+    int vu32;
+      :_Unsigned = "true";
+
+    long v64;
+
+    long vu64;
+      :_Unsigned = "true";
+
+    float vf;
+
+    double vd;
+
+    char vc;
+
+    String vs;
+
+    opaque vo;
+
+    String primary_cloud;
+      :_FillValue = "Missing";
+
+    String secondary_cloud;
+      :_FillValue = "Missing";
+
+  // global attributes:
+  :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+v8 =-128
+vu8 =-1
+v16 =-32768
+vu16 =-1
+v32 =2147483647
+vu32 =-1
+v64 =9223372036854775807
+vu64 =-1
+vf =3.1415927
+vd =3.141592653589793
+vc =@
+vs =  "hello	world"
+vo =  0x0123456789abcdef,
+
+primary_cloud =  "Stratus"
+secondary_cloud =  "Unknown enum value=60"
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_enum.nc.dmp b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_enum.nc.dmp
new file mode 100644
index 0000000000..5708512c59
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_enum.nc.dmp
@@ -0,0 +1,21 @@
+<Dataset>
+    <Enumeration name="cloud_class_t" basetype="Byte">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Missing" value="127"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+    </Enumeration>
+    <Byte name="primary_cloud">
+        <Attribute name="_FillValue" type="/cloud_class_t" value="Missing"/>
+    </Byte>
+    <Attribute name="_CoordSysBuilder" type="String" value="ucar.nc2.dataset.conv.DefaultConvention"/>
+</Dataset>
+primary_cloud = Stratus ;
diff --git a/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_enum_array.nc.0.dmp b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_enum_array.nc.0.dmp
new file mode 100644
index 0000000000..c08e20fe0f
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_enum_array.nc.0.dmp
@@ -0,0 +1,27 @@
+<Dataset>
+    <Dimension name="d5" size="5"/>
+    <Enumeration name="cloud_class_t" basetype="Byte">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Missing" value="127"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+    </Enumeration>
+    <Byte name="primary_cloud">
+        <Attribute name="_FillValue" type="/cloud_class_t" value="Missing"/>
+        <Dim name="d5"/>
+    </Byte>
+    <Attribute name="_CoordSysBuilder" type="/cloud_class_t" value="ucar.nc2.dataset.conv.DefaultConvention"/>
+</Dataset>
+primary_cloud(0) = Clear ;
+primary_cloud(1) = Stratus ;
+primary_cloud(2) = Clear ;
+primary_cloud(3) = Cumulonimbus ;
+primary_cloud(4) = Missing ;
diff --git a/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_enum_array.nc.1.dmp b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_enum_array.nc.1.dmp
new file mode 100644
index 0000000000..02fa4ec7e5
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_enum_array.nc.1.dmp
@@ -0,0 +1,23 @@
+<Dataset>
+    <Enumeration name="cloud_class_t" basetype="Byte">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Missing" value="127"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+    </Enumeration>
+    <Byte name="primary_cloud">
+        <Attribute name="_FillValue" type="/cloud_class_t" value="Missing"/>
+        <Dim size="2"/>
+    </Byte>
+    <Attribute name="_CoordSysBuilder" type="/cloud_class_t" value="ucar.nc2.dataset.conv.DefaultConvention"/>
+</Dataset>
+primary_cloud(0) = Stratus ;
+primary_cloud(1) = Cumulonimbus ;
diff --git a/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_enum_array.nc.dmp b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_enum_array.nc.dmp
new file mode 100644
index 0000000000..b82a1e1091
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_enum_array.nc.dmp
@@ -0,0 +1,27 @@
+<Dataset>
+    <Dimension name="d5" size="5"/>
+    <Enumeration name="cloud_class_t" basetype="Byte">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Missing" value="127"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+    </Enumeration>
+    <Byte name="primary_cloud">
+        <Attribute name="_FillValue" type="/cloud_class_t" value="Missing"/>
+        <Dim name="d5"/>
+    </Byte>
+    <Attribute name="_CoordSysBuilder" type="String" value="ucar.nc2.dataset.conv.DefaultConvention"/>
+</Dataset>
+primary_cloud(0) = Clear ;
+primary_cloud(1) = Stratus ;
+primary_cloud(2) = Clear ;
+primary_cloud(3) = Cumulonimbus ;
+primary_cloud(4) = Missing ;
diff --git a/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_groups1.nc.dmp b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_groups1.nc.dmp
new file mode 100644
index 0000000000..2458e100dd
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_groups1.nc.dmp
@@ -0,0 +1,4 @@
+<Dataset>
+    <Dimension name="dim1" size="5"/>
+    <Attribute name="_CoordSysBuilder" type="String" value="ucar.nc2.dataset.conv.DefaultConvention"/>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_groups1.nc.ncdump b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_groups1.nc.ncdump
new file mode 100644
index 0000000000..d0ff04ed22
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_groups1.nc.ncdump
@@ -0,0 +1,7 @@
+netcdf null {
+  dimensions:
+    dim1 = 5;
+  // global attributes:
+  :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_one_var.nc.dmp b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_one_var.nc.dmp
new file mode 100644
index 0000000000..07327c9df8
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_one_var.nc.dmp
@@ -0,0 +1,5 @@
+<Dataset>
+    <Int name="t"/>
+    <Attribute name="_CoordSysBuilder" type="String" value="ucar.nc2.dataset.conv.DefaultConvention"/>
+</Dataset>
+t = 17 ;
diff --git a/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_one_var.nc.ncdump b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_one_var.nc.ncdump
new file mode 100644
index 0000000000..f9b96a90ca
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_one_var.nc.ncdump
@@ -0,0 +1,9 @@
+netcdf null {
+  variables:
+    int t;
+
+  // global attributes:
+  :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+t =17
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_one_vararray.nc.0.dmp b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_one_vararray.nc.0.dmp
new file mode 100644
index 0000000000..b42a52d67e
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_one_vararray.nc.0.dmp
@@ -0,0 +1,9 @@
+<Dataset>
+    <Dimension name="d2" size="2"/>
+    <Int name="t">
+        <Dim name="d2"/>
+    </Int>
+    <Attribute name="_CoordSysBuilder" type="String" value="ucar.nc2.dataset.conv.DefaultConvention"/>
+</Dataset>
+t(0) = 17 ;
+t(1) = 37 ;
diff --git a/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_one_vararray.nc.1.dmp b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_one_vararray.nc.1.dmp
new file mode 100644
index 0000000000..5cd368ebb4
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_one_vararray.nc.1.dmp
@@ -0,0 +1,7 @@
+<Dataset>
+    <Int name="t">
+        <Dim size="1"/>
+    </Int>
+    <Attribute name="_CoordSysBuilder" type="String" value="ucar.nc2.dataset.conv.DefaultConvention"/>
+</Dataset>
+t(0) = 37 ;
diff --git a/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_one_vararray.nc.dmp b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_one_vararray.nc.dmp
new file mode 100644
index 0000000000..b42a52d67e
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_one_vararray.nc.dmp
@@ -0,0 +1,9 @@
+<Dataset>
+    <Dimension name="d2" size="2"/>
+    <Int name="t">
+        <Dim name="d2"/>
+    </Int>
+    <Attribute name="_CoordSysBuilder" type="String" value="ucar.nc2.dataset.conv.DefaultConvention"/>
+</Dataset>
+t(0) = 17 ;
+t(1) = 37 ;
diff --git a/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_struct_array.nc.0.dmp b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_struct_array.nc.0.dmp
new file mode 100644
index 0000000000..d9cf704dcf
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_struct_array.nc.0.dmp
@@ -0,0 +1,25 @@
+<Dataset>
+    <Structure name="s">
+        <Int name="x"/>
+        <Int name="y"/>
+        <Dim size="2"/>
+        <Dim size="2"/>
+    </Structure>
+    <Attribute name="_CoordSysBuilder" type="String" value="ucar.nc2.dataset.conv.DefaultConvention"/>
+</Dataset>
+Struct {
+s.x = 1 ;
+s.y = -1 ;
+} s(0);
+Struct {
+s.x = 17 ;
+s.y = 37 ;
+} s(1);
+Struct {
+s.x = -4 ;
+s.y = 12 ;
+} s(2);
+Struct {
+s.x = -8 ;
+s.y = 8 ;
+} s(3);
diff --git a/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_struct_array.nc.dmp b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_struct_array.nc.dmp
new file mode 100644
index 0000000000..13448edf44
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_struct_array.nc.dmp
@@ -0,0 +1,59 @@
+<Dataset>
+    <Dimension name="dx" size="4"/>
+    <Dimension name="dy" size="3"/>
+    <Structure name="s">
+        <Int name="x"/>
+        <Int name="y"/>
+        <Dim name="dx"/>
+        <Dim name="dy"/>
+    </Structure>
+    <Attribute name="_CoordSysBuilder" type="String" value="ucar.nc2.dataset.conv.DefaultConvention"/>
+</Dataset>
+Struct {
+s.x = 1 ;
+s.y = -1 ;
+} s(0);
+Struct {
+s.x = 17 ;
+s.y = 37 ;
+} s(1);
+Struct {
+s.x = -32767 ;
+s.y = 32767 ;
+} s(2);
+Struct {
+s.x = -1 ;
+s.y = 3 ;
+} s(3);
+Struct {
+s.x = -2 ;
+s.y = 2 ;
+} s(4);
+Struct {
+s.x = -3 ;
+s.y = 1 ;
+} s(5);
+Struct {
+s.x = -4 ;
+s.y = 12 ;
+} s(6);
+Struct {
+s.x = -8 ;
+s.y = 8 ;
+} s(7);
+Struct {
+s.x = -12 ;
+s.y = 4 ;
+} s(8);
+Struct {
+s.x = -5 ;
+s.y = 15 ;
+} s(9);
+Struct {
+s.x = -10 ;
+s.y = 10 ;
+} s(10);
+Struct {
+s.x = -15 ;
+s.y = 5 ;
+} s(11);
diff --git a/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_struct_array.nc.ncdump b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_struct_array.nc.ncdump
new file mode 100644
index 0000000000..296e936377
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_struct_array.nc.ncdump
@@ -0,0 +1,26 @@
+netcdf null {
+  dimensions:
+    dx = 2;
+  variables:
+
+    Structure {
+      int x;
+        :_CoordinateAxisType = "GeoX";
+      int y;
+        :_CoordinateAxisType = "GeoY";
+    } x(dx=2);
+
+
+  // global attributes:
+  :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+x =
+  {
+    x =1
+    y =-2
+  } x(0)
+  {
+    x =17
+    y =37
+  } x(1)
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_struct_nested.hdf5.dmp b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_struct_nested.hdf5.dmp
new file mode 100644
index 0000000000..ab0a96abaa
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_struct_nested.hdf5.dmp
@@ -0,0 +1,23 @@
+<Dataset>
+    <Structure name="x">
+        <Structure name="field1">
+            <Int name="x"/>
+            <Int name="y"/>
+        </Structure>
+        <Structure name="field2">
+            <Int name="x"/>
+            <Int name="y"/>
+        </Structure>
+    </Structure>
+    <Attribute name="_CoordSysBuilder" type="String" value="ucar.nc2.dataset.conv.DefaultConvention"/>
+</Dataset>
+Struct {
+Struct {
+x.field1.x = 1 ;
+x.field1.y = -2 ;
+} x.field1;
+Struct {
+x.field2.x = 255 ;
+x.field2.y = 90 ;
+} x.field2;
+} x;
diff --git a/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_struct_type.nc.dmp b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_struct_type.nc.dmp
new file mode 100644
index 0000000000..9bf70f993e
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_struct_type.nc.dmp
@@ -0,0 +1,11 @@
+<Dataset>
+    <Structure name="s">
+        <Int name="x"/>
+        <Int name="y"/>
+    </Structure>
+    <Attribute name="_CoordSysBuilder" type="String" value="ucar.nc2.dataset.conv.DefaultConvention"/>
+</Dataset>
+Struct {
+s.x = 1 ;
+s.y = -2 ;
+} s;
diff --git a/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_struct_type.nc.ncdump b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_struct_type.nc.ncdump
new file mode 100644
index 0000000000..a7a7e096a9
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_struct_type.nc.ncdump
@@ -0,0 +1,18 @@
+netcdf null {
+  variables:
+
+    Structure {
+      int x;
+        :_CoordinateAxisType = "GeoX";
+      int y;
+        :_CoordinateAxisType = "GeoY";
+    } x;
+
+
+  // global attributes:
+  :_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
+ data:
+x =    x =1
+    y =-2
+
+}
diff --git a/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_utf8.nc.dmp b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_utf8.nc.dmp
new file mode 100644
index 0000000000..54fdf0828f
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_utf8.nc.dmp
@@ -0,0 +1,9 @@
+<Dataset>
+    <Dimension name="d2" size="2"/>
+    <String name="vs">
+        <Dim name="d2"/>
+    </String>
+    <Attribute name="_CoordSysBuilder" type="String" value="ucar.nc2.dataset.conv.DefaultConvention"/>
+</Dataset>
+vs(0) = "Καλημέα" ;
+vs(1) = "abc" ;
diff --git a/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_vlen1.nc.dmp b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_vlen1.nc.dmp
new file mode 100644
index 0000000000..d341f2cefc
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_vlen1.nc.dmp
@@ -0,0 +1,11 @@
+<Dataset>
+    <Int name="x">
+        <Attribute name="_CoordinateAxisType" type="String" value="GeoX"/>
+        <Dim size="*"/>
+    </Int>
+    <Attribute name="_CoordSysBuilder" type="String" value="ucar.nc2.dataset.conv.DefaultConvention"/>
+</Dataset>
+x(0) = 1 ;
+x(1) = 3 ;
+x(2) = 5 ;
+x(3) = 7 ;
diff --git a/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_vlen2.nc.dmp b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_vlen2.nc.dmp
new file mode 100644
index 0000000000..f530233504
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_vlen2.nc.dmp
@@ -0,0 +1,17 @@
+<Dataset>
+    <Dimension name="d3" size="3"/>
+    <Dimension name="d2" size="2"/>
+    <Int name="x">
+        <Attribute name="_CoordinateAxisType" type="String" value="GeoX"/>
+        <Dim name="d3"/>
+        <Dim name="d2"/>
+        <Dim size="*"/>
+    </Int>
+    <Attribute name="_CoordSysBuilder" type="String" value="ucar.nc2.dataset.conv.DefaultConvention"/>
+</Dataset>
+x(0,0) = 1,3,5,7 ;
+x(0,1) = 100,200 ;
+x(1,0) = -1,-2 ;
+x(1,1) = 1,3,5,7 ;
+x(2,0) = 100,200 ;
+x(2,1) = -1,-2 ;
diff --git a/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_vlen3.hdf5.dmp b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_vlen3.hdf5.dmp
new file mode 100644
index 0000000000..1197da6c2f
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_vlen3.hdf5.dmp
@@ -0,0 +1,15 @@
+<Dataset>
+    <Dimension name="d3" size="3"/>
+    <Structure name="v1">
+        <Int name="f1">
+            <Dim size="*"/>
+        </Int>
+    </Structure>
+    <Attribute name="_CoordSysBuilder" type="String" value="ucar.nc2.dataset.conv.DefaultConvention"/>
+</Dataset>
+Struct {
+v1.f1(0) = 1 ;
+v1.f1(1) = 3 ;
+v1.f1(2) = 5 ;
+v1.f1(3) = 7 ;
+} v1;
diff --git a/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_vlen5.hdf5.dmp b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_vlen5.hdf5.dmp
new file mode 100644
index 0000000000..341c6ecfe9
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestSerial/baseline/test_vlen5.hdf5.dmp
@@ -0,0 +1,20 @@
+<Dataset>
+    <Dimension name="d2" size="2"/>
+    <Structure name="v1">
+        <Int name="v">
+            <Dim size="*"/>
+        </Int>
+        <Dim name="d2"/>
+    </Structure>
+    <Attribute name="_CoordSysBuilder" type="String" value="ucar.nc2.dataset.conv.DefaultConvention"/>
+</Dataset>
+Struct {
+v1.v(0) = 1 ;
+v1.v(1) = 3 ;
+v1.v(2) = 5 ;
+v1.v(3) = 7 ;
+} v1(0);
+Struct {
+v1.v(0) = 100 ;
+v1.v(1) = 200 ;
+} v1(1);
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_anon_dim.syn.dap b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_anon_dim.syn.dap
new file mode 100644
index 0000000000..82d8047804
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_anon_dim.syn.dap
@@ -0,0 +1 @@
+ [0] -1169720286 [1] -920699049 [2] -2088732436 [3] 1060190036 [4] -1123468835 [5] 922940053
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_anon_dim.syn.dmr b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_anon_dim.syn.dmr
new file mode 100644
index 0000000000..ea8e789434
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_anon_dim.syn.dmr
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Dataset
+         name="test_anon_dim.syn"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+
+    <Int32 name="vu32">
+        <Dim size="6"/>
+    </Int32>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_atomic_array.nc.dap b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_atomic_array.nc.dap
new file mode 100644
index 0000000000..59a60fbd3b
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_atomic_array.nc.dap
@@ -0,0 +1,8 @@
+ [0] 255 [1] 1 [2] 2 [3] 3 [4] 4 [5] 5
+ [0] 1 [1] 2 [2] 3 [3] 4
+ [0] 5 [1] 4 [2] 3 [3] 2 [4] 1 [5] 0
+ [0] 17.9000 [1] 1024.80
+ [0] '@' [1] '&'
+ [0] "hello\tworld" [1] "\r\n" [2] "Καλημέα" [3] "abc"
+ [0] 0x0123456789ABCDEF [1] 0xABCDEF0000000000
+ [0] 0 [1] 2 [2] 0 [3] 1 [4] 127
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_atomic_array.nc.dmr b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_atomic_array.nc.dmr
new file mode 100644
index 0000000000..99f5f126df
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_atomic_array.nc.dmr
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Dataset
+         name="test_atomic_array.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d1" size="1"/>
+    <Dimension name="d2" size="2"/>
+    <Dimension name="d3" size="3"/>
+    <Dimension name="d4" size="4"/>
+    <Dimension name="d5" size="5"/>
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <UInt8 name="vu8">
+        <Dim name="/d2"/>
+        <Dim name="/d3"/>
+    </UInt8>
+    <Int16 name="v16">
+        <Dim name="/d4"/>
+    </Int16>
+    <UInt32 name="vu32">
+        <Dim name="/d2"/>
+        <Dim name="/d3"/>
+    </UInt32>
+    <Float64 name="vd">
+        <Dim name="/d2"/>
+    </Float64>
+    <Char name="vc">
+        <Dim name="/d2"/>
+    </Char>
+    <String name="vs">
+        <Dim name="/d2"/>
+        <Dim name="/d2"/>
+    </String>
+    <Opaque name="vo">
+        <Dim name="/d1"/>
+        <Dim name="/d2"/>
+    </Opaque>
+    <Enum name="primary_cloud" enum="/cloud_class_t">
+        <Dim name="/d5"/>
+        <Attribute name="_FillValue" type="/cloud_class_t">
+            <Value value="Missing"/>
+        </Attribute>
+    </Enum>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_atomic_array.syn.dap b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_atomic_array.syn.dap
new file mode 100644
index 0000000000..8bc6508fd1
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_atomic_array.syn.dap
@@ -0,0 +1,8 @@
+ [0] 186 [1] 201 [2] 131 [3] 63 [4] 189 [5] 55
+ [0] -341 [1] -21899 [2] -13413 [3] -22144
+ [0] 2367803413 [1] 3586730583 [2] 511843988 [3] 3754752863 [4] 2950934681 [5] 2366232135
+ [0] 0.217870 [1] 0.602451
+ [0] 'C' [1] 'O'
+ [0] "{S" [1] "gb8^OE$" [2] "4a/q%n9;5Y" [3] "{fIl?T\"\\A["
+ [0] 0xA2177AA7287C04FA8BB57BCDF76EC80F [1] 0x34FA472AA9404DD543143CADED303A75
+ [0] 2 [1] 9 [2] 6 [3] 8 [4] 3
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_atomic_array.syn.dmr b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_atomic_array.syn.dmr
new file mode 100644
index 0000000000..366e9cf069
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_atomic_array.syn.dmr
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Dataset
+         name="test_atomic_array.syn"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d1" size="1"/>
+    <Dimension name="d2" size="2"/>
+    <Dimension name="d3" size="3"/>
+    <Dimension name="d4" size="4"/>
+    <Dimension name="d5" size="5"/>
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <UInt8 name="vu8">
+        <Dim name="/d2"/>
+        <Dim name="/d3"/>
+    </UInt8>
+    <Int16 name="v16">
+        <Dim name="/d4"/>
+    </Int16>
+    <UInt32 name="vu32">
+        <Dim name="/d2"/>
+        <Dim name="/d3"/>
+    </UInt32>
+    <Float64 name="vd">
+        <Dim name="/d2"/>
+    </Float64>
+    <Char name="vc">
+        <Dim name="/d2"/>
+    </Char>
+    <String name="vs">
+        <Dim name="/d2"/>
+        <Dim name="/d2"/>
+    </String>
+    <Opaque name="vo">
+        <Dim name="/d1"/>
+        <Dim name="/d2"/>
+    </Opaque>
+    <Enum name="primary_cloud" enum="/cloud_class_t">
+        <Dim name="/d5"/>
+        <Attribute name="_FillValue" type="/cloud_class_t">
+            <Value value="Missing"/>
+        </Attribute>
+    </Enum>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_atomic_types.nc.dap b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_atomic_types.nc.dap
new file mode 100644
index 0000000000..0b6fb8911a
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_atomic_types.nc.dap
@@ -0,0 +1,15 @@
+ -128
+ 255
+ -32768
+ 65535
+ 2147483647
+ 4294967295
+ 9223372036854775807
+ 18446744073709551615
+ 3.14159
+ 3.14159
+ '@'
+ "hello\tworld"
+ 0x0123456789ABCDEF
+ 2
+ 127
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_atomic_types.nc.dmr b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_atomic_types.nc.dmr
new file mode 100644
index 0000000000..92d809af1e
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_atomic_types.nc.dmr
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Dataset
+         name="test_atomic_types.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <Int8 name="v8"/>
+    <UInt8 name="vu8"/>
+    <Int16 name="v16"/>
+    <UInt16 name="vu16"/>
+    <Int32 name="v32"/>
+    <UInt32 name="vu32"/>
+    <Int64 name="v64"/>
+    <UInt64 name="vu64"/>
+    <Float32 name="vf"/>
+    <Float64 name="vd"/>
+    <Char name="vc"/>
+    <String name="vs"/>
+    <Opaque name="vo"/>
+    <Enum name="primary_cloud" enum="/cloud_class_t">
+        <Attribute name="_FillValue" type="/cloud_class_t">
+            <Value value="Missing"/>
+        </Attribute>
+    </Enum>
+    <Enum name="secondary_cloud" enum="/cloud_class_t">
+        <Attribute name="_FillValue" type="/cloud_class_t">
+            <Value value="Missing"/>
+        </Attribute>
+    </Enum>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_atomic_types.syn.dap b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_atomic_types.syn.dap
new file mode 100644
index 0000000000..4fe0dfa020
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_atomic_types.syn.dap
@@ -0,0 +1,15 @@
+ 58
+ 201
+ 896
+ 16177
+ -1123468835
+ 2125143125
+ 3059391736915381031
+ 11577488182652895291
+ 0.551297
+ 0.790267
+ '*'
+ "O,L?c8A%V"
+ 0x46F169EF23CBAF9B1FEBD99E4E16CEC9
+ 7
+ 3
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_atomic_types.syn.dmr b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_atomic_types.syn.dmr
new file mode 100644
index 0000000000..b3362869be
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_atomic_types.syn.dmr
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Dataset
+         name="test_atomic_types.syn"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <Int8 name="v8"/>
+    <UInt8 name="vu8"/>
+    <Int16 name="v16"/>
+    <UInt16 name="vu16"/>
+    <Int32 name="v32"/>
+    <UInt32 name="vu32"/>
+    <Int64 name="v64"/>
+    <UInt64 name="vu64"/>
+    <Float32 name="vf"/>
+    <Float64 name="vd"/>
+    <Char name="vc"/>
+    <String name="vs"/>
+    <Opaque name="vo"/>
+    <Enum name="primary_cloud" enum="/cloud_class_t">
+        <Attribute name="_FillValue" type="/cloud_class_t">
+            <Value value="Missing"/>
+        </Attribute>
+    </Enum>
+    <Enum name="secondary_cloud" enum="/cloud_class_t">
+        <Attribute name="_FillValue" type="/cloud_class_t">
+            <Value value="Missing"/>
+        </Attribute>
+    </Enum>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_enum.nc.dap b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_enum.nc.dap
new file mode 100644
index 0000000000..671900d5f1
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_enum.nc.dap
@@ -0,0 +1 @@
+ 2
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_enum.nc.dmr b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_enum.nc.dmr
new file mode 100644
index 0000000000..b2607d5acd
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_enum.nc.dmr
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Dataset
+         name="test_enum.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <Enum name="primary_cloud" enum="/cloud_class_t">
+        <Attribute name="_FillValue" type="/cloud_class_t">
+            <Value value="Missing"/>
+        </Attribute>
+    </Enum>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_enum_2.nc.dap b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_enum_2.nc.dap
new file mode 100644
index 0000000000..671900d5f1
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_enum_2.nc.dap
@@ -0,0 +1 @@
+ 2
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_enum_2.nc.dmr b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_enum_2.nc.dmr
new file mode 100644
index 0000000000..55a6f3513f
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_enum_2.nc.dmr
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Dataset
+         name="test_enum_2.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <Group name="h">
+        <Enum name="primary_cloud" enum="/cloud_class_t">
+            <Attribute name="_FillValue" type="/cloud_class_t">
+                <Value value="Missing"/>
+            </Attribute>
+        </Enum>
+    </Group>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_enum_array.nc.dap b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_enum_array.nc.dap
new file mode 100644
index 0000000000..d13e008917
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_enum_array.nc.dap
@@ -0,0 +1 @@
+ [0] 0 [1] 2 [2] 0 [3] 1 [4] 127
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_enum_array.nc.dmr b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_enum_array.nc.dmr
new file mode 100644
index 0000000000..666c56d12e
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_enum_array.nc.dmr
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Dataset
+         name="test_enum_array.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d5" size="5"/>
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <Enum name="primary_cloud" enum="/cloud_class_t">
+        <Dim name="/d5"/>
+        <Attribute name="_FillValue" type="/cloud_class_t">
+            <Value value="Missing"/>
+        </Attribute>
+    </Enum>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_fill.nc.dap b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_fill.nc.dap
new file mode 100644
index 0000000000..3bf1930073
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_fill.nc.dap
@@ -0,0 +1,3 @@
+ 240
+ 32700
+ 111000
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_fill.nc.dmr b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_fill.nc.dmr
new file mode 100644
index 0000000000..cf7ba82288
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_fill.nc.dmr
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Dataset
+         name="test_fill.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <UInt8 name="uv8"/>
+    <Int16 name="v16"/>
+    <UInt32 name="uv32">
+        <Attribute name="_FillValue" type="UInt32">
+            <Value value="17"/>
+        </Attribute>
+    </UInt32>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_groups1.nc.dap b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_groups1.nc.dap
new file mode 100644
index 0000000000..0af89ec492
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_groups1.nc.dap
@@ -0,0 +1,4 @@
+ [0] -876354855 [1] -1761252264 [2] 1723477387 [3] -46827465 [4] 1475147969
+ [0] 12.0000 [1] -100.000 [2] 9.96921e+36
+ [0] 2 [1] 3 [2] 5 [3] 7 [4] 11
+ [0] 23.0000 [1] 29.0000 [2] 19.0000 [3] 31.0000 [4] 17.0000 [5] 37.0000 [6] 13.0000
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_groups1.nc.dmr b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_groups1.nc.dmr
new file mode 100644
index 0000000000..745fd108b6
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_groups1.nc.dmr
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Dataset
+         name="test_groups1.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="dim1" size="5"/>
+    <Group name="g">
+        <Dimension name="dim2" size="3"/>
+        <Group name="h">
+            <Dimension name="dim3" size="7"/>
+            <Int32 name="v1">
+                <Dim name="/dim1"/>
+            </Int32>
+            <Float32 name="v2">
+                <Dim name="/g/dim2"/>
+            </Float32>
+        </Group>
+        <Group name="i">
+            <Dimension name="dim3" size="7"/>
+            <Int32 name="v1">
+                <Dim name="/dim1"/>
+            </Int32>
+            <Float32 name="v3">
+                <Dim name="/g/i/dim3"/>
+            </Float32>
+        </Group>
+    </Group>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_one_var.nc.dap b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_one_var.nc.dap
new file mode 100644
index 0000000000..d193859153
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_one_var.nc.dap
@@ -0,0 +1 @@
+ 17
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_one_var.nc.dmr b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_one_var.nc.dmr
new file mode 100644
index 0000000000..a6532d366c
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_one_var.nc.dmr
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Dataset
+         name="test_one_var.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Int32 name="t"/>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_one_vararray.nc.dap b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_one_vararray.nc.dap
new file mode 100644
index 0000000000..cef7e62967
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_one_vararray.nc.dap
@@ -0,0 +1 @@
+ 17 37
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_one_vararray.nc.dmr b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_one_vararray.nc.dmr
new file mode 100644
index 0000000000..b1cf783134
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_one_vararray.nc.dmr
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Dataset
+         name="test_one_vararray.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d2" size="2"/>
+    <Int32 name="t">
+        <Dim name="/d2"/>
+    </Int32>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_opaque.nc.dap b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_opaque.nc.dap
new file mode 100644
index 0000000000..8fc9b352ad
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_opaque.nc.dap
@@ -0,0 +1 @@
+ 0x0123456789ABCDEF
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_opaque.nc.dmr b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_opaque.nc.dmr
new file mode 100644
index 0000000000..ef6174b74d
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_opaque.nc.dmr
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Dataset
+         name="test_opaque.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Opaque name="vo1"/>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_opaque_array.nc.dap b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_opaque_array.nc.dap
new file mode 100644
index 0000000000..41b22527f4
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_opaque_array.nc.dap
@@ -0,0 +1 @@
+ [0] 0x0123456789ABCDEF [1] 0xABCDEF0000000000 [2] 0xFEDCBA9876543210 [3] 0xFEDCBA9999999999
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_opaque_array.nc.dmr b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_opaque_array.nc.dmr
new file mode 100644
index 0000000000..5e66b2c79b
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_opaque_array.nc.dmr
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Dataset
+         name="test_opaque_array.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d2" size="2"/>
+    <Opaque name="vo2">
+        <Dim name="/d2"/>
+        <Dim name="/d2"/>
+    </Opaque>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_sequence_1.syn.dap b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_sequence_1.syn.dap
new file mode 100644
index 0000000000..85131d2746
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_sequence_1.syn.dap
@@ -0,0 +1,2 @@
+count=1
+ -920699049 896
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_sequence_1.syn.dmr b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_sequence_1.syn.dmr
new file mode 100644
index 0000000000..0a36f261eb
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_sequence_1.syn.dmr
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Dataset
+         name="test_sequence_1.syn"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Sequence name="s">
+        <Int32 name="i1"/>
+        <Int16 name="sh1"/>
+    </Sequence>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_sequence_2.syn.dap b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_sequence_2.syn.dap
new file mode 100644
index 0000000000..4fa50da104
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_sequence_2.syn.dap
@@ -0,0 +1,5 @@
+count=1
+ -920699049 896
+count=4
+ -1123468835 -18686 2125143125 -21899 1268468519 -22144 989876086 3361
+
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_sequence_2.syn.dmr b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_sequence_2.syn.dmr
new file mode 100644
index 0000000000..fd2e599638
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_sequence_2.syn.dmr
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Dataset
+         name="test_sequence_2.syn"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+
+    <Sequence name="s">
+        <Int32 name="i1"/>
+        <Int16 name="sh1"/>
+        <Dim size="2"/>
+    </Sequence>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_struct_array.nc.dmr b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_struct_array.nc.dmr
new file mode 100644
index 0000000000..32b27ef436
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_struct_array.nc.dmr
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Dataset
+         name="test_struct_array.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="dx" size="4"/>
+    <Dimension name="dy" size="3"/>
+    <Structure name="s">
+        <Int32 name="x"/>
+        <Int32 name="y"/>
+        <Dim name="/dx"/>
+        <Dim name="/dy"/>
+    </Structure>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_struct_array.syn.dap b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_struct_array.syn.dap
new file mode 100644
index 0000000000..65748cdd85
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_struct_array.syn.dap
@@ -0,0 +1,15 @@
+ [0] 0.727653 [1] 0.785633 [2] 0.513679 [3] 0.246845
+ [0] 0.738422 [1] 0.214889 [2] 0.494798
+ [0] 712320147  1268468519
+ [0] 696298400  989876086
+ [0] -1927163883  -900795134
+ [1] -708236713  1377500019
+ [1] 511843988  1699265896
+ [1] -540214433  -914532520
+ [2] -1344032615  -871416961
+ [2] -1928735161  935744880
+ [2] -1509955773  -1707460853
+ [3] 1145911788  -415231529
+ [3] -278269626  -1682978013
+ [3] -1629885665  -909240754
+
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_struct_array.syn.dmr b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_struct_array.syn.dmr
new file mode 100644
index 0000000000..0856a7e65e
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_struct_array.syn.dmr
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Dataset
+         name="test_struct_array.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="dx" size="4"/>
+    <Dimension name="dy" size="3"/>
+    <Float32 name="z">
+        <Dim name="/dx"/>
+    </Float32>
+    <Float32 name="t">
+        <Dim name="/dy"/>
+    </Float32>
+    <Structure name="s">
+        <Int32 name="x"/>
+        <Int32 name="y"/>
+        <Dim name="/dx"/>
+        <Dim name="/dy"/>
+    </Structure>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_struct_nested.hdf5.dap b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_struct_nested.hdf5.dap
new file mode 100644
index 0000000000..2e043ab8fe
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_struct_nested.hdf5.dap
@@ -0,0 +1 @@
+ 1 -2 255 90
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_struct_nested.hdf5.dmr b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_struct_nested.hdf5.dmr
new file mode 100644
index 0000000000..1f20bbf4ef
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_struct_nested.hdf5.dmr
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Dataset
+         name="test_struct_nested.hdf5"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Structure name="x">
+        <Structure name="field1">
+            <Int32 name="x"/>
+            <Int32 name="y"/>
+        </Structure>
+        <Structure name="field2">
+            <Int32 name="x"/>
+            <Int32 name="y"/>
+        </Structure>
+    </Structure>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_struct_nested3.hdf5.dap b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_struct_nested3.hdf5.dap
new file mode 100644
index 0000000000..d193859153
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_struct_nested3.hdf5.dap
@@ -0,0 +1 @@
+ 17
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_struct_nested3.hdf5.dmr b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_struct_nested3.hdf5.dmr
new file mode 100644
index 0000000000..4105ba1c41
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_struct_nested3.hdf5.dmr
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Dataset
+         name="test_struct_nested3.hdf5"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Structure name="x">
+        <Structure name="field3">
+            <Structure name="field2">
+                <Int32 name="field1"/>
+            </Structure>
+        </Structure>
+    </Structure>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_struct_type.nc.dap b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_struct_type.nc.dap
new file mode 100644
index 0000000000..6e0cb49e1d
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_struct_type.nc.dap
@@ -0,0 +1 @@
+ 1 -2
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_struct_type.nc.dmr b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_struct_type.nc.dmr
new file mode 100644
index 0000000000..85155f3742
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_struct_type.nc.dmr
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Dataset
+         name="test_struct_type.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Structure name="s">
+        <Int32 name="x"/>
+        <Int32 name="y"/>
+    </Structure>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_utf8.nc.dap b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_utf8.nc.dap
new file mode 100644
index 0000000000..68b34c93ad
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_utf8.nc.dap
@@ -0,0 +1,3 @@
+ [0] "Καλημέα"
+ [1] "abc"
+
diff --git a/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_utf8.nc.dmr b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_utf8.nc.dmr
new file mode 100644
index 0000000000..7be161da9f
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServlet/baseline/test_utf8.nc.dmr
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Dataset
+         name="test_utf8.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d2" size="2"/>
+    <String name="vs">
+        <Dim name="/d2"/>
+    </String>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_anon_dim.syn.2.dap b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_anon_dim.syn.2.dap
new file mode 100644
index 0000000000..a69de268a4
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_anon_dim.syn.2.dap
@@ -0,0 +1 @@
+ 3125247010 3374268247 2206234860 1060190036
diff --git a/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_anon_dim.syn.2.dmr b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_anon_dim.syn.2.dmr
new file mode 100644
index 0000000000..34bdcff0d0
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_anon_dim.syn.2.dmr
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Dataset
+         name="test_anon_dim.syn"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Int32 name="vu32">
+        <Dim size="4"/>
+    </Int32>
+    <Attribute name="_dap4.ce" type="String">
+        <Value value="/vu32[0:3]"/>
+    </Attribute>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_atomic_array.nc.5.dap b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_atomic_array.nc.5.dap
new file mode 100644
index 0000000000..7420b43453
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_atomic_array.nc.5.dap
@@ -0,0 +1,4 @@
+ [0] 3 [1] 5
+ [0] 1024.80
+ [0] "Καλημέα"
+ [0] 0xABCDEF0000000000
diff --git a/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_atomic_array.nc.5.dmr b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_atomic_array.nc.5.dmr
new file mode 100644
index 0000000000..ec3348668e
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_atomic_array.nc.5.dmr
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Dataset
+         name="test_atomic_array.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <UInt8 name="vu8">
+        <Dim size="1"/>
+        <Dim size="2"/>
+    </UInt8>
+    <Float64 name="vd">
+        <Dim size="1"/>
+    </Float64>
+    <String name="vs">
+        <Dim size="1"/>
+        <Dim size="1"/>
+    </String>
+    <Opaque name="vo">
+        <Dim size="1"/>
+        <Dim size="1"/>
+    </Opaque>
+    <Attribute name="_dap4.ce" type="String">
+        <Value value="/vu8[1][0:2:2];/vd[1];/vs[1][0];/vo[0][1]"/>
+    </Attribute>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_atomic_array.nc.8.dap b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_atomic_array.nc.8.dap
new file mode 100644
index 0000000000..9c060c2015
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_atomic_array.nc.8.dap
@@ -0,0 +1 @@
+ [0] 1 [1] 2 [2] 4
diff --git a/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_atomic_array.nc.8.dmr b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_atomic_array.nc.8.dmr
new file mode 100644
index 0000000000..475ddd2883
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_atomic_array.nc.8.dmr
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Dataset
+         name="test_atomic_array.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Int16 name="v16">
+        <Dim size="3"/>
+    </Int16>
+    <Attribute name="_dap4.ce" type="String">
+        <Value value="/v16[0:1,3]"/>
+    </Attribute>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_atomic_array.nc.9.dap b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_atomic_array.nc.9.dap
new file mode 100644
index 0000000000..b7fc1fa5bd
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_atomic_array.nc.9.dap
@@ -0,0 +1 @@
+ [0] 4 [1] 1 [2] 2
diff --git a/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_atomic_array.nc.9.dmr b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_atomic_array.nc.9.dmr
new file mode 100644
index 0000000000..bc98546100
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_atomic_array.nc.9.dmr
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Dataset
+         name="test_atomic_array.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Int16 name="v16">
+        <Dim size="3"/>
+    </Int16>
+    <Attribute name="_dap4.ce" type="String">
+        <Value value="/v16[3,0:1]"/>
+    </Attribute>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_enum_array.nc.4.dap b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_enum_array.nc.4.dap
new file mode 100644
index 0000000000..8277a7de56
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_enum_array.nc.4.dap
@@ -0,0 +1 @@
+ [0] 2 [1] 1
diff --git a/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_enum_array.nc.4.dmr b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_enum_array.nc.4.dmr
new file mode 100644
index 0000000000..03b0e02237
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_enum_array.nc.4.dmr
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Dataset
+         name="test_enum_array.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <Enum name="primary_cloud" enum="/cloud_class_t">
+        <Dim size="2"/>
+        <Attribute name="_FillValue" type="/cloud_class_t">
+            <Value value="Missing"/>
+        </Attribute>
+    </Enum>
+    <Attribute name="_dap4.ce" type="String">
+        <Value value="/primary_cloud[1:2:4]"/>
+    </Attribute>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_one_vararray.nc.1.dap b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_one_vararray.nc.1.dap
new file mode 100644
index 0000000000..e9082c0001
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_one_vararray.nc.1.dap
@@ -0,0 +1 @@
+ 37
diff --git a/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_one_vararray.nc.1.dmr b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_one_vararray.nc.1.dmr
new file mode 100644
index 0000000000..4ca652721c
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_one_vararray.nc.1.dmr
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Dataset
+         name="test_one_vararray.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Int32 name="t">
+        <Dim size="1"/>
+    </Int32>
+    <Attribute name="_dap4.ce" type="String">
+        <Value value="/t[1]"/>
+    </Attribute>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_one_vararray.nc.3.dap b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_one_vararray.nc.3.dap
new file mode 100644
index 0000000000..cef7e62967
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_one_vararray.nc.3.dap
@@ -0,0 +1 @@
+ 17 37
diff --git a/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_one_vararray.nc.3.dmr b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_one_vararray.nc.3.dmr
new file mode 100644
index 0000000000..f715bea4e2
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_one_vararray.nc.3.dmr
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Dataset
+         name="test_one_vararray.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d2" size="2"/>
+    <Int32 name="t">
+        <Dim name="/d2"/>
+    </Int32>
+    <Attribute name="_dap4.ce" type="String">
+        <Value value="/t[0:1]"/>
+    </Attribute>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_opaque_array.nc.7.dap b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_opaque_array.nc.7.dap
new file mode 100644
index 0000000000..2c0819195e
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_opaque_array.nc.7.dap
@@ -0,0 +1 @@
+ [0] 0xFEDCBA9876543210 [1] 0xFEDCBA9999999999
diff --git a/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_opaque_array.nc.7.dmr b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_opaque_array.nc.7.dmr
new file mode 100644
index 0000000000..b74aafe1b4
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_opaque_array.nc.7.dmr
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Dataset
+         name="test_opaque_array.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Opaque name="vo2">
+        <Dim size="1"/>
+        <Dim size="2"/>
+    </Opaque>
+    <Attribute name="_dap4.ce" type="String">
+        <Value value="/vo2[1][0:1]"/>
+    </Attribute>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_struct_array.nc.6.dap b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_struct_array.nc.6.dap
new file mode 100644
index 0000000000..af7758ecde
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_struct_array.nc.6.dap
@@ -0,0 +1 @@
+ 1 -1 17 37 -4 12 -8 8
diff --git a/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_struct_array.nc.6.dmr b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_struct_array.nc.6.dmr
new file mode 100644
index 0000000000..ecff7d7ad5
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/TestServletConstraints/baseline/test_struct_array.nc.6.dmr
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Dataset
+         name="test_struct_array.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Structure name="s">
+        <Int32 name="x"/>
+        <Int32 name="y"/>
+        <Dim size="2"/>
+        <Dim size="2"/>
+    </Structure>
+    <Attribute name="_dap4.ce" type="String">
+        <Value value="/s[0:2:3][0:1]"/>
+    </Attribute>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/favicon.ico b/dap4/d4tests/src/test/data/resources/favicon.ico
new file mode 100644
index 0000000000..d63ed90888
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/favicon.ico differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/Makefile b/dap4/d4tests/src/test/data/resources/testfiles/Makefile
new file mode 100644
index 0000000000..fda8984011
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/Makefile
@@ -0,0 +1,75 @@
+NC=\
+test_one_var \
+test_one_vararray \
+test_atomic_types \
+test_atomic_array \
+test_enum \
+test_enum_2 \
+test_enum_array \
+test_groups1 \
+test_struct_type \
+test_struct_array \
+test_misc1 \
+test_vlen1 \
+test_vlen2 \
+test_opaque \
+test_opaque_array \
+test_fill \
+test_utf8
+
+HDF5=\
+test_struct_nested \
+test_struct_nested3 \
+test_vlen3 \
+test_vlen4 \
+test_vlen5
+
+C=tst_fills tst_h5fill
+
+BUGS=
+
+all:: all2 all3
+
+all1:
+	for x in ${C} ; do \
+	    gcc -g -O0 -o $$x.exe $$x.c -L/usr/local/lib -lnetcdf -lcurl -lhdf5 -lhdf5_hl ; \
+	    ./$$x ; \
+	done
+
+all2:
+	for x in ${NC} ${HDF5} ; do ncgen -k3 $${x}.cdl ; done
+
+all3:
+	for x in ${HDF5} ; do cp $${x}.nc $${x}.hdf5 ; done 
+
+clean::
+	rm -f *.nc; rm -f *.hdf5; rm -f *.h5
+	for x in ${C} ; do rm -f $$x.exe ; done
+	rm -fr dump
+	
+
+verify:
+	rm -fr dump
+	mkdir dump
+	for x in ${NC} ; do ncdump $${x}.nc > dump/$${x}.cdl ; done
+	for x in ${HDF5} ; do ncdump $${x}.hdf5 > dump/$${x}.cdl ; done
+	for x in ${NC} ${HDF5} ; do \
+	echo $${x}.cdl ; \
+	diff -wBb $${x}.cdl dump/$${x}.cdl ; \
+	done
+
+UI=f:/git/thredds/ui/target/toolsUI-4.4.0-SNAPSHOT.jar
+F=test_test
+
+# note -vall fails
+x::
+	rm -f ${F}.hdf5 ${F}.nc
+	ncgen -k3 -o ${F}.nc ${F}.cdl
+	cp ${F}.nc ${F}.hdf5
+	java -cp ${UI} ucar.nc2.NCdumpW ${F}.hdf5
+
+#	ncdump ${F}.hdf5
+
+t::
+	ncgen -k3 -o ${F}.nc ${F}.cdl
+	ncdump ${F}.nc
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_aaa.nc.dmr b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_aaa.nc.dmr
new file mode 100644
index 0000000000..a8d498be14
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_aaa.nc.dmr
@@ -0,0 +1,11 @@
+<Dataset
+         name="test_aaa.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d2" size="2"/>
+    <String name="vs">
+        <Dim name="/d2"/>
+    </String>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_atomic_array.nc.dmr b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_atomic_array.nc.dmr
new file mode 100644
index 0000000000..9e0dd4e355
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_atomic_array.nc.dmr
@@ -0,0 +1,55 @@
+<Dataset
+         name="test_atomic_array.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <Dimension name="d1" size="1"/>
+    <Dimension name="d2" size="2"/>
+    <Dimension name="d3" size="3"/>
+    <Dimension name="d4" size="4"/>
+    <Dimension name="d5" size="5"/>
+    <UInt8 name="vu8">
+        <Dim name="/d2"/>
+        <Dim name="/d3"/>
+    </UInt8>
+    <Int16 name="v16">
+        <Dim name="/d4"/>
+    </Int16>
+    <UInt32 name="vu32">
+        <Dim name="/d2"/>
+        <Dim name="/d3"/>
+    </UInt32>
+    <Float64 name="vd">
+        <Dim name="/d2"/>
+    </Float64>
+    <Char name="vc">
+        <Dim name="/d2"/>
+    </Char>
+    <String name="vs">
+        <Dim name="/d2"/>
+        <Dim name="/d2"/>
+    </String>
+    <Opaque name="vo">
+        <Dim name="/d1"/>
+        <Dim name="/d2"/>
+    </Opaque>
+    <Enum name="primary_cloud" enum="/cloud_class_t">
+        <Dim name="/d5"/>
+        <Attribute name="_FillValue" type="String" value="Missing"/>
+    </Enum>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_atomic_types.nc.dmr b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_atomic_types.nc.dmr
new file mode 100644
index 0000000000..88340335c2
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_atomic_types.nc.dmr
@@ -0,0 +1,44 @@
+<Dataset
+         name="test_atomic_types.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <Int8 name="v8"/>
+    <Byte name="vu8">
+    </Byte>
+    <Int16 name="v16"/>
+    <UInt16 name="vu16">
+    </UInt16>
+    <Int32 name="v32"/>
+    <UInt32 name="vu32">
+    </UInt32>
+    <Int64 name="v64"/>
+    <UInt64 name="vu64">
+    </UInt64>
+    <Float32 name="vf"/>
+    <Float64 name="vd"/>
+    <Char name="vc"/>
+    <String name="vs"/>
+    <Opaque name="vo"/>
+    <Enum name="primary_cloud" enum="/cloud_class_t">
+        <Attribute name="_FillValue" type="String" value="Missing"/>
+    </Enum>
+    <Enum name="secondary_cloud" enum="/cloud_class_t">
+        <Attribute name="_FillValue" type="String" value="Missing"/>
+    </Enum>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_enum.nc.dmr b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_enum.nc.dmr
new file mode 100644
index 0000000000..7126f07378
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_enum.nc.dmr
@@ -0,0 +1,24 @@
+<Dataset
+         name="test_enum.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <Enum name="primary_cloud" enum="/cloud_class_t">
+        <Attribute name="_FillValue" type="String" value="Missing"/>
+    </Enum>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_enum1.nc.dmr b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_enum1.nc.dmr
new file mode 100644
index 0000000000..dca662dfc9
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_enum1.nc.dmr
@@ -0,0 +1,27 @@
+<Dataset
+         name="test_enum1.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <Enum name="primary_cloud" enum="/cloud_class_t">
+        <Attribute name="_FillValue" type="String" value="Missing"/>
+    </Enum>
+    <Enum name="secondary_cloud" enum="/cloud_class_t">
+        <Attribute name="_FillValue" type="String" value="Missing"/>
+    </Enum>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_enum2.nc.dmr b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_enum2.nc.dmr
new file mode 100644
index 0000000000..6cfd3fa18c
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_enum2.nc.dmr
@@ -0,0 +1,26 @@
+<Dataset
+         name="test_enum2.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="station" size="5"/>
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <Enum name="primary_cloud" enum="/cloud_class_t">
+        <Dim name="/station"/>
+        <Attribute name="_FillValue" type="String" value="Missing"/>
+    </Enum>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_enum_array.nc.dmr b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_enum_array.nc.dmr
new file mode 100644
index 0000000000..dd8b966f98
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_enum_array.nc.dmr
@@ -0,0 +1,26 @@
+<Dataset
+         name="test_enum_array.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <Dimension name="d5" size="5"/>
+    <Enum name="primary_cloud" enum="/cloud_class_t">
+        <Dim name="/d5"/>
+        <Attribute name="_FillValue" type="String" value="Missing"/>
+    </Enum>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_groups1.nc.dmr b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_groups1.nc.dmr
new file mode 100644
index 0000000000..80f918edc6
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_groups1.nc.dmr
@@ -0,0 +1,29 @@
+<Dataset
+         name="test_groups1.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="dim1" size="5"/>
+    <Group name="g">
+        <Dimension name="dim2" size="3"/>
+        <Group name="h">
+            <Dimension name="dim3" size="7"/>
+            <Int32 name="v1">
+                <Dim name="/dim1"/>
+            </Int32>
+            <Float32 name="v2">
+                <Dim name="/g/dim2"/>
+            </Float32>
+        </Group>
+        <Group name="i">
+            <Dimension name="dim3" size="7"/>
+            <Int32 name="v1">
+                <Dim name="/dim1"/>
+            </Int32>
+            <Float32 name="v3">
+                <Dim name="/g/i/dim3"/>
+            </Float32>
+        </Group>
+    </Group>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_numeric_types.nc.dmr b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_numeric_types.nc.dmr
new file mode 100644
index 0000000000..57cb8ca453
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_numeric_types.nc.dmr
@@ -0,0 +1,22 @@
+<Dataset
+         name="test_numeric_types.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Int8 name="v8"/>
+    <Byte name="vu8">
+    </Byte>
+    <Int16 name="v16"/>
+    <UInt16 name="vu16">
+    </UInt16>
+    <Int32 name="v32"/>
+    <UInt32 name="vu32">
+    </UInt32>
+    <Int64 name="v64"/>
+    <Float32 name="vf"/>
+    <Float64 name="vd"/>
+    <UInt64 name="vu64">
+    </UInt64>
+    <Char name="vc"/>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_one_var.nc.dmr b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_one_var.nc.dmr
new file mode 100644
index 0000000000..89016b1816
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_one_var.nc.dmr
@@ -0,0 +1,8 @@
+<Dataset
+         name="test_one_var.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Int32 name="t"/>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_one_vararray.nc.dmr b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_one_vararray.nc.dmr
new file mode 100644
index 0000000000..8f199d1cb1
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_one_vararray.nc.dmr
@@ -0,0 +1,11 @@
+<Dataset
+         name="test_one_vararray.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d2" size="2"/>
+    <Int32 name="t">
+        <Dim name="/d2"/>
+    </Int32>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_opaque_type.nc.dmr b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_opaque_type.nc.dmr
new file mode 100644
index 0000000000..298d5f9c8e
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_opaque_type.nc.dmr
@@ -0,0 +1,8 @@
+<Dataset
+         name="test_opaque_type.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Opaque name="vo"/>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_string_type.nc.dmr b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_string_type.nc.dmr
new file mode 100644
index 0000000000..4b7615450f
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_string_type.nc.dmr
@@ -0,0 +1,8 @@
+<Dataset
+         name="test_string_type.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <String name="vs"/>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_struct1.nc.dmr b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_struct1.nc.dmr
new file mode 100644
index 0000000000..9612148ceb
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_struct1.nc.dmr
@@ -0,0 +1,11 @@
+<Dataset
+         name="test_struct1.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Structure name="x">
+        <Int32 name="x"/>
+        <Int32 name="y"/>
+    </Structure>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_struct_array.nc.dmr b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_struct_array.nc.dmr
new file mode 100644
index 0000000000..8dabe14882
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_struct_array.nc.dmr
@@ -0,0 +1,15 @@
+<Dataset
+         name="test_struct_array.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="dx" size="4"/>
+    <Dimension name="dy" size="3"/>
+    <Structure name="s">
+        <Int32 name="x"/>
+        <Int32 name="y"/>
+        <Dim name="/dx"/>
+        <Dim name="/dy"/>
+    </Structure>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_struct_nested.hdf5.dmr b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_struct_nested.hdf5.dmr
new file mode 100644
index 0000000000..376824981e
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_struct_nested.hdf5.dmr
@@ -0,0 +1,17 @@
+<Dataset
+         name="test_struct_nested.hdf5"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Structure name="x">
+        <Structure name="field1">
+            <Int32 name="x"/>
+            <Int32 name="y"/>
+        </Structure>
+        <Structure name="field2">
+            <Int32 name="x"/>
+            <Int32 name="y"/>
+        </Structure>
+    </Structure>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_struct_nested.nc.dmr b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_struct_nested.nc.dmr
new file mode 100644
index 0000000000..f42d82a6ba
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_struct_nested.nc.dmr
@@ -0,0 +1,17 @@
+<Dataset
+         name="test_struct_nested.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Structure name="x">
+        <Structure name="field1">
+            <Int32 name="x"/>
+            <Int32 name="y"/>
+        </Structure>
+        <Structure name="field2">
+            <Int32 name="x"/>
+            <Int32 name="y"/>
+        </Structure>
+    </Structure>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_struct_type.nc.dmr b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_struct_type.nc.dmr
new file mode 100644
index 0000000000..4e2adb0c1d
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_struct_type.nc.dmr
@@ -0,0 +1,11 @@
+<Dataset
+         name="test_struct_type.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Structure name="s">
+        <Int32 name="x"/>
+        <Int32 name="y"/>
+    </Structure>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_utf8.nc.dmr b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_utf8.nc.dmr
new file mode 100644
index 0000000000..74115be967
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_utf8.nc.dmr
@@ -0,0 +1,11 @@
+<Dataset
+         name="test_utf8.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d2" size="2"/>
+    <String name="vs">
+        <Dim name="/d2"/>
+    </String>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_vlen1.nc.dmr b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_vlen1.nc.dmr
new file mode 100644
index 0000000000..b8086d06d1
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_vlen1.nc.dmr
@@ -0,0 +1,11 @@
+<Dataset
+         name="test_vlen1.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+
+    <Int32 name="x">
+        <Dim size="*"/>
+    </Int32>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_vlen2.nc.dmr b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_vlen2.nc.dmr
new file mode 100644
index 0000000000..f5ebdb60b9
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_vlen2.nc.dmr
@@ -0,0 +1,15 @@
+<Dataset
+         name="test_vlen2.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d3" size="3"/>
+    <Dimension name="d2" size="2"/>
+
+    <Int32 name="x">
+        <Dim name="/d3"/>
+        <Dim name="/d2"/>
+        <Dim size="*"/>
+    </Int32>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_vlen3.hdf5.dmr b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_vlen3.hdf5.dmr
new file mode 100644
index 0000000000..13041f5136
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_vlen3.hdf5.dmr
@@ -0,0 +1,14 @@
+<Dataset
+         name="test_vlen3.hdf5"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d3" size="3"/>
+
+    <Structure name="v1">
+        <Int32 name="f1">
+            <Dim size="*"/>
+        </Int32>
+    </Structure>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_vlen3.nc.dmr b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_vlen3.nc.dmr
new file mode 100644
index 0000000000..b8729a4e15
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_vlen3.nc.dmr
@@ -0,0 +1,8 @@
+    <Dimension name="d3" size="3"/>
+
+    <Structure name="v1">
+        <Int32 name="v">
+            <Dim size="*"/>
+        </Int32>
+    </Structure>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_vlen4.hdf5.dmr b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_vlen4.hdf5.dmr
new file mode 100644
index 0000000000..09398765d6
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_vlen4.hdf5.dmr
@@ -0,0 +1,14 @@
+<Dataset
+         name="test_vlen4.hdf5"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d2" size="2"/>
+
+    <Structure name="v1">
+        <Int32 name="f1">
+            <Dim size="2"/>
+        </Int32>
+    </Structure>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_vlen5.hdf5.dmr b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_vlen5.hdf5.dmr
new file mode 100644
index 0000000000..2cd00c88d1
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/dmr/test_vlen5.hdf5.dmr
@@ -0,0 +1,15 @@
+<Dataset
+         name="test_vlen5.hdf5"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="d2" size="2"/>
+
+    <Structure name="v1">
+        <Int32 name="v">
+            <Dim size="*"/>
+        </Int32>
+        <Dim name="/d2"/>
+    </Structure>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/doit b/dap4/d4tests/src/test/data/resources/testfiles/doit
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_anon_dim.syn b/dap4/d4tests/src/test/data/resources/testfiles/test_anon_dim.syn
new file mode 100644
index 0000000000..221f7ac725
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_anon_dim.syn
@@ -0,0 +1,11 @@
+<Dataset
+         name="test_anon_dim.syn"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Int32 name="vu32">
+        <Dim size="6"/>
+    </Int32>
+</Dataset>
+
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_atomic_array.cdl b/dap4/d4tests/src/test/data/resources/testfiles/test_atomic_array.cdl
new file mode 100644
index 0000000000..ea901a8db6
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_atomic_array.cdl
@@ -0,0 +1,39 @@
+netcdf test_atomic_array {
+types:
+  opaque(8) o_t;  
+  byte enum cloud_class_t {Clear = 0, Cumulonimbus = 1, Stratus = 2, 
+      Stratocumulus = 3, Cumulus = 4, Altostratus = 5, Nimbostratus = 6, 
+      Altocumulus = 7, Cirrostratus = 8, Cirrocumulus = 9, Cirrus = 10, 
+      Missing = 127} ;
+dimensions:
+  d1 = 1;
+  d2 = 2;
+  d3 = 3;
+  d4 = 4;
+  d5 = 5;
+variables:
+  ubyte vu8(d2,d3);
+  short v16(d4);
+  uint vu32(d2,d3);
+  double vd(d2);
+  char vc(d2);
+  string vs(d2,d2);
+  o_t vo(d1,d2);
+  cloud_class_t primary_cloud(d5) ;
+      cloud_class_t primary_cloud:_FillValue = Missing ;
+
+data:
+ vu8 =
+  255, 1, 2,
+  3, 4, 5 ;
+ v16 = 1, 2, 3, 4 ;
+ vu32 =
+  5, 4, 3,
+  2, 1, 0 ;
+ vd = 17.9, 1024.8 ;
+ vc = '@', '&' ;
+ vs = "hello\tworld", "\r\n", "Καλημέα", "abc" ;
+ vo =
+  0X0123456789ABCDEF, 0XABCDEF0000000000 ;
+ primary_cloud = Clear, Stratus, Clear, Cumulonimbus, _ ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_atomic_array.nc b/dap4/d4tests/src/test/data/resources/testfiles/test_atomic_array.nc
new file mode 100644
index 0000000000..26cb578f8a
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_atomic_array.nc differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_atomic_array.ncdump b/dap4/d4tests/src/test/data/resources/testfiles/test_atomic_array.ncdump
new file mode 100644
index 0000000000..2a9d0f1966
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_atomic_array.ncdump
@@ -0,0 +1,48 @@
+netcdf test_atomic_array {
+types:
+  opaque(8) o_t ;
+  byte enum cloud_class_t {Clear = 0, Cumulonimbus = 1, Stratus = 2, 
+      Stratocumulus = 3, Cumulus = 4, Altostratus = 5, Nimbostratus = 6, 
+      Altocumulus = 7, Cirrostratus = 8, Cirrocumulus = 9, Cirrus = 10, 
+      Missing = 127} ;
+dimensions:
+	d1 = 1 ;
+	d2 = 2 ;
+	d3 = 3 ;
+	d4 = 4 ;
+	d5 = 5 ;
+variables:
+	ubyte vu8(d2, d3) ;
+	short v16(d4) ;
+	uint vu32(d2, d3) ;
+	double vd(d2) ;
+	char vc(d2) ;
+	string vs(d2, d2) ;
+	o_t vo(d1, d2) ;
+	cloud_class_t primary_cloud(d5) ;
+		cloud_class_t primary_cloud:_FillValue = Missing ;
+data:
+
+ vu8 =
+  255, 1, 2,
+  3, 4, 5 ;
+
+ v16 = 1, 2, 3, 4 ;
+
+ vu32 =
+  5, 4, 3,
+  2, 1, 0 ;
+
+ vd = 17.9, 1024.8 ;
+
+ vc = "@&" ;
+
+ vs =
+  "hello\tworld", "\r\n",
+  "Καλημέα", "abc" ;
+
+ vo =
+  0X0123456789ABCDEF, 0XABCDEF0000000000 ;
+
+ primary_cloud = Clear, Stratus, Clear, Cumulonimbus, _ ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_atomic_array.syn b/dap4/d4tests/src/test/data/resources/testfiles/test_atomic_array.syn
new file mode 100644
index 0000000000..86d46ceb7d
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_atomic_array.syn
@@ -0,0 +1,55 @@
+<Dataset
+         name="test_atomic_array.syn"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <Dimension name="d1" size="1"/>
+    <Dimension name="d2" size="2"/>
+    <Dimension name="d3" size="3"/>
+    <Dimension name="d4" size="4"/>
+    <Dimension name="d5" size="5"/>
+    <UInt8 name="vu8">
+        <Dim name="/d2"/>
+        <Dim name="/d3"/>
+    </UInt8>
+    <Int16 name="v16">
+        <Dim name="/d4"/>
+    </Int16>
+    <UInt32 name="vu32">
+        <Dim name="/d2"/>
+        <Dim name="/d3"/>
+    </UInt32>
+    <Float64 name="vd">
+        <Dim name="/d2"/>
+    </Float64>
+    <Char name="vc">
+        <Dim name="/d2"/>
+    </Char>
+    <String name="vs">
+        <Dim name="/d2"/>
+        <Dim name="/d2"/>
+    </String>
+    <Opaque name="vo">
+        <Dim name="/d1"/>
+        <Dim name="/d2"/>
+    </Opaque>
+    <Enum name="primary_cloud" enum="/cloud_class_t">
+        <Dim name="/d5"/>
+        <Attribute name="_FillValue" type="/cloud_class_t"><Value value="Missing"/></Attribute>
+    </Enum>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_atomic_types.cdl b/dap4/d4tests/src/test/data/resources/testfiles/test_atomic_types.cdl
new file mode 100644
index 0000000000..d43301a201
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_atomic_types.cdl
@@ -0,0 +1,42 @@
+netcdf test_atomic_types {
+types:
+  opaque(8) o_t;  
+  byte enum cloud_class_t {Clear = 0, Cumulonimbus = 1, Stratus = 2, 
+      Stratocumulus = 3, Cumulus = 4, Altostratus = 5, Nimbostratus = 6, 
+      Altocumulus = 7, Cirrostratus = 8, Cirrocumulus = 9, Cirrus = 10, 
+      Missing = 127} ;
+variables:
+  byte v8;
+  ubyte vu8;
+  short v16;
+  ushort vu16;
+  int v32;
+  uint vu32;
+  int64 v64;
+  uint64 vu64;
+  float vf; 
+  double vd; 
+  char vc;
+  string vs;
+  o_t vo;
+  cloud_class_t primary_cloud;
+    cloud_class_t primary_cloud:_FillValue = Missing ;
+  cloud_class_t secondary_cloud;
+    cloud_class_t secondary_cloud:_FillValue = Missing ;
+data:
+  v8 = -128;
+  vu8 = 255;
+  v16 = -32768;
+  vu16 = 65535;
+  v32 = 2147483647;
+  vu32 = 4294967295;
+  v64 = 9223372036854775807;
+  vu64 = 18446744073709551615;
+  vf = 3.1415926535897932384626433832795;
+  vd = 3.141592653589793238462643383279502884197169399375105820974944592;
+  vc = '@';
+  vs = "hello\tworld";
+  vo = 0x0123456789abcdef;
+  primary_cloud = Stratus;
+  secondary_cloud = _;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_atomic_types.nc b/dap4/d4tests/src/test/data/resources/testfiles/test_atomic_types.nc
new file mode 100644
index 0000000000..066dd89354
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_atomic_types.nc differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_atomic_types.ncdump b/dap4/d4tests/src/test/data/resources/testfiles/test_atomic_types.ncdump
new file mode 100644
index 0000000000..dd4d209c48
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_atomic_types.ncdump
@@ -0,0 +1,57 @@
+netcdf test_atomic_types {
+types:
+  opaque(8) o_t ;
+  byte enum cloud_class_t {Clear = 0, Cumulonimbus = 1, Stratus = 2, 
+      Stratocumulus = 3, Cumulus = 4, Altostratus = 5, Nimbostratus = 6, 
+      Altocumulus = 7, Cirrostratus = 8, Cirrocumulus = 9, Cirrus = 10, 
+      Missing = 127} ;
+variables:
+	byte v8 ;
+	ubyte vu8 ;
+	short v16 ;
+	ushort vu16 ;
+	int v32 ;
+	uint vu32 ;
+	int64 v64 ;
+	uint64 vu64 ;
+	float vf ;
+	double vd ;
+	char vc ;
+	string vs ;
+	o_t vo ;
+	cloud_class_t primary_cloud ;
+		cloud_class_t primary_cloud:_FillValue = Missing ;
+	cloud_class_t secondary_cloud ;
+		cloud_class_t secondary_cloud:_FillValue = Missing ;
+data:
+
+ v8 = -128 ;
+
+ vu8 = 255 ;
+
+ v16 = -32768 ;
+
+ vu16 = _ ;
+
+ v32 = 2147483647 ;
+
+ vu32 = _ ;
+
+ v64 = 9223372036854775807 ;
+
+ vu64 = 18446744073709551615 ;
+
+ vf = 3.141593 ;
+
+ vd = 3.14159265358979 ;
+
+ vc = "@" ;
+
+ vs = "hello\tworld" ;
+
+ vo = 0X0123456789ABCDEF ;
+
+ primary_cloud = Stratus ;
+
+ secondary_cloud = _ ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_atomic_types.syn b/dap4/d4tests/src/test/data/resources/testfiles/test_atomic_types.syn
new file mode 100644
index 0000000000..d6f19ef663
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_atomic_types.syn
@@ -0,0 +1,40 @@
+<Dataset
+         name="test_atomic_types.syn"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Enumeration name="cloud_class_t" basetype="Int8">
+        <EnumConst name="Clear" value="0"/>
+        <EnumConst name="Cumulonimbus" value="1"/>
+        <EnumConst name="Stratus" value="2"/>
+        <EnumConst name="Stratocumulus" value="3"/>
+        <EnumConst name="Cumulus" value="4"/>
+        <EnumConst name="Altostratus" value="5"/>
+        <EnumConst name="Nimbostratus" value="6"/>
+        <EnumConst name="Altocumulus" value="7"/>
+        <EnumConst name="Cirrostratus" value="8"/>
+        <EnumConst name="Cirrocumulus" value="9"/>
+        <EnumConst name="Cirrus" value="10"/>
+        <EnumConst name="Missing" value="127"/>
+    </Enumeration>
+    <Int8 name="v8"/>
+    <UInt8 name="vu8"/>
+    <Int16 name="v16"/>
+    <UInt16 name="vu16"/>
+    <Int32 name="v32"/>
+    <UInt32 name="vu32"/>
+    <Int64 name="v64"/>
+    <UInt64 name="vu64"/>
+    <Float32 name="vf"/>
+    <Float64 name="vd"/>
+    <Char name="vc"/>
+    <String name="vs"/>
+    <Opaque name="vo"/>
+    <Enum name="primary_cloud" enum="/cloud_class_t">
+        <Attribute name="_FillValue" type="/cloud_class_t"><Value value="Missing"/></Attribute>
+    </Enum>
+    <Enum name="secondary_cloud" enum="/cloud_class_t">
+        <Attribute name="_FillValue" type="/cloud_class_t"><Value value="127"/></Attribute>
+    </Enum>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_enum.cdl b/dap4/d4tests/src/test/data/resources/testfiles/test_enum.cdl
new file mode 100644
index 0000000000..6cd1ceb34b
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_enum.cdl
@@ -0,0 +1,12 @@
+netcdf test_enum {
+types:
+  byte enum cloud_class_t {Clear = 0, Cumulonimbus = 1, Stratus = 2, 
+      Stratocumulus = 3, Cumulus = 4, Altostratus = 5, Nimbostratus = 6, 
+      Altocumulus = 7, Cirrostratus = 8, Cirrocumulus = 9, Cirrus = 10, 
+      Missing = 127} ;
+variables:
+  cloud_class_t primary_cloud;
+    cloud_class_t primary_cloud:_FillValue = Missing ;
+data:
+  primary_cloud = Stratus;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_enum.nc b/dap4/d4tests/src/test/data/resources/testfiles/test_enum.nc
new file mode 100644
index 0000000000..39a1db3688
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_enum.nc differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_enum.ncdump b/dap4/d4tests/src/test/data/resources/testfiles/test_enum.ncdump
new file mode 100644
index 0000000000..7a7ca86e1b
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_enum.ncdump
@@ -0,0 +1,13 @@
+netcdf test_enum {
+types:
+  byte enum cloud_class_t {Clear = 0, Cumulonimbus = 1, Stratus = 2, 
+      Stratocumulus = 3, Cumulus = 4, Altostratus = 5, Nimbostratus = 6, 
+      Altocumulus = 7, Cirrostratus = 8, Cirrocumulus = 9, Cirrus = 10, 
+      Missing = 127} ;
+variables:
+	cloud_class_t primary_cloud ;
+		cloud_class_t primary_cloud:_FillValue = Missing ;
+data:
+
+ primary_cloud = Stratus ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_enum1.cdl b/dap4/d4tests/src/test/data/resources/testfiles/test_enum1.cdl
new file mode 100644
index 0000000000..da9c770a8b
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_enum1.cdl
@@ -0,0 +1,12 @@
+netcdf test_enum1 {
+types:
+  byte enum cloud_class_t {Clear = 0, Cumulonimbus = 1, Stratus = 2, 
+      Stratocumulus = 3, Cumulus = 4, Altostratus = 5, Nimbostratus = 6, 
+      Altocumulus = 7, Cirrostratus = 8, Cirrocumulus = 9, Cirrus = 10, 
+      Missing = 127} ;
+variables:
+  cloud_class_t primary_cloud;
+    cloud_class_t primary_cloud:_FillValue = Missing ;
+data:
+  primary_cloud = Stratus;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_enum1.nc b/dap4/d4tests/src/test/data/resources/testfiles/test_enum1.nc
new file mode 100644
index 0000000000..39a1db3688
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_enum1.nc differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_enum1.ncdump b/dap4/d4tests/src/test/data/resources/testfiles/test_enum1.ncdump
new file mode 100644
index 0000000000..7aea061a3b
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_enum1.ncdump
@@ -0,0 +1,13 @@
+netcdf test_enum1 {
+types:
+  byte enum cloud_class_t {Clear = 0, Cumulonimbus = 1, Stratus = 2, 
+      Stratocumulus = 3, Cumulus = 4, Altostratus = 5, Nimbostratus = 6, 
+      Altocumulus = 7, Cirrostratus = 8, Cirrocumulus = 9, Cirrus = 10, 
+      Missing = 127} ;
+variables:
+	cloud_class_t primary_cloud ;
+		cloud_class_t primary_cloud:_FillValue = Missing ;
+data:
+
+ primary_cloud = Stratus ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_enum_2.cdl b/dap4/d4tests/src/test/data/resources/testfiles/test_enum_2.cdl
new file mode 100644
index 0000000000..ef6ab50d1d
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_enum_2.cdl
@@ -0,0 +1,15 @@
+// Test cross group enum references
+netcdf test_enum_2 {
+  types:
+    byte enum cloud_class_t {Clear = 0, Cumulonimbus = 1, Stratus = 2, 
+      Stratocumulus = 3, Cumulus = 4, Altostratus = 5, Nimbostratus = 6, 
+      Altocumulus = 7, Cirrostratus = 8, Cirrocumulus = 9, Cirrus = 10, 
+      Missing = 127} ;
+  group: h {
+  variables:
+    /cloud_class_t primary_cloud;
+      /cloud_class_t primary_cloud:_FillValue = Missing ;
+  data:
+    primary_cloud = Stratus;
+  }
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_enum_2.nc b/dap4/d4tests/src/test/data/resources/testfiles/test_enum_2.nc
new file mode 100644
index 0000000000..ff30729699
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_enum_2.nc differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_enum_2.ncdump b/dap4/d4tests/src/test/data/resources/testfiles/test_enum_2.ncdump
new file mode 100644
index 0000000000..b651551733
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_enum_2.ncdump
@@ -0,0 +1,16 @@
+netcdf test_enum_2 {
+types:
+  byte enum cloud_class_t {Clear = 0, Cumulonimbus = 1, Stratus = 2, 
+      Stratocumulus = 3, Cumulus = 4, Altostratus = 5, Nimbostratus = 6, 
+      Altocumulus = 7, Cirrostratus = 8, Cirrocumulus = 9, Cirrus = 10, 
+      Missing = 127} ;
+
+group: h {
+  variables:
+  	cloud_class_t primary_cloud ;
+  		cloud_class_t primary_cloud:_FillValue = Missing ;
+  data:
+
+   primary_cloud = Stratus ;
+  } // group h
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_enum_array.cdl b/dap4/d4tests/src/test/data/resources/testfiles/test_enum_array.cdl
new file mode 100644
index 0000000000..d395990b64
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_enum_array.cdl
@@ -0,0 +1,14 @@
+netcdf test_enum_array {
+types:
+  byte enum cloud_class_t {Clear = 0, Cumulonimbus = 1, Stratus = 2, 
+      Stratocumulus = 3, Cumulus = 4, Altostratus = 5, Nimbostratus = 6, 
+      Altocumulus = 7, Cirrostratus = 8, Cirrocumulus = 9, Cirrus = 10, 
+      Missing = 127} ;
+dimensions:
+  d5 = 5;
+variables:
+  cloud_class_t primary_cloud(d5);
+    cloud_class_t primary_cloud:_FillValue = Missing ;
+data:
+ primary_cloud = Clear, Stratus, Clear, Cumulonimbus, _ ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_enum_array.nc b/dap4/d4tests/src/test/data/resources/testfiles/test_enum_array.nc
new file mode 100644
index 0000000000..c6b4a2f388
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_enum_array.nc differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_enum_array.ncdump b/dap4/d4tests/src/test/data/resources/testfiles/test_enum_array.ncdump
new file mode 100644
index 0000000000..1c5944620a
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_enum_array.ncdump
@@ -0,0 +1,15 @@
+netcdf test_enum_array {
+types:
+  byte enum cloud_class_t {Clear = 0, Cumulonimbus = 1, Stratus = 2, 
+      Stratocumulus = 3, Cumulus = 4, Altostratus = 5, Nimbostratus = 6, 
+      Altocumulus = 7, Cirrostratus = 8, Cirrocumulus = 9, Cirrus = 10, 
+      Missing = 127} ;
+dimensions:
+	d5 = 5 ;
+variables:
+	cloud_class_t primary_cloud(d5) ;
+		cloud_class_t primary_cloud:_FillValue = Missing ;
+data:
+
+ primary_cloud = Clear, Stratus, Clear, Cumulonimbus, _ ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_fill.cdl b/dap4/d4tests/src/test/data/resources/testfiles/test_fill.cdl
new file mode 100644
index 0000000000..7d2af998fc
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_fill.cdl
@@ -0,0 +1,11 @@
+netcdf test_fill {
+variables:
+  ubyte uv8;
+  short v16;
+  uint uv32;
+	uv32:_FillValue=17;
+data:
+  uv8 = 240;
+  v16 = 32700;
+  uv32 = 111000;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_fill.nc b/dap4/d4tests/src/test/data/resources/testfiles/test_fill.nc
new file mode 100644
index 0000000000..35e817fd5a
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_fill.nc differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_fill.ncdump b/dap4/d4tests/src/test/data/resources/testfiles/test_fill.ncdump
new file mode 100644
index 0000000000..5ca0494ef7
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_fill.ncdump
@@ -0,0 +1,14 @@
+netcdf test_fill {
+variables:
+	ubyte uv8 ;
+	short v16 ;
+	uint uv32 ;
+		uv32:_FillValue = 17U ;
+data:
+
+ uv8 = 240 ;
+
+ v16 = 32700 ;
+
+ uv32 = 111000 ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_groups1.cdl b/dap4/d4tests/src/test/data/resources/testfiles/test_groups1.cdl
new file mode 100644
index 0000000000..bde2677083
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_groups1.cdl
@@ -0,0 +1,35 @@
+netcdf test_groups1 {
+dimensions:
+  dim1 = 5 ;
+
+group: g {
+  dimensions:
+    dim2 = 3 ;
+
+  group: h {
+    dimensions:
+      dim3 = 7 ;
+    variables:
+      int v1(dim1);
+      float v2(dim2);
+    data:
+
+     v1 = -876354855, -1761252264, 1723477387, -46827465, 1475147969;
+
+     v2 = 12, -100, _ ;
+  } // group h
+
+  group: i {
+    dimensions:
+      dim3 = 7 ;
+    variables:
+      int v1(dim1);
+      float v3(dim3);
+    data:
+
+     v1 = 2, 3, 5, 7, 11 ;
+
+     v3 = 23, 29, 19, 31, 17, 37, 13 ;
+  } // group i
+} // group g
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_groups1.nc b/dap4/d4tests/src/test/data/resources/testfiles/test_groups1.nc
new file mode 100644
index 0000000000..b4fe34704f
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_groups1.nc differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_groups1.ncdump b/dap4/d4tests/src/test/data/resources/testfiles/test_groups1.ncdump
new file mode 100644
index 0000000000..d351478dbe
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_groups1.ncdump
@@ -0,0 +1,35 @@
+netcdf test_groups1 {
+dimensions:
+	dim1 = 5 ;
+
+group: g {
+  dimensions:
+  	dim2 = 3 ;
+
+  group: h {
+    dimensions:
+    	dim3 = 7 ;
+    variables:
+    	int v1(dim1) ;
+    	float v2(dim2) ;
+    data:
+
+     v1 = -876354855, -1761252264, 1723477387, -46827465, 1475147969 ;
+
+     v2 = 12, -100, _ ;
+    } // group h
+
+  group: i {
+    dimensions:
+    	dim3 = 7 ;
+    variables:
+    	int v1(dim1) ;
+    	float v3(dim3) ;
+    data:
+
+     v1 = 2, 3, 5, 7, 11 ;
+
+     v3 = 23, 29, 19, 31, 17, 37, 13 ;
+    } // group i
+  } // group g
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_misc1.nc b/dap4/d4tests/src/test/data/resources/testfiles/test_misc1.nc
new file mode 100644
index 0000000000..36fbab844d
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_misc1.nc differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_one_var.cdl b/dap4/d4tests/src/test/data/resources/testfiles/test_one_var.cdl
new file mode 100644
index 0000000000..f5edd1268f
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_one_var.cdl
@@ -0,0 +1,6 @@
+netcdf test_one_var {
+variables:
+  int t;
+data:
+  t = 17;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_one_var.nc b/dap4/d4tests/src/test/data/resources/testfiles/test_one_var.nc
new file mode 100644
index 0000000000..4169d2d296
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_one_var.nc differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_one_var.ncdump b/dap4/d4tests/src/test/data/resources/testfiles/test_one_var.ncdump
new file mode 100644
index 0000000000..f4ab177bd6
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_one_var.ncdump
@@ -0,0 +1,7 @@
+netcdf test_one_var {
+variables:
+	int t ;
+data:
+
+ t = 17 ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_one_vararray.cdl b/dap4/d4tests/src/test/data/resources/testfiles/test_one_vararray.cdl
new file mode 100644
index 0000000000..78d1ef14de
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_one_vararray.cdl
@@ -0,0 +1,8 @@
+netcdf test_one_vararray {
+dimensions:
+ d2 = 2;
+variables:
+  int t(d2);
+data:
+  t = 17, 37;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_one_vararray.nc b/dap4/d4tests/src/test/data/resources/testfiles/test_one_vararray.nc
new file mode 100644
index 0000000000..e0cc0ce34a
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_one_vararray.nc differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_one_vararray.ncdump b/dap4/d4tests/src/test/data/resources/testfiles/test_one_vararray.ncdump
new file mode 100644
index 0000000000..964677c450
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_one_vararray.ncdump
@@ -0,0 +1,9 @@
+netcdf test_one_vararray {
+dimensions:
+	d2 = 2 ;
+variables:
+	int t(d2) ;
+data:
+
+ t = 17, 37 ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_opaque.cdl b/dap4/d4tests/src/test/data/resources/testfiles/test_opaque.cdl
new file mode 100644
index 0000000000..5cc4e7abb3
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_opaque.cdl
@@ -0,0 +1,8 @@
+netcdf test_opaque {
+types:
+  opaque(8) o_t;  
+variables:
+  o_t vo1;
+data:
+ vo1 = 0X0123456789ABCDEF ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_opaque.nc b/dap4/d4tests/src/test/data/resources/testfiles/test_opaque.nc
new file mode 100644
index 0000000000..ae6b866e9d
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_opaque.nc differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_opaque.ncdump b/dap4/d4tests/src/test/data/resources/testfiles/test_opaque.ncdump
new file mode 100644
index 0000000000..97de1aedbf
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_opaque.ncdump
@@ -0,0 +1,9 @@
+netcdf test_opaque {
+types:
+  opaque(8) o_t ;
+variables:
+	o_t vo1 ;
+data:
+
+ vo1 = 0X0123456789ABCDEF ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_opaque_array.cdl b/dap4/d4tests/src/test/data/resources/testfiles/test_opaque_array.cdl
new file mode 100644
index 0000000000..bd33119964
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_opaque_array.cdl
@@ -0,0 +1,12 @@
+netcdf test_opaque_array {
+types:
+  opaque(8) o_t;  
+dimensions:
+  d2 = 2;
+variables:
+  o_t vo2(d2,d2);
+data:
+ vo2 =
+   0X0123456789ABCDEF, 0XABCDEF0000000000,
+   0XFEDCBA9876543210, 0XFEDCBA9999999999;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_opaque_array.nc b/dap4/d4tests/src/test/data/resources/testfiles/test_opaque_array.nc
new file mode 100644
index 0000000000..895a8bf065
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_opaque_array.nc differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_opaque_array.ncdump b/dap4/d4tests/src/test/data/resources/testfiles/test_opaque_array.ncdump
new file mode 100644
index 0000000000..4a7e2f1825
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_opaque_array.ncdump
@@ -0,0 +1,13 @@
+netcdf test_opaque_array {
+types:
+  opaque(8) o_t ;
+dimensions:
+	d2 = 2 ;
+variables:
+	o_t vo2(d2, d2) ;
+data:
+
+ vo2 =
+  0X0123456789ABCDEF, 0XABCDEF0000000000,
+  0XFEDCBA9876543210, 0XFEDCBA9999999999 ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_sequence_1.syn b/dap4/d4tests/src/test/data/resources/testfiles/test_sequence_1.syn
new file mode 100644
index 0000000000..355f652977
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_sequence_1.syn
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Dataset 
+         name="test_sequence_1.syn"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Sequence name="s">
+        <Int32 name="i1"/>
+        <Int16 name="sh1"/>
+    </Sequence>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_sequence_2.syn b/dap4/d4tests/src/test/data/resources/testfiles/test_sequence_2.syn
new file mode 100644
index 0000000000..4aa6576faf
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_sequence_2.syn
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Dataset 
+         name="test_sequence_2.syn"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Sequence name="s">
+        <Int32 name="i1"/>
+        <Int16 name="sh1"/>
+	<Dim size="2"/>
+    </Sequence>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_struct1.cdl b/dap4/d4tests/src/test/data/resources/testfiles/test_struct1.cdl
new file mode 100644
index 0000000000..005f897c52
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_struct1.cdl
@@ -0,0 +1,11 @@
+netcdf test_struct_type {
+  types:
+    compound c_t {
+      int x ;
+      int y ;
+    }; // c_t
+variables:
+  c_t s;
+data:
+  s = {1,-2};
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_struct1.nc b/dap4/d4tests/src/test/data/resources/testfiles/test_struct1.nc
new file mode 100644
index 0000000000..2a988dc2fe
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_struct1.nc differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_struct1.ncdump b/dap4/d4tests/src/test/data/resources/testfiles/test_struct1.ncdump
new file mode 100644
index 0000000000..1b2c36e6f7
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_struct1.ncdump
@@ -0,0 +1,12 @@
+netcdf test_struct1 {
+types:
+  compound c_t {
+    int x ;
+    int y ;
+  }; // c_t
+variables:
+	c_t s ;
+data:
+
+ s = {1, -2} ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_struct_array.cdl b/dap4/d4tests/src/test/data/resources/testfiles/test_struct_array.cdl
new file mode 100644
index 0000000000..bc5f723006
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_struct_array.cdl
@@ -0,0 +1,18 @@
+netcdf test_struct_array {
+types:
+    compound c_t {
+      int x ;
+      int y ;
+    }; // c_t
+dimensions:
+ dx = 4;
+ dy = 3;
+variables:
+  c_t s(dx,dy);
+data:
+ s =
+/*[0][0..2]*/  {1, -1}, {17, 37}, {-32767, 32767},
+/*[1][0..2]*/  {-1, 3}, {-2, 2}, {-3, 1},
+/*[2][0..2]*/  {-4, 12}, {-8, 8}, {-12, 4},
+/*[3][0..2]*/  {-5, 15}, {-10, 10}, {-15, 5} ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_struct_array.nc b/dap4/d4tests/src/test/data/resources/testfiles/test_struct_array.nc
new file mode 100644
index 0000000000..00be0b7551
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_struct_array.nc differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_struct_array.ncdump b/dap4/d4tests/src/test/data/resources/testfiles/test_struct_array.ncdump
new file mode 100644
index 0000000000..c306c05595
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_struct_array.ncdump
@@ -0,0 +1,19 @@
+netcdf test_struct_array {
+types:
+  compound c_t {
+    int x ;
+    int y ;
+  }; // c_t
+dimensions:
+	dx = 4 ;
+	dy = 3 ;
+variables:
+	c_t s(dx, dy) ;
+data:
+
+ s =
+  {1, -1}, {17, 37}, {-32767, 32767},
+  {-1, 3}, {-2, 2}, {-3, 1},
+  {-4, 12}, {-8, 8}, {-12, 4},
+  {-5, 15}, {-10, 10}, {-15, 5} ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_struct_array.syn b/dap4/d4tests/src/test/data/resources/testfiles/test_struct_array.syn
new file mode 100644
index 0000000000..dfe5cf7484
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_struct_array.syn
@@ -0,0 +1,25 @@
+<Dataset
+         name="test_struct_array.nc"
+         dapVersion="4.0"
+         dmrVersion="1.0"
+         xmlns="http://xml.opendap.org/ns/DAP/4.0#"
+         xmlns:dap="http://xml.opendap.org/ns/DAP/4.0#">
+    <Dimension name="dx" size="4"/>
+    <Dimension name="dy" size="3"/>
+    
+    <Float32 name="z">
+        <Dim name="/dx"/>
+    </Float32>
+    <Float32 name="t">
+        <Dim name="/dy"/>
+    </Float32>
+    
+    <Structure name="s">
+        <Int32 name="x"/>
+        <Int32 name="y"/>
+        <Dim name="/dx"/>
+        <Dim name="/dy"/>
+        <Map name="/z"/>
+        <Map name="/t"/>
+    </Structure>
+</Dataset>
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_struct_nested.cdl b/dap4/d4tests/src/test/data/resources/testfiles/test_struct_nested.cdl
new file mode 100644
index 0000000000..399d8954ef
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_struct_nested.cdl
@@ -0,0 +1,15 @@
+netcdf test_struct_nested {
+  types:
+    compound s1_t {
+      int x ;
+      int y ;
+    }; // s1_t
+    compound s2_t {
+      s1_t field1 ;
+      s1_t field2 ;
+    }; // s2_t
+variables:
+  s2_t x;
+data:
+  x = {{1,-2}, {255, 90}};
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_struct_nested.hdf5 b/dap4/d4tests/src/test/data/resources/testfiles/test_struct_nested.hdf5
new file mode 100644
index 0000000000..f49856fa34
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_struct_nested.hdf5 differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_struct_nested.nc b/dap4/d4tests/src/test/data/resources/testfiles/test_struct_nested.nc
new file mode 100644
index 0000000000..42f2e6a7ea
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_struct_nested.nc differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_struct_nested.ncdump b/dap4/d4tests/src/test/data/resources/testfiles/test_struct_nested.ncdump
new file mode 100644
index 0000000000..16c71d22bf
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_struct_nested.ncdump
@@ -0,0 +1,16 @@
+netcdf test_struct_nested {
+types:
+  compound s1_t {
+    int x ;
+    int y ;
+  }; // s1_t
+  compound s2_t {
+    s1_t field1 ;
+    s1_t field2 ;
+  }; // s2_t
+variables:
+	s2_t x ;
+data:
+
+ x = {{1, -2}, {255, 90}} ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_struct_nested3.cdl b/dap4/d4tests/src/test/data/resources/testfiles/test_struct_nested3.cdl
new file mode 100644
index 0000000000..e52eba8179
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_struct_nested3.cdl
@@ -0,0 +1,16 @@
+netcdf test_struct_nested3 {
+  types:
+    compound s1_t {
+      int field1 ;
+    }; // s1_t
+    compound s2_t {
+      s1_t field2 ;
+    }; // s2_t
+    compound s3_t {
+      s2_t field3 ;
+    }; // s2_t
+variables:
+  s3_t x;
+data:
+ x = {{{17}}} ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_struct_nested3.hdf5 b/dap4/d4tests/src/test/data/resources/testfiles/test_struct_nested3.hdf5
new file mode 100644
index 0000000000..7e0173c94a
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_struct_nested3.hdf5 differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_struct_nested3.nc b/dap4/d4tests/src/test/data/resources/testfiles/test_struct_nested3.nc
new file mode 100644
index 0000000000..c8cc68e0d6
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_struct_nested3.nc differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_struct_nested3.ncdump b/dap4/d4tests/src/test/data/resources/testfiles/test_struct_nested3.ncdump
new file mode 100644
index 0000000000..a3a6cb40e2
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_struct_nested3.ncdump
@@ -0,0 +1,17 @@
+netcdf test_struct_nested3 {
+types:
+  compound s1_t {
+    int field1 ;
+  }; // s1_t
+  compound s2_t {
+    s1_t field2 ;
+  }; // s2_t
+  compound s3_t {
+    s2_t field3 ;
+  }; // s3_t
+variables:
+	s3_t x ;
+data:
+
+ x = {{{17}}} ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_struct_type.cdl b/dap4/d4tests/src/test/data/resources/testfiles/test_struct_type.cdl
new file mode 100644
index 0000000000..005f897c52
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_struct_type.cdl
@@ -0,0 +1,11 @@
+netcdf test_struct_type {
+  types:
+    compound c_t {
+      int x ;
+      int y ;
+    }; // c_t
+variables:
+  c_t s;
+data:
+  s = {1,-2};
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_struct_type.nc b/dap4/d4tests/src/test/data/resources/testfiles/test_struct_type.nc
new file mode 100644
index 0000000000..2a988dc2fe
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_struct_type.nc differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_struct_type.ncdump b/dap4/d4tests/src/test/data/resources/testfiles/test_struct_type.ncdump
new file mode 100644
index 0000000000..6fc0c77b50
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_struct_type.ncdump
@@ -0,0 +1,12 @@
+netcdf test_struct_type {
+types:
+  compound c_t {
+    int x ;
+    int y ;
+  }; // c_t
+variables:
+	c_t s ;
+data:
+
+ s = {1, -2} ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_test.cdl b/dap4/d4tests/src/test/data/resources/testfiles/test_test.cdl
new file mode 100644
index 0000000000..684d1c5002
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_test.cdl
@@ -0,0 +1,11 @@
+netcdf test_test {
+
+types:
+  byte enum enum_t {c1=1, c2=2, c3=3};
+
+variables:
+  enum_t v1;
+
+data:
+  v1 = c1;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_test.nc b/dap4/d4tests/src/test/data/resources/testfiles/test_test.nc
new file mode 100644
index 0000000000..56638925f8
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_test.nc differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_test.ncdump b/dap4/d4tests/src/test/data/resources/testfiles/test_test.ncdump
new file mode 100644
index 0000000000..936c3cfeef
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_test.ncdump
@@ -0,0 +1,9 @@
+netcdf test_test {
+types:
+  byte enum enum_t {c1 = 1, c2 = 2, c3 = 3} ;
+variables:
+	enum_t v1 ;
+data:
+
+ v1 = c1 ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_unlim.nc b/dap4/d4tests/src/test/data/resources/testfiles/test_unlim.nc
new file mode 100644
index 0000000000..f362f967fb
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_unlim.nc differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_unlim1.cdl b/dap4/d4tests/src/test/data/resources/testfiles/test_unlim1.cdl
new file mode 100644
index 0000000000..e300442837
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_unlim1.cdl
@@ -0,0 +1,27 @@
+netcdf test_unlim1 {
+dimensions:
+	lat = 3 ;
+	lon = 2 ;
+	time = UNLIMITED ; // (2 currently)
+variables:
+	float lat(lat) ;
+		lat:units = "degrees_north" ;
+	float lon(lon) ;
+		lon:units = "degrees_east" ;
+	double time(time) ;
+		time:units = "seconds since 2009-01-01" ;
+	float pr(time, lat, lon) ;
+		pr:standard_name = "air_pressure_at_sea_level" ;
+		pr:units = "hPa" ;
+
+// global attributes:
+		:title = "example for workshop" ;
+data:
+ pr =
+  0, 1,
+  2, 3,
+  4, 5,
+  10, 11,
+  12, 13,
+  14, 15 ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_unlim1.nc b/dap4/d4tests/src/test/data/resources/testfiles/test_unlim1.nc
new file mode 100644
index 0000000000..5b92931e63
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_unlim1.nc differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_unlim1.ncdump b/dap4/d4tests/src/test/data/resources/testfiles/test_unlim1.ncdump
new file mode 100644
index 0000000000..da7d31a211
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_unlim1.ncdump
@@ -0,0 +1,34 @@
+netcdf test_unlim1 {
+dimensions:
+	lat = 3 ;
+	lon = 2 ;
+	time = UNLIMITED ; // (2 currently)
+variables:
+	float lat(lat) ;
+		lat:units = "degrees_north" ;
+	float lon(lon) ;
+		lon:units = "degrees_east" ;
+	double time(time) ;
+		time:units = "seconds since 2009-01-01" ;
+	float pr(time, lat, lon) ;
+		pr:standard_name = "air_pressure_at_sea_level" ;
+		pr:units = "hPa" ;
+
+// global attributes:
+		:title = "example for workshop" ;
+data:
+
+ lat = _, _, _ ;
+
+ lon = _, _ ;
+
+ time = _, _ ;
+
+ pr =
+  0, 1,
+  2, 3,
+  4, 5,
+  10, 11,
+  12, 13,
+  14, 15 ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_utf8.cdl b/dap4/d4tests/src/test/data/resources/testfiles/test_utf8.cdl
new file mode 100644
index 0000000000..14025f5a36
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_utf8.cdl
@@ -0,0 +1,8 @@
+netcdf test_utf8 {
+dimensions:
+  d2 = 2;
+variables:
+  string vs(d2);
+data:
+  vs = "Καλημέα" , "abc";
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_utf8.nc b/dap4/d4tests/src/test/data/resources/testfiles/test_utf8.nc
new file mode 100644
index 0000000000..fd90a6f12e
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_utf8.nc differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_utf8.ncdump b/dap4/d4tests/src/test/data/resources/testfiles/test_utf8.ncdump
new file mode 100644
index 0000000000..d9429c1be3
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_utf8.ncdump
@@ -0,0 +1,9 @@
+netcdf test_utf8 {
+dimensions:
+	d2 = 2 ;
+variables:
+	string vs(d2) ;
+data:
+
+ vs = "Καλημέα", "abc" ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen1.cdl b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen1.cdl
new file mode 100644
index 0000000000..3ec2f06543
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen1.cdl
@@ -0,0 +1,11 @@
+netcdf test_vlen1 {
+
+types:
+  int(*) vlen_t;
+
+variables:
+  vlen_t x;  
+
+data:
+  x = {1, 3, 5, 7};
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen1.nc b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen1.nc
new file mode 100644
index 0000000000..4c7f097564
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen1.nc differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen1.ncdump b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen1.ncdump
new file mode 100644
index 0000000000..68140f424e
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen1.ncdump
@@ -0,0 +1,9 @@
+netcdf test_vlen1 {
+types:
+  int(*) vlen_t ;
+variables:
+	vlen_t x ;
+data:
+
+ x = {1, 3, 5, 7} ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen10.cdl b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen10.cdl
new file mode 100644
index 0000000000..ebdf6ce624
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen10.cdl
@@ -0,0 +1,14 @@
+netcdf test_vlen10 {
+
+types:
+  compound c_t {int x; float y;};
+  c_t(*) v_t;
+
+variables:
+  v_t v;  
+
+data:
+
+ v = {{17,30.7}, {19,101.1}};
+}
+
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen10.nc b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen10.nc
new file mode 100644
index 0000000000..eeb02b6351
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen10.nc differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen10.ncdump b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen10.ncdump
new file mode 100644
index 0000000000..432a625790
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen10.ncdump
@@ -0,0 +1,13 @@
+netcdf test_vlen10 {
+types:
+  compound c_t {
+    int x ;
+    float y ;
+  }; // c_t
+  c_t(*) v_t ;
+variables:
+	v_t v ;
+data:
+
+ v = {{17, 30.7}, {19, 101.1}} ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen11.cdl b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen11.cdl
new file mode 100644
index 0000000000..98c0575603
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen11.cdl
@@ -0,0 +1,13 @@
+netcdf test_vlen11 {
+
+types:
+  int(*) v1_t;
+  v1_t(*) v2_t;
+
+variables:
+  v2_t v;  
+
+data:
+  v = {{1, 3, 5, 7},{100,200}} ;
+}
+
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen11.nc b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen11.nc
new file mode 100644
index 0000000000..729e4b607b
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen11.nc differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen11.ncdump b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen11.ncdump
new file mode 100644
index 0000000000..806ec725c1
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen11.ncdump
@@ -0,0 +1,10 @@
+netcdf test_vlen11 {
+types:
+  int(*) v1_t ;
+  v1_t(*) v2_t ;
+variables:
+	v2_t v ;
+data:
+
+ v = {{1, 3, 5, 7}, {100, 200}} ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen2.cdl b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen2.cdl
new file mode 100644
index 0000000000..8e3a578c18
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen2.cdl
@@ -0,0 +1,15 @@
+netcdf test_vlen2 {
+
+types:
+  int(*) vlen_t;
+
+dimensions:
+  d3=3;
+  d2=2;
+	
+variables:
+  vlen_t x(d3,d2);  
+
+data:
+  x = {1, 3, 5, 7}, {100,200}, {-1,-2},{1, 3, 5, 7}, {100,200}, {-1,-2};
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen2.nc b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen2.nc
new file mode 100644
index 0000000000..dd2d4a2f1e
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen2.nc differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen2.ncdump b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen2.ncdump
new file mode 100644
index 0000000000..0398d71252
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen2.ncdump
@@ -0,0 +1,15 @@
+netcdf test_vlen2 {
+types:
+  int(*) vlen_t ;
+dimensions:
+	d3 = 3 ;
+	d2 = 2 ;
+variables:
+	vlen_t x(d3, d2) ;
+data:
+
+ x =
+  {1, 3, 5, 7}, {100, 200},
+  {-1, -2}, {1, 3, 5, 7},
+  {100, 200}, {-1, -2} ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen3.cdl b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen3.cdl
new file mode 100644
index 0000000000..a4365fe4b9
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen3.cdl
@@ -0,0 +1,13 @@
+netcdf test_vlen3 {
+
+types:
+  int(*) v_t;
+  compound c_t {v_t f1;};
+
+variables:
+  c_t v1;  
+
+data:
+  v1 = {{1, 3, 5, 7}} ;
+}
+
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen3.hdf5 b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen3.hdf5
new file mode 100644
index 0000000000..2d3be72508
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen3.hdf5 differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen3.nc b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen3.nc
new file mode 100644
index 0000000000..e5564961e2
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen3.nc differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen3.ncdump b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen3.ncdump
new file mode 100644
index 0000000000..84e768b57f
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen3.ncdump
@@ -0,0 +1,12 @@
+netcdf test_vlen3 {
+types:
+  int(*) v_t ;
+  compound c_t {
+    v_t f1 ;
+  }; // c_t
+variables:
+	c_t v1 ;
+data:
+
+ v1 = {{1, 3, 5, 7}} ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen4.cdl b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen4.cdl
new file mode 100644
index 0000000000..b6db7ff2e7
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen4.cdl
@@ -0,0 +1,13 @@
+netcdf test_vlen4 {
+
+types:
+  int(*) v_t;
+  compound c_t {v_t f1(2);};
+
+variables:
+  c_t v1;  
+
+data:
+  v1 = {{{1, 3, 5, 7},{100,200}}} ;
+}
+
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen4.hdf5 b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen4.hdf5
new file mode 100644
index 0000000000..cf0654cd89
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen4.hdf5 differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen4.nc b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen4.nc
new file mode 100644
index 0000000000..f119d3d119
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen4.nc differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen4.ncdump b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen4.ncdump
new file mode 100644
index 0000000000..3f3e8ac2c4
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen4.ncdump
@@ -0,0 +1,12 @@
+netcdf test_vlen4 {
+types:
+  int(*) v_t ;
+  compound c_t {
+    v_t f1(2) ;
+  }; // c_t
+variables:
+	c_t v1 ;
+data:
+
+ v1 = {{{1, 3, 5, 7}, {100, 200}}} ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen5.cdl b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen5.cdl
new file mode 100644
index 0000000000..11d8efa54a
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen5.cdl
@@ -0,0 +1,16 @@
+netcdf test_vlen5 {
+
+types:
+  int(*) v_t;
+  compound c_t {v_t v;};
+
+dimensions:
+  d2=2;
+
+variables:
+  c_t v1(d2);  
+
+data:
+  v1 = {{1, 3, 5, 7}},{{100,200}} ;
+}
+
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen5.hdf5 b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen5.hdf5
new file mode 100644
index 0000000000..cd54563424
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen5.hdf5 differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen5.nc b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen5.nc
new file mode 100644
index 0000000000..95343fff4f
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen5.nc differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen5.ncdump b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen5.ncdump
new file mode 100644
index 0000000000..aaf9eec519
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen5.ncdump
@@ -0,0 +1,14 @@
+netcdf test_vlen5 {
+types:
+  int(*) v_t ;
+  compound c_t {
+    v_t v ;
+  }; // c_t
+dimensions:
+	d2 = 2 ;
+variables:
+	c_t v1(d2) ;
+data:
+
+ v1 = {{1, 3, 5, 7}}, {{100, 200}} ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen6.cdl b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen6.cdl
new file mode 100644
index 0000000000..b116583de5
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen6.cdl
@@ -0,0 +1,16 @@
+netcdf test_vlen6 {
+
+types:
+  int(*) v_t;
+
+dimensions:
+  d=2;
+
+variables:
+  v_t v1(d);  
+
+data:
+
+ v1 = {1,3,5,7}, {17,19} ;
+}
+
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen6.nc b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen6.nc
new file mode 100644
index 0000000000..f294775e10
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen6.nc differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen6.ncdump b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen6.ncdump
new file mode 100644
index 0000000000..bbe124ecaf
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen6.ncdump
@@ -0,0 +1,11 @@
+netcdf test_vlen6 {
+types:
+  int(*) v_t ;
+dimensions:
+	d = 2 ;
+variables:
+	v_t v1(d) ;
+data:
+
+ v1 = {1, 3, 5, 7}, {17, 19} ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen7.cdl b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen7.cdl
new file mode 100644
index 0000000000..3711750729
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen7.cdl
@@ -0,0 +1,16 @@
+netcdf test_vlen7 {
+
+types:
+  int(*) v_t;
+
+dimensions:
+  d=1;
+
+variables:
+  v_t v1(d);  
+
+data:
+
+ v1 = {17,19,21} ;
+}
+
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen7.nc b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen7.nc
new file mode 100644
index 0000000000..f1989bf335
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen7.nc differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen7.ncdump b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen7.ncdump
new file mode 100644
index 0000000000..8826f39f77
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen7.ncdump
@@ -0,0 +1,11 @@
+netcdf test_vlen7 {
+types:
+  int(*) v_t ;
+dimensions:
+	d = 1 ;
+variables:
+	v_t v1(d) ;
+data:
+
+ v1 = {17, 19, 21} ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen8.cdl b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen8.cdl
new file mode 100644
index 0000000000..f7522a93dd
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen8.cdl
@@ -0,0 +1,19 @@
+netcdf test_vlen8 {
+
+types:
+  int(*) v_t;
+
+dimensions:
+  d1=2;
+  d2=2;
+
+variables:
+  v_t v1(d1,d2);  
+
+data:
+
+  v1 =
+   {1,3,5,7}, {17,19},
+   {11,33,55,77}, {717,919};
+}
+
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen8.nc b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen8.nc
new file mode 100644
index 0000000000..9546ef1c64
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen8.nc differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen8.ncdump b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen8.ncdump
new file mode 100644
index 0000000000..c498cb64f5
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen8.ncdump
@@ -0,0 +1,14 @@
+netcdf test_vlen8 {
+types:
+  int(*) v_t ;
+dimensions:
+	d1 = 2 ;
+	d2 = 2 ;
+variables:
+	v_t v1(d1, d2) ;
+data:
+
+ v1 =
+  {1, 3, 5, 7}, {17, 19},
+  {11, 33, 55, 77}, {717, 919} ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen9.cdl b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen9.cdl
new file mode 100644
index 0000000000..4244c2425c
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen9.cdl
@@ -0,0 +1,16 @@
+netcdf test_vlen9 {
+
+types:
+  compound c_t {int x; float y;};
+  c_t(*) v_t;
+
+dimensions:
+  d=2;
+
+variables:
+  v_t v(d);  
+
+data:
+
+ v = {{17,30.7}}, {{19,101.1},{2,1.0}} ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen9.nc b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen9.nc
new file mode 100644
index 0000000000..572ed1deaa
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen9.nc differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_vlen9.ncdump b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen9.ncdump
new file mode 100644
index 0000000000..506c9ab6aa
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_vlen9.ncdump
@@ -0,0 +1,15 @@
+netcdf test_vlen9 {
+types:
+  compound c_t {
+    int x ;
+    float y ;
+  }; // c_t
+  c_t(*) v_t ;
+dimensions:
+	d = 2 ;
+variables:
+	v_t v(d) ;
+data:
+
+ v = {{17, 30.7}}, {{19, 101.1}, {2, 1}} ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_zerodim.cdl b/dap4/d4tests/src/test/data/resources/testfiles/test_zerodim.cdl
new file mode 100644
index 0000000000..6afadd0a51
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_zerodim.cdl
@@ -0,0 +1,23 @@
+netcdf test_zerodim {
+dimensions:
+	lat = 6 ;
+	lon = 4 ;
+	time = UNLIMITED ; // (0 currently)
+	unlim = UNLIMITED ; // (3 currently)
+variables:
+	float lat(lat) ;
+		lat:units = "degrees_north" ;
+	float lon(lon) ;
+		lon:units = "degrees_east" ;
+	double time(time) ;
+		time:units = "seconds since 2009-01-01" ;
+	float pr(time, lat, lon) ;
+		pr:standard_name = "air_pressure_at_sea_level" ;
+		pr:units = "hPa" ;
+	float var(unlim) ;
+
+// global attributes:
+		:title = "example for workshop" ;
+data:
+ var = 0, 1, 3 ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_zerodim.nc b/dap4/d4tests/src/test/data/resources/testfiles/test_zerodim.nc
new file mode 100644
index 0000000000..85ecf70d96
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/test_zerodim.nc differ
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/test_zerodim.ncdump b/dap4/d4tests/src/test/data/resources/testfiles/test_zerodim.ncdump
new file mode 100644
index 0000000000..e13baa0d39
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/test_zerodim.ncdump
@@ -0,0 +1,28 @@
+netcdf test_zerodim {
+dimensions:
+	lat = 6 ;
+	lon = 4 ;
+	time = UNLIMITED ; // (0 currently)
+	unlim = UNLIMITED ; // (3 currently)
+variables:
+	float lat(lat) ;
+		lat:units = "degrees_north" ;
+	float lon(lon) ;
+		lon:units = "degrees_east" ;
+	double time(time) ;
+		time:units = "seconds since 2009-01-01" ;
+	float pr(time, lat, lon) ;
+		pr:standard_name = "air_pressure_at_sea_level" ;
+		pr:units = "hPa" ;
+	float var(unlim) ;
+
+// global attributes:
+		:title = "example for workshop" ;
+data:
+
+ lat = _, _, _, _, _, _ ;
+
+ lon = _, _, _, _ ;
+
+ var = 0, 1, 3 ;
+}
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/tst_fills.c b/dap4/d4tests/src/test/data/resources/testfiles/tst_fills.c
new file mode 100644
index 0000000000..dd7844a837
--- /dev/null
+++ b/dap4/d4tests/src/test/data/resources/testfiles/tst_fills.c
@@ -0,0 +1,51 @@
+/* This is part of the netCDF package. Copyright 2008 University
+   Corporation for Atmospheric Research/Unidata See COPYRIGHT file for
+   conditions of use. See www.unidata.ucar.edu for more info.
+
+   Create a test file with default fill values for variables of each type.
+
+   $Id: tst_fills.c,v 1.12 2009/03/17 01:22:42 ed Exp $
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <netcdf.h>
+
+#define FILE_NAME "tst_fills.nc" 
+#define VAR1 "uv8"
+#  define TYPE1 NC_UBYTE
+#  define DATA1 240
+#define VAR2 "v16"
+#  define TYPE2 NC_SHORT
+#  define DATA2 32700
+#define VAR3 "uv32"
+#  define TYPE3 NC_INT
+#  define FILL3 17
+#  define DATA3 111000
+
+#define ERR abort()
+
+
+int
+main(int argc, char **argv) 
+{
+    int ncid;
+    int varid1, varid2, varid3;
+    int fill3 = FILL3;
+
+    printf("\n*** Testing fill values.\n");
+
+    if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
+    if (nc_def_var(ncid, VAR1, TYPE1, 0, NULL, &varid1)) ERR;
+    if (nc_def_var(ncid, VAR2, TYPE2, 0, NULL, &varid2)) ERR;
+    if (nc_def_var(ncid, VAR3, TYPE3, 0, NULL, &varid3)) ERR;
+      if (nc_def_var_fill(ncid, varid3, 0, &fill3)) ERR;
+    
+    if (nc_enddef(ncid)) ERR;    
+
+    {unsigned char data = DATA1; if (nc_put_var(ncid,varid1,&data)) ERR;}
+    {short data = DATA2; if (nc_put_var(ncid,varid2,&data)) ERR;}
+    {unsigned int data = DATA3; if (nc_put_var(ncid,varid3,&data)) ERR;}
+}
+
+    
diff --git a/dap4/d4tests/src/test/data/resources/testfiles/tst_fills.nc b/dap4/d4tests/src/test/data/resources/testfiles/tst_fills.nc
new file mode 100644
index 0000000000..f45e6600f6
Binary files /dev/null and b/dap4/d4tests/src/test/data/resources/testfiles/tst_fills.nc differ
diff --git a/dap4/d4tests/src/test/java/dap4/test/DapTestCommon.java b/dap4/d4tests/src/test/java/dap4/test/DapTestCommon.java
new file mode 100644
index 0000000000..64009805a5
--- /dev/null
+++ b/dap4/d4tests/src/test/java/dap4/test/DapTestCommon.java
@@ -0,0 +1,319 @@
+/* Copyright 2012, UCAR/Unidata.
+   See the LICENSE file for more information.
+*/
+
+package dap4.test;
+
+import dap4.core.data.DSPRegistry;
+import dap4.core.util.DapException;
+import dap4.core.util.DapUtil;
+import dap4.dap4lib.FileDSP;
+import org.apache.http.Header;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpVersion;
+import org.apache.http.client.methods.HttpRequestBase;
+import org.apache.http.entity.ByteArrayEntity;
+import org.apache.http.message.BasicHttpResponse;
+import org.junit.Test;
+import org.springframework.validation.Errors;
+import org.springframework.validation.Validator;
+import ucar.httpservices.HTTPMethod;
+import ucar.httpservices.HTTPUtil;
+import ucar.nc2.NetcdfFile;
+import ucar.nc2.jni.netcdf.Nc4Iosp;
+import ucar.nc2.jni.netcdf.Nc4prototypes;
+import ucar.unidata.util.test.TestDir;
+import ucar.unidata.util.test.UnitTestCommon;
+
+import javax.servlet.ServletException;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+import java.lang.invoke.MethodHandles;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.util.Collection;
+import java.util.List;
+
+abstract public class DapTestCommon extends UnitTestCommon
+{
+
+    //////////////////////////////////////////////////
+    // Constants
+
+    static final String DEFAULTTREEROOT = "dap4";
+
+    static public final String FILESERVER = "file://localhost:8080";
+
+    static public final String CONSTRAINTTAG = "dap4.ce";
+    static public final String ORDERTAG = "ucar.littleendian";
+    static public final String NOCSUMTAG = "ucar.nochecksum";
+    static public final String TRANSLATETAG = "ucar.translate";
+    static public final String TESTTAG = "ucar.testing";
+
+    static final String D4TESTDIRNAME = "d4tests";
+
+    // Equivalent to the path to the webapp/d4ts for testing purposes
+    static protected final String DFALTRESOURCEPATH = "/src/test/data/resources";
+    static protected Class NC4IOSP = ucar.nc2.jni.netcdf.Nc4Iosp.class;
+
+    static class TestFilter implements FileFilter
+    {
+        boolean debug;
+        boolean strip;
+        String[] extensions;
+
+        public TestFilter(boolean debug, String[] extensions)
+        {
+            this.debug = debug;
+            this.strip = strip;
+            this.extensions = extensions;
+        }
+
+        public boolean accept(File file)
+        {
+            boolean ok = false;
+            if(file.isFile() && file.canRead()) {
+                // Check for proper extension
+                String name = file.getName();
+                if(name != null) {
+                    for(String ext : extensions) {
+                        if(name.endsWith(ext))
+                            ok = true;
+                    }
+                }
+                if(!ok && debug)
+                    System.err.println("Ignoring: " + file.toString());
+            }
+            return ok;
+        }
+
+        static void
+        filterfiles(String path, List<String> matches, String... extensions)
+        {
+            File testdirf = new File(path);
+            assert (testdirf.canRead());
+            TestFilter tf = new TestFilter(DEBUG, extensions);
+            File[] filelist = testdirf.listFiles(tf);
+            for(int i = 0; i < filelist.length; i++) {
+                File file = filelist[i];
+                if(file.isDirectory()) continue;
+                String fname = DapUtil.canonicalpath(file.getAbsolutePath());
+                matches.add(fname);
+            }
+        }
+    }
+
+    //////////////////////////////////////////////////
+    // Static variables
+
+    static protected String dap4root = null;
+    static protected String dap4testroot = null;
+    static protected String dap4resourcedir = null;
+
+    static {
+        dap4root = locateDAP4Root(threddsroot);
+        if(dap4root == null)
+            System.err.println("Cannot locate /dap4 parent dir");
+        dap4testroot = canonjoin(dap4root, D4TESTDIRNAME);
+        dap4resourcedir = canonjoin(dap4testroot, DFALTRESOURCEPATH);
+    }
+
+    //////////////////////////////////////////////////
+    // Static methods
+
+
+    static protected String getD4TestsRoot()
+    {
+        return dap4testroot;
+    }
+
+    static protected String getResourceRoot()
+    {
+        return dap4resourcedir;
+    }
+
+    static String
+    locateDAP4Root(String threddsroot)
+    {
+        String root = threddsroot;
+        if(root != null)
+            root = root + "/" + DEFAULTTREEROOT;
+        // See if it exists
+        File f = new File(root);
+        if(!f.exists() || !f.isDirectory())
+            root = null;
+        return root;
+    }
+
+    //////////////////////////////////////////////////
+    // Instance variables
+
+
+    protected String d4tsserver = null;
+
+    protected String title = "Dap4 Testing";
+
+    public DapTestCommon()
+    {
+        this("DapTest");
+    }
+
+    public DapTestCommon(String name)
+    {
+        super(name);
+
+        this.d4tsserver = TestDir.dap4TestServer;
+        if(DEBUG)
+            System.err.println("DapTestCommon: d4tsServer=" + d4tsserver);
+    }
+
+    /**
+     * Try to get the system properties
+     */
+    protected void setSystemProperties()
+    {
+        String testargs = System.getProperty("testargs");
+        if(testargs != null && testargs.length() > 0) {
+            String[] pairs = testargs.split("[  ]*[,][  ]*");
+            for(String pair : pairs) {
+                String[] tuple = pair.split("[  ]*[=][  ]*");
+                String value = (tuple.length == 1 ? "" : tuple[1]);
+                if(tuple[0].length() > 0)
+                    System.setProperty(tuple[0], value);
+            }
+        }
+        if(System.getProperty("nodiff") != null)
+            prop_diff = false;
+        if(System.getProperty("baseline") != null)
+            prop_baseline = true;
+        if(System.getProperty("nogenerate") != null)
+            prop_generate = false;
+        if(System.getProperty("debug") != null)
+            prop_debug = true;
+        if(System.getProperty("visual") != null)
+            prop_visual = true;
+        if(System.getProperty("ascii") != null)
+            prop_ascii = true;
+        if(System.getProperty("utf8") != null)
+            prop_ascii = false;
+        if(prop_baseline && prop_diff)
+            prop_diff = false;
+        prop_controls = System.getProperty("controls", "");
+    }
+
+    //////////////////////////////////////////////////
+    // Overrideable methods
+
+    //////////////////////////////////////////////////
+    // Accessor
+
+    public void setTitle(String title)
+    {
+        this.title = title;
+    }
+
+    public String getTitle()
+    {
+        return this.title;
+    }
+
+    //////////////////////////////////////////////////
+    // Instance Utilities
+
+    public void
+    visual(String header, String captured)
+    {
+        if(!captured.endsWith("\n"))
+            captured = captured + "\n";
+        // Dump the output for visual comparison
+        System.err.println("\n"+header + ":");
+        System.err.println("---------------");
+        System.err.print(captured);
+        System.err.println("---------------");
+        System.err.flush();
+    }
+
+    protected void
+    findServer(String path)
+            throws DapException
+    {
+        String svc = "http://" + this.d4tsserver + "/d4ts";
+        if(!checkServer(svc))
+            System.err.println("D4TS Server not reachable: " + svc);
+        // Since we will be accessing it thru NetcdfDataset, we need to change the schema.
+        d4tsserver = "dap4://" + d4tsserver + "/d4ts";
+    }
+
+    //////////////////////////////////////////////////
+
+    public String getDAP4Root()
+    {
+        return this.dap4root;
+    }
+
+    @Override
+    public String getResourceDir()
+    {
+        return this.dap4resourcedir;
+    }
+
+    static protected void
+    testSetup()
+    {
+        try {
+            // Always prefer Nc4Iosp over HDF5
+            NetcdfFile.iospDeRegister(NC4IOSP);
+            NetcdfFile.registerIOProviderPreferred(NC4IOSP,
+                    ucar.nc2.iosp.hdf5.H5iosp.class
+            );
+            // Print out the library version
+            System.err.printf("Netcdf-c library version: %s%n", getCLibraryVersion());
+            System.err.flush();
+        } catch (Exception e) {
+            System.err.println("Cannot load ucar.nc2.jni.netcdf.Nc4Iosp");
+        }
+    }
+
+    static void
+    printDir(String path)
+    {
+        File testdirf = new File(path);
+        assert (testdirf.canRead());
+        File[] filelist = testdirf.listFiles();
+        System.err.println("\n*******************");
+        System.err.printf("Contents of %s:%n", path);
+        for(int i = 0; i < filelist.length; i++) {
+            File file = filelist[i];
+            String fname = file.getName();
+            System.err.printf("\t%s%s%n",
+                    fname,
+                    (file.isDirectory() ? "/" : ""));
+        }
+        System.err.println("*******************");
+        System.err.flush();
+    }
+
+    static public String
+    getCLibraryVersion()
+    {
+        Nc4prototypes nc4 = getCLibrary();
+        return (nc4 == null ? "Unknown" : nc4.nc_inq_libvers());
+    }
+
+    static public Nc4prototypes
+    getCLibrary()
+    {
+        try {
+            Method getclib = NC4IOSP.getMethod("getCLibrary");
+            return (Nc4prototypes) getclib.invoke(null);
+        } catch (NoSuchMethodException
+                | IllegalAccessException
+                | IllegalArgumentException
+                | InvocationTargetException e) {
+            return null;
+        }
+    }
+}
+
diff --git a/dap4/d4tests/src/test/java/dap4/test/Diff.j b/dap4/d4tests/src/test/java/dap4/test/Diff.j
new file mode 100644
index 0000000000..4c516837a1
--- /dev/null
+++ b/dap4/d4tests/src/test/java/dap4/test/Diff.j
@@ -0,0 +1,794 @@
+// Diff -- text file difference utility.
+// See full docu-comment at beginning of Diff class.
+
+/* Copyright (c) Ian F. Darwin, http://www.darwinsys.com/, 1996-2002.
+ * All rights reserved. Software written by Ian F. Darwin and others.
+ * $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Java, the Duke mascot, and all variants of Sun's Java 'steaming coffee cup'
+ logo are trademarks of Sun Microsystems. Sun's, and James Gosling's,
+ * pioneering role in inventing and promulgating (and standardizing) the Java
+ * language and environment is gratefully acknowledged.
+ *
+ * The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
+ * inventing predecessor languages C and C+is also gratefully acknowledged.
+ */
+
+package dap4.test;
+
+import java.io.*;
+
+
+/**
+ * This is the info kept per-file.
+ */
+class fileInfo {
+
+    static final int MAXLINECOUNT = 20000;
+
+    BufferedReader file;  /* File handle that is open for read.  */
+    public int maxLine;  /* After input done, # lines in file.  */
+    node symbol[]; /* The symtab handle of each line. */
+    int other[]; /* Map of line# to line# in other file */
+    /* ( -1 means don't-know ).            */
+    /* Allocated AFTER the lines are read. */
+
+    /**
+     * Normal constructor with one filename; file is opened and saved.
+     */
+    public fileInfo(String filename) throws Exception {
+        symbol = new node[MAXLINECOUNT + 2];
+        other = null;    // allocated later!
+        file = new BufferedReader(new FileReader(filename));
+    }
+
+    public fileInfo(Reader rdr) throws Exception {
+        symbol = new node[MAXLINECOUNT + 2];
+        other = null;    // allocated later!
+        file = new BufferedReader(rdr);
+    }
+
+    // This is done late, to be same size as # lines in input file.
+
+    void alloc() {
+        other = new int[symbol.length + 2];
+    }
+};
+
+/**
+ * diff         Text file difference utility.
+ * ----         Copyright 1987, 1989 by Donald C. Lindsay,
+ * School of Computer Science,  Carnegie Mellon University.
+ * Copyright 1982 by Symbionics.
+ * Use without fee is permitted when not for direct commercial
+ * advantage, and when credit to the source is given. Other uses
+ * require specific permission.
+ * <p/>
+ * Converted from C to Java by Ian F. Darwin, http://www.darwinsys.com/, January, 1997.
+ * Copyright 1997, Ian F. Darwin.
+ * <p/>
+ * Conversion is NOT FULLY TESTED.
+ * <p/>
+ * USAGE:      diff oldfile newfile
+ * <p/>
+ * This program assumes that "oldfile" and "newfile" are text files.
+ * The program writes to stdout a description of the changes which would
+ * transform "oldfile" into "newfile".
+ * <p/>
+ * The printout is in the form of commands, each followed by a block of
+ * text. The text is delimited by the commands, which are:
+ * <p/>
+ * DELETE AT n
+ * ..deleted lines
+ * <p/>
+ * INSERT BEFORE n
+ * ..inserted lines
+ * <p/>
+ * n MOVED TO BEFORE n
+ * ..moved lines
+ * <p/>
+ * n CHANGED FROM
+ * ..old lines
+ * CHANGED TO
+ * ..newer lines
+ * <p/>
+ * The line numbers all refer to the lines of the oldfile, as they are
+ * numbered before any commands are applied.
+ * The text lines are printed as-is, without indentation or prefixing. The
+ * commands are printed in upper case, with a prefix of ">>>>", so that
+ * they will stand out. Other schemes may be preferred.
+ * Files which contain more than MAXLINECOUNT lines cannot be processed.
+ * This can be fixed by changing "symbol" to a Vector.
+ * The algorithm is taken from Communications of the ACM, Apr78 (21, 4, 264-),
+ * "A Technique for Isolating Differences Between Files."
+ * Ignoring I/O, and ignoring the symbol table, it should take O(N) time.
+ * This implementation takes fixed space, plus O(U) space for the symbol
+ * table (where U is the number of unique lines). Methods exist to change
+ * the fixed space to O(N) space.
+ * Note that this is not the only interesting file-difference algorithm. In
+ * general, different algorithms draw different conclusions about the
+ * changes that have been made to the oldfile. This algorithm is sometimes
+ * "more right", particularly since it does not consider a block move to be
+ * an insertion and a (separate) deletion. However, on some files it will be
+ * "less right". This is a consequence of the fact that files may contain
+ * many identical lines (particularly if they are program source). Each
+ * algorithm resolves the ambiguity in its own way, and the resolution
+ * is never guaranteed to be "right". However, it is often excellent.
+ * This program is intended to be pedagogic.  Specifically, this program was
+ * the basis of the Literate Programming column which appeared in the
+ * Communications of the ACM (CACM), in the June 1989 issue (32, 6,
+ * 740-755).
+ * By "pedagogic", I do not mean that the program is gracefully worded, or
+ * that it showcases language features or its algorithm. I also do not mean
+ * that it is highly accessible to beginners, or that it is intended to be
+ * read in full, or in a particular order. Rather, this program is an
+ * example of one professional's style of keeping things organized and
+ * maintainable.
+ * The program would be better if the "print" variables were wrapped into
+ * a struct. In general, grouping related variables in this way improves
+ * documentation, and adds the ability to pass the group in argument lists.
+ * This program is a de-engineered version of a program which uses less
+ * memory and less time.  The article points out that the "symbol" arrays
+ * can be implemented as arrays of pointers to arrays, with dynamic
+ * allocation of the subarrays.  (In C, macros are very useful for hiding
+ * the two-level accesses.) In Java, a Vector would be used. This allows an
+ * extremely large value for MAXLINECOUNT, without dedicating fixed arrays.
+ * (The "other" array can be allocated after the input phase, when the exact
+ * sizes are known.) The only slow piece of code is the "strcmp" in the tree
+ * descent: it can be speeded up by keeping a hash in the tree node, and
+ * only using "strcmp" when two hashes happen to be equal.
+ * <p/>
+ * Change Log
+ * ----------
+ * 1Jan97 Ian F. Darwin: first working rewrite in Java, based entirely on
+ * D.C.Lindsay's reasonable C version.
+ * Changed comments from /***************** to /**, shortened, added
+ * whitespace, used tabs more, etc.
+ * 6jul89 D.C.Lindsay, CMU: fixed portability bug. Thanks, Gregg Wonderly.
+ * Just changed "char ch" to "int ch".
+ * Also added comment about way to improve code.
+ * 10jun89 D.C.Lindsay, CMU: posted version created.
+ * Copyright notice changed to ACM style, and Dept. is now School.
+ * ACM article referenced in docn.
+ * 26sep87 D.C.Lindsay, CMU: publication version created.
+ * Condensed all 1982/83 change log entries.
+ * Removed all command line options, and supporting code. This
+ * simplified the input code (no case reduction etc). It also
+ * simplified the symbol table, which was capable of remembering
+ * offsets into files (instead of strings), and trusting (!) hash
+ * values to be unique.
+ * Removed dynamic allocation of arrays: now fixed static arrays.
+ * Removed speed optimizations in symtab package.
+ * Removed string compression/decompression code.
+ * Recoded to Unix standards from old Lattice/MSDOS standards.
+ * (This affected only the #include's and the IO.)
+ * Some renaming of variables, and rewording of comments.
+ * 1982/83 D.C.Lindsay, Symbionics: created.
+ *
+ * @author Ian F. Darwin, Java version
+ * @author D. C. Lindsay, C version (1982-1987)
+ * @version Java version 0.9, 1997
+ */
+
+public class Diff {
+
+    /**
+     * block len > any possible real block len
+     */
+    final int UNREAL = Integer.MAX_VALUE;
+
+    /**
+     * Keeps track of information about file1 and file2
+     */
+    fileInfo oldinfo, newinfo;
+
+    PrintWriter printer = null;
+
+    String identifier = "";
+
+
+    /**
+     * blocklen is the info about found blocks. It will be set to 0, except
+     * at the line#s where blocks start in the old file. At these places it
+     * will be set to the # of lines in the block. During printout ,
+     * this # will be reset to -1 if the block is printed as a MOVE block
+     * (because the printout phase will encounter the block twice, but
+     * must only print it once.)
+     * The array declarations are to MAXLINECOUNT+2 so that we can have two
+     * extra lines (pseudolines) at line# 0 and line# MAXLINECOUNT+1
+     * (or less).
+     */
+    int blocklen[];
+
+    /**
+     * main - entry point when used standalone.
+     * NOTE: no routines return error codes or throw any local
+     * exceptions. Instead, any routine may complain
+     * to stderr and then exit with error to the system.
+     */
+    public static void main(String argstrings[]) throws Exception {
+        if (argstrings.length != 2) {
+            System.err.println("Usage: diff oldfile newfile");
+            System.exit(1);
+        }
+        Diff d = new Diff("Diff");
+        d.doDiff(argstrings[0], argstrings[1]);
+        return;
+    }
+
+    /**
+     * Construct a Diff object.
+     */
+    public Diff(String id) {
+        identifier = id;
+    }
+
+   
+    /* Do comparison against two Reader streams */
+
+    public boolean doDiff(Reader oldFile, Reader newFile, Writer out) throws Exception {
+        this.printer = new PrintWriter(out);
+        oldinfo = new fileInfo(oldFile);
+        newinfo = new fileInfo(newFile);
+        return process();
+    }
+
+    public boolean doDiff(Reader oldFile, Reader newFile) throws Exception {
+        Writer w = new OutputStreamWriter(System.out);
+        return doDiff(oldFile, newFile, w);
+    }
+
+    /* Do comparison against two string streams */
+
+     public boolean doDiff(String data1, String data2, Writer out) throws Exception {
+        if(data1 == null || data2 == null) return false;
+        return doDiff(new StringReader(data1), new StringReader(data2), out);
+    }
+
+    public boolean doDiff(String data1, String data2) throws Exception {
+        return doDiff(data1, data2, new OutputStreamWriter(System.out));
+    }
+
+    boolean process() throws Exception {
+        /* we don't process until we know both files really do exist. */
+        inputscan(oldinfo);
+        inputscan(newinfo);
+
+        /* Now that we've read all the lines, allocate some arrays.
+        */
+        blocklen = new int[(oldinfo.maxLine > newinfo.maxLine ?
+                oldinfo.maxLine : newinfo.maxLine) + 2];
+        oldinfo.alloc();
+        newinfo.alloc();
+
+        /* Now do the work, and print the results. */
+        transform();
+        return printout();
+    }
+
+    static boolean isBlankLine(String s)
+    {
+        int index = 0;
+        int len = s.length();
+        for(index=len-1;index>=0;index--) {
+            if(" \t\r".indexOf(s.charAt(index)) < 0) return false;
+        }
+        return true;
+    }
+
+    /**
+     * inputscan    Reads the file specified by pinfo.file.
+     * ---------    Places the lines of that file in the symbol table.
+     * Sets pinfo.maxLine to the number of lines found.
+     */
+    void inputscan(fileInfo pinfo) throws IOException {
+        String linebuffer;
+        pinfo.maxLine = 0;
+        while ((linebuffer = pinfo.file.readLine()) != null) {
+            if(!isBlankLine(linebuffer))
+                storeline(linebuffer, pinfo);
+        }
+    }
+
+    /**
+     * storeline    Places line into symbol table.
+     * ---------    Expects pinfo.maxLine initted: increments.
+     * Places symbol table handle in pinfo.ymbol.
+     * Expects pinfo is either oldinfo or newinfo.
+     */
+    void storeline(String linebuffer, fileInfo pinfo) {
+        int linenum = ++pinfo.maxLine;    /* note, no line zero */
+        if (linenum > fileInfo.MAXLINECOUNT) {
+            System.err.println("MAXLINECOUNT exceeded, must stop.");
+            System.exit(1);
+        }
+        pinfo.symbol[linenum] = node.addSymbol(this, linebuffer, pinfo == oldinfo, linenum);
+    }
+
+    /*
+    * transform
+    * Analyzes the file differences and leaves its findings in
+    * the global arrays oldinfo.other, newinfo.other, and blocklen.
+    * Expects both files in symtab.
+    * Expects valid "maxLine" and "symbol" in oldinfo and newinfo.
+    */
+
+    void transform() {
+        int oldline, newline;
+        int oldmax = oldinfo.maxLine + 2;  /* Count pseudolines at  */
+        int newmax = newinfo.maxLine + 2;  /* ..front and rear of file */
+
+        for (oldline = 0; oldline < oldmax; oldline++)
+            oldinfo.other[oldline] = -1;
+        for (newline = 0; newline < newmax; newline++)
+            newinfo.other[newline] = -1;
+
+        scanunique();  /* scan for lines used once in both files */
+        scanafter();   /* scan past sure-matches for non-unique blocks */
+        scanbefore();  /* scan backwards from sure-matches */
+        scanblocks();  /* find the fronts and lengths of blocks */
+    }
+
+    /*
+    * scanunique
+    * Scans for lines which are used exactly once in each file.
+    * Expects both files in symtab, and oldinfo and newinfo valid.
+    * The appropriate "other" array entries are set to the line# in
+    * the other file.
+    * Claims pseudo-lines at 0 and XXXinfo.maxLine+1 are unique.
+    */
+
+    void scanunique() {
+        int oldline, newline;
+        node psymbol;
+
+        for (newline = 1; newline <= newinfo.maxLine; newline++) {
+            psymbol = newinfo.symbol[newline];
+            if (psymbol.symbolIsUnique()) {        // 1 use in each file
+                oldline = psymbol.linenum;
+                newinfo.other[newline] = oldline; // record 1-1 map
+                oldinfo.other[oldline] = newline;
+            }
+        }
+        newinfo.other[0] = 0;
+        oldinfo.other[0] = 0;
+        newinfo.other[newinfo.maxLine + 1] = oldinfo.maxLine + 1;
+        oldinfo.other[oldinfo.maxLine + 1] = newinfo.maxLine + 1;
+    }
+
+    /*
+    * scanafter
+    * Expects both files in symtab, and oldinfo and newinfo valid.
+    * Expects the "other" arrays contain positive #s to indicate
+    * lines that are unique in both files.
+    * For each such pair of places, scans past in each file.
+    * Contiguous groups of lines that match non-uniquely are
+    * taken to be good-enough matches, and so marked in "other".
+    * Assumes each other[0] is 0.
+    */
+
+    void scanafter() {
+        int oldline, newline;
+
+        for (newline = 0; newline <= newinfo.maxLine; newline++) {
+            oldline = newinfo.other[newline];
+            if (oldline >= 0) {  /* is unique in old & new */
+                for (; ;) {  /* scan after there in both files */
+                    if (++oldline > oldinfo.maxLine) break;
+                    if (oldinfo.other[oldline] >= 0) break;
+                    if (++newline > newinfo.maxLine) break;
+                    if (newinfo.other[newline] >= 0) break;
+
+                    /* oldline & newline exist, and
+                 aren't already matched */
+
+                    if (newinfo.symbol[newline] !=
+                            oldinfo.symbol[oldline]) break;  // not same
+
+                    newinfo.other[newline] = oldline; // record a match
+                    oldinfo.other[oldline] = newline;
+                }
+            }
+        }
+    }
+
+    /**
+     * scanbefore
+     * As scanafter, except scans towards file fronts.
+     * Assumes the off-end lines have been marked as a match.
+     */
+    void scanbefore() {
+        int oldline, newline;
+
+        for (newline = newinfo.maxLine + 1; newline > 0; newline--) {
+            oldline = newinfo.other[newline];
+            if (oldline >= 0) {               /* unique in each */
+                for (; ;) {
+                    if (--oldline <= 0) break;
+                    if (oldinfo.other[oldline] >= 0) break;
+                    if (--newline <= 0) break;
+                    if (newinfo.other[newline] >= 0) break;
+
+                    /* oldline and newline exist,
+                and aren't marked yet */
+
+                    if (newinfo.symbol[newline] !=
+                            oldinfo.symbol[oldline]) break;  // not same
+
+                    newinfo.other[newline] = oldline; // record a match
+                    oldinfo.other[oldline] = newline;
+                }
+            }
+        }
+    }
+
+    /**
+     * scanblocks - Finds the beginnings and lengths of blocks of matches.
+     * Sets the blocklen array (see definition).
+     * Expects oldinfo valid.
+     */
+    void scanblocks() {
+        int oldline, newline;
+        int oldfront = 0;      // line# of front of a block in old, or 0
+        int newlast = -1;      // newline's value during prev. iteration
+
+        for (oldline = 1; oldline <= oldinfo.maxLine; oldline++)
+            blocklen[oldline] = 0;
+        blocklen[oldinfo.maxLine + 1] = UNREAL; // starts a mythical blk
+
+        for (oldline = 1; oldline <= oldinfo.maxLine; oldline++) {
+            newline = oldinfo.other[oldline];
+            if (newline < 0) oldfront = 0;  /* no match: not in block */
+            else {                                   /* match. */
+                if (oldfront == 0) oldfront = oldline;
+                if (newline != (newlast + 1)) oldfront = oldline;
+                ++blocklen[oldfront];
+            }
+            newlast = newline;
+        }
+    }
+
+    /* The following are global to printout's subsidiary routines */
+    // enum{ idle, delete, insert, movenew, moveold,
+    // same, change } printstatus;
+    public static final int
+            idle = 0, delete = 1, insert = 2, movenew = 3, moveold = 4,
+            same = 5, change = 6;
+    int printstatus;
+    boolean anyprinted;
+    int printoldline, printnewline;     // line numbers in old & new file
+
+    /**
+     * printout - Prints summary to stdout.
+     * Expects all databuffer structures have been filled out.
+     *
+     * @return true if differences detected
+     */
+    boolean printout() {
+        printstatus = idle;
+        anyprinted = false;
+        for (printoldline = printnewline = 1; ;) {
+            if (printoldline > oldinfo.maxLine) {
+                newconsume();
+                break;
+            }
+            if (printnewline > newinfo.maxLine) {
+                oldconsume();
+                break;
+            }
+            if (newinfo.other[printnewline] < 0) {
+                if (oldinfo.other[printoldline] < 0)
+                    showchange();
+                else
+                    showinsert();
+            } else if (oldinfo.other[printoldline] < 0)
+                showdelete();
+            else if (blocklen[printoldline] < 0)
+                skipold();
+            else if (oldinfo.other[printoldline] == printnewline)
+                showsame();
+            else
+                showmove();
+        }
+        if (anyprinted == true) println(">>>> "+identifier+": End of differences.");
+        else println(">>>> "+identifier+": Files are identical.");
+        return anyprinted;
+    }
+
+    /*
+    * newconsume        Part of printout. Have run out of old file.
+    * Print the rest of the new file, as inserts and/or moves.
+    */
+
+    void newconsume() {
+        for (; ;) {
+            if (printnewline > newinfo.maxLine)
+                break;        /* end of file */
+            if (newinfo.other[printnewline] < 0) showinsert();
+            else showmove();
+        }
+    }
+
+    /**
+     * oldconsume        Part of printout. Have run out of new file.
+     * Process the rest of the old file, printing any
+     * parts which were deletes or moves.
+     */
+    void oldconsume() {
+        for (; ;) {
+            if (printoldline > oldinfo.maxLine)
+                break;       /* end of file */
+            printnewline = oldinfo.other[printoldline];
+            if (printnewline < 0) showdelete();
+            else if (blocklen[printoldline] < 0) skipold();
+            else showmove();
+        }
+    }
+
+    /**
+     * showdelete        Part of printout.
+     * Expects printoldline is at a deletion.
+     */
+    void showdelete() {
+        if (printstatus != delete)
+            println(">>>> DELETE AT " + printoldline);
+        printstatus = delete;
+        oldinfo.symbol[printoldline].showSymbol();
+        anyprinted = true;
+        printoldline++;
+    }
+
+    /*
+    * showinsert        Part of printout.
+    * Expects printnewline is at an insertion.
+    */
+
+    void showinsert() {
+        if (printstatus == change) println(">>>>     CHANGED TO");
+        else if (printstatus != insert)
+            println(">>>> INSERT BEFORE " + printoldline);
+        printstatus = insert;
+        newinfo.symbol[printnewline].showSymbol();
+        anyprinted = true;
+        printnewline++;
+    }
+
+    /**
+     * showchange        Part of printout.
+     * Expects printnewline is an insertion.
+     * Expects printoldline is a deletion.
+     */
+    void showchange() {
+        if (printstatus != change)
+            println(">>>> " + printoldline + " CHANGED FROM");
+        printstatus = change;
+        oldinfo.symbol[printoldline].showSymbol();
+        anyprinted = true;
+        printoldline++;
+    }
+
+    /**
+     * skipold           Part of printout.
+     * Expects printoldline at start of an old block that has
+     * already been announced as a move.
+     * Skips over the old block.
+     */
+    void skipold() {
+        printstatus = idle;
+        for (; ;) {
+            if (++printoldline > oldinfo.maxLine)
+                break;     /* end of file  */
+            if (oldinfo.other[printoldline] < 0)
+                break;    /* end of block */
+            if (blocklen[printoldline] != 0)
+                break;          /* start of another */
+        }
+    }
+
+    /**
+     * skipnew           Part of printout.
+     * Expects printnewline is at start of a new block that has
+     * already been announced as a move.
+     * Skips over the new block.
+     */
+    void skipnew() {
+        int oldline;
+        printstatus = idle;
+        for (; ;) {
+            if (++printnewline > newinfo.maxLine)
+                break;    /* end of file  */
+            oldline = newinfo.other[printnewline];
+            if (oldline < 0)
+                break;                         /* end of block */
+            if (blocklen[oldline] != 0)
+                break;              /* start of another */
+        }
+    }
+
+    /**
+     * showsame          Part of printout.
+     * Expects printnewline and printoldline at start of
+     * two blocks that aren't to be displayed.
+     */
+    void showsame() {
+        int count;
+        printstatus = idle;
+        if (newinfo.other[printnewline] != printoldline) {
+            System.err.println("BUG IN LINE REFERENCING");
+            System.exit(1);
+        }
+        count = blocklen[printoldline];
+        printoldline += count;
+        printnewline += count;
+    }
+
+    /**
+     * showmove          Part of printout.
+     * Expects printoldline, printnewline at start of
+     * two different blocks ( a move was done).
+     */
+    void showmove() {
+        int oldblock = blocklen[printoldline];
+        int newother = newinfo.other[printnewline];
+        int newblock = blocklen[newother];
+
+        if (newblock < 0) skipnew();         // already printed.
+        else if (oldblock >= newblock) {     // assume new's blk moved.
+            blocklen[newother] = -1;         // stamp block as "printed".
+            println(">>>> " + newother +
+                    " THRU " + (newother + newblock - 1) +
+                    " MOVED TO BEFORE " + printoldline);
+            for (; newblock > 0; newblock--, printnewline++)
+                newinfo.symbol[printnewline].showSymbol();
+            anyprinted = true;
+            printstatus = idle;
+
+        } else                /* assume old's block moved */
+            skipold();      /* target line# not known, display later */
+    }
+
+    /**
+     * Convenience wrapper for println
+     */
+    public void println(String s) {
+        printer.println(s);
+        printer.flush();
+    }
+
+};        // end of main class!
+
+/**
+ * Class "node". The symbol table routines in this class all
+ * understand the symbol table format, which is a binary tree.
+ * The methods are: addSymbol, symbolIsUnique, showSymbol.
+ */
+class node {                       /* the tree is made up of these nodes */
+
+    static Diff diff = null;
+    static node panchor = null;    /* symtab is a tree hung from this */
+    static final int freshnode = 0,
+            oldonce = 1, newonce = 2, bothonce = 3, other = 4;
+
+    node pleft, pright;
+    int linenum;
+    int /* enum linestates */ linestate;
+    String line;
+
+    /**
+     * Construct a new symbol table node and fill in its fields.
+     *
+     * @param pline string  A line of the text file
+     */
+    public node(String pline) {
+        pleft = pright = null;
+        linestate = freshnode;
+        /* linenum field is not always valid */
+        line = pline;
+    }
+
+    /**
+     * matchsymbol       Searches tree for a match to the line.
+     *
+     * @param pline String  pline, a line of text
+     *              If node's linestate == freshnode, then created the node.
+     */
+    static node matchsymbol(String pline) {
+        int comparison;
+        node pnode = panchor;
+        if (panchor == null) return panchor = new node(pline);
+        for (; ;) {
+            comparison = linecompare(pnode.line,pline);
+            if (comparison == 0) return pnode;          /* found */
+
+            if (comparison < 0) {
+                if (pnode.pleft == null) {
+                    pnode.pleft = new node(pline);
+                    return pnode.pleft;
+                }
+                pnode = pnode.pleft;
+            }
+            if (comparison > 0) {
+                if (pnode.pright == null) {
+                    pnode.pright = new node(pline);
+                    return pnode.pright;
+                }
+                pnode = pnode.pright;
+            }
+        }
+        /* NOTE: There are return stmts, so control does not get here. */
+    }
+
+    /**
+     * addSymbol(String pline) - Saves line into the symbol table.
+     * Returns a handle to the symtab entry for that unique line.
+     * If inoldfile nonzero, then linenum is remembered.
+     */
+    static node addSymbol(Diff diff, String pline, boolean inoldfile, int linenum) {
+        node.diff = diff;
+        node pnode;
+        pnode = matchsymbol(pline);  /* find the node in the tree */
+        if (pnode.linestate == freshnode) {
+            pnode.linestate = inoldfile ? oldonce : newonce;
+        } else {
+            if ((pnode.linestate == oldonce && !inoldfile) ||
+                    (pnode.linestate == newonce && inoldfile))
+                pnode.linestate = bothonce;
+            else pnode.linestate = other;
+        }
+        if (inoldfile) pnode.linenum = linenum;
+        return pnode;
+    }
+
+    /**
+     * symbolIsUnique    Arg is a ptr previously returned by addSymbol.
+     * --------------    Returns true if the line was added to the
+     * symbol table exactly once with inoldfile true,
+     * and exactly once with inoldfile false.
+     */
+    boolean symbolIsUnique() {
+        return (linestate == bothonce);
+    }
+
+    /**
+     * showSymbol        Prints the line to stdout.
+     */
+    void showSymbol() {
+        diff.printer.println(line);
+    }
+    static String compact(String line){
+        // trim and remove return characters
+        String[] pieces = line.trim().split("\r");
+        line = ""; for(String s: pieces) line = line +s;
+        // Break line on whitespace and compact
+        pieces = line.split("[ \t\n][ \t\n]*");
+        line = ""; for(String s: pieces) line = line + s;
+        return line;
+    }
+
+    static int linecompare(String line1, String line2)
+    {
+       return compact(line1).compareToIgnoreCase(compact(line2));
+    }
+
+}
diff --git a/dap4/d4tests/src/test/java/dap4/test/Dump.java b/dap4/d4tests/src/test/java/dap4/test/Dump.java
new file mode 100644
index 0000000000..e969c4ea74
--- /dev/null
+++ b/dap4/d4tests/src/test/java/dap4/test/Dump.java
@@ -0,0 +1,266 @@
+/* Copyright 2012, UCAR/Unidata.
+   See the LICENSE file for more information.
+*/
+
+
+package dap4.test;
+
+import dap4.core.util.DapUtil;
+import dap4.core.util.Escape;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+public class Dump
+{
+
+    //////////////////////////////////////////////////
+    // Constants
+
+    static public boolean DUMPCSUM = false;
+
+    static final String LBRACE = "{";
+    static final String RBRACE = "}";
+
+    static final BigInteger MASK = new BigInteger("FFFFFFFFFFFFFFFF", 16);
+
+    //////////////////////////////////////////////////
+    // Type decls
+
+    // Place to insert the command list
+    static public interface Commands
+    {
+        public void run(Dump printer) throws IOException;
+    }
+
+    //////////////////////////////////////////////////
+    // Instance databuffer
+
+    protected ByteBuffer reader = null;
+    protected boolean checksumming = true;
+    protected ByteOrder remoteorder = null;
+    protected StringBuilder buf = null;
+    protected java.util.zip.Checksum localchecksum;
+    protected int lastchecksum = 0;
+
+    //////////////////////////////////////////////////
+    // Constructor(s)
+
+    public Dump()
+    {
+    }
+
+    //////////////////////////////////////////////////
+    // Command processing
+
+    public String
+    dumpdata(InputStream stream, boolean checksumming, ByteOrder remoteorder, Commands commands)
+            throws IOException
+    {
+        // Hack for debugging; use a bytebuffer internally
+        this.reader = ByteBuffer.wrap(DapUtil.readbinaryfile(stream));
+        this.checksumming = checksumming;
+        this.remoteorder = remoteorder;
+        this.buf = new StringBuilder();
+        commands.run(this);
+        return this.buf.toString();
+    }
+
+    public int
+    printcount()
+            throws IOException
+    {
+        ByteBuffer bytes = checksum(8);
+        long l = bytes.getLong();
+        buf.append(String.format("count=%d%n", l));
+        return (int) l;
+    }
+
+    public void
+    printvalue(char cmd, int typesize, int... indices)
+            throws IOException
+    {
+        long l = 0;
+        ByteBuffer bytes = null;
+        // for strings and opaque, the typesize is zero
+        if(typesize == 0) {
+            bytes = checksum(8);
+            l = bytes.getLong();
+            bytes = checksum((int) l);
+        } else
+            bytes = checksum(typesize);
+        if(indices != null && indices.length > 0) {
+            for(int index : indices) {
+                buf.append(" [" + Integer.toString(index) + "]");
+            }
+        }
+        buf.append(" ");
+        int switcher = (((int) cmd) << 4) + typesize;
+        switch (switcher) {
+        case ('S' << 4) + 1:
+            byte b = bytes.get();
+            l = ((long) b);
+            buf.append(String.format("%d", l));
+            break;
+        case ('U' << 4) + 1:
+            b = bytes.get();
+            l = ((long) b) & 0xFF;
+            buf.append(String.format("%d", l));
+            break;
+        case ('C' << 4) + 0:
+        case ('C' << 4) + 1:
+            l = ((long) bytes.get()) & 0x7F;
+            buf.append(String.format("'%c'", (char) (l & 0xFF)));
+            break;
+        case ('S' << 4) + 2:
+            short s = bytes.getShort();
+            l = ((long) s);
+            buf.append(String.format("%d", l));
+            break;
+        case ('U' << 4) + 2:
+            s = bytes.getShort();
+            l = ((long) s) & 0xFFFFL;
+            buf.append(String.format("%d", l));
+            break;
+        case ('S' << 4) + 4:
+            int i = bytes.getInt();
+            l = ((long) i);
+            buf.append(String.format("%d", l));
+            break;
+        case ('U' << 4) + 4:
+            i = bytes.getInt();
+            l = ((long) i) & 0xFFFFFFFFL;
+            buf.append(String.format("%d", l));
+            break;
+        case ('S' << 4) + 8:
+            l = bytes.getLong();
+            l = ((long) l);
+            buf.append(String.format("%d", l));
+            break;
+        case ('U' << 4) + 8: // We have to convert to BigInteger to get this right
+            l = bytes.getLong();
+            l = ((long) l);
+            BigInteger big = BigInteger.valueOf(l);
+            big = big.and(MASK);
+            buf.append(String.format("%s", big.toString()));
+            break;
+        case ('F' << 4) + 4:
+            Float f = bytes.getFloat();
+            buf.append(String.format("%g", f));
+            break;
+        case ('F' << 4) + 8:
+            Double d = bytes.getDouble();
+            buf.append(String.format("%g", d));
+            break;
+        case ('T' << 4) + 0:
+            // Read the text
+            buf.append('"' + Escape.backslashEscape(new String(bytes.array(), DapUtil.UTF8), "\"") + '"');
+            break;
+        case ('O' << 4) + 0:
+            buf.append("0x");
+            for(i = 0; i < bytes.limit(); i++) {
+                int uint8 = bytes.get();
+                char c = hexchar((uint8 >> 4) & 0xF);
+                buf.append(c);
+                c = hexchar((uint8) & 0xF);
+                buf.append(c);
+            }
+            break;
+        default:
+            assert false;
+        }
+    }
+
+    public void
+    verifychecksum()
+            throws IOException
+    {
+        if(!checksumming)
+            return;
+        int localcrc32 = endchecksum();
+        // Get the checksum from the input stream
+        ByteBuffer bbuf = readn(DapUtil.CHECKSUMSIZE);
+        int remotecrc32 = bbuf.getInt();
+        assert localcrc32 == remotecrc32;
+        newline();
+    }
+
+    public void
+    newline()
+    {
+        buf.append("\n");
+    }
+
+    public void
+    startchecksum()
+    {
+        if(this.localchecksum == null)
+            this.localchecksum = new java.util.zip.CRC32();
+        this.localchecksum.reset();
+    }
+
+    protected int
+    endchecksum()
+    {
+        long crc = this.localchecksum.getValue(); // get the digest value
+        crc = (crc & 0x00000000FFFFFFFFL); /* crc is 32 bits */
+        this.lastchecksum = (int) crc;
+        return this.lastchecksum;
+    }
+
+    protected byte[]
+    readnbytes(int n)
+            throws IOException
+    {
+        byte[] bytes = new byte[n];
+        try {
+            this.reader.get(bytes);
+        } catch (BufferUnderflowException e) {
+            throw new IOException("Short DATADMR");
+        }
+        return bytes;
+    }
+
+    protected ByteBuffer
+    readn(int n)
+            throws IOException
+    {
+        byte[] bytes = readnbytes(n);
+        ByteBuffer result = ByteBuffer.wrap(bytes).order(this.remoteorder);
+        return result;
+    }
+
+    protected ByteBuffer
+    checksum(int n)
+            throws IOException
+    {
+        byte[] bytes = readnbytes(n);
+        localchecksum.update(bytes, 0, n);
+        if(DUMPCSUM) {
+            System.err.print("CCC ");
+            for(int i = 0; i < n; i++) {
+                System.err.printf("%02x", bytes[i]);
+            }
+            System.err.println();
+        }
+        ByteBuffer result = ByteBuffer.wrap(bytes).order(this.remoteorder);
+        return result;
+    }
+
+    public void
+    format(String s)
+    {
+        buf.append(String.format(s));
+    }
+
+    char
+    hexchar(int i)
+    {
+        return "0123456789ABCDEF".charAt((i & 0xF));
+    }
+
+}
diff --git a/dap4/d4tests/src/test/java/dap4/test/TestCDMClient.java b/dap4/d4tests/src/test/java/dap4/test/TestCDMClient.java
new file mode 100644
index 0000000000..6de97fb4c5
--- /dev/null
+++ b/dap4/d4tests/src/test/java/dap4/test/TestCDMClient.java
@@ -0,0 +1,366 @@
+/* Copyright 2016, University Corporation for Atmospheric Research
+   See the LICENSE.txt file for more information.
+*/
+
+package dap4.test;
+
+import dap4.core.util.DapUtil;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import ucar.nc2.dataset.NetcdfDataset;
+import ucar.unidata.util.test.TestDir;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.lang.invoke.MethodHandles;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Test Client side access
+ */
+
+public class TestCDMClient extends DapTestCommon
+{
+    private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+    static final boolean DEBUG = false;
+
+    //////////////////////////////////////////////////
+    // Constants
+
+    static final String BASEEXTENSION = ".txt";
+    static final String INPUTEXTENSION = ".raw";
+
+    static final String DAP4TAG = "#protocol=dap4";
+
+    static final String DATADIR = "src/test/data/resources"; // relative to dap4 root
+    static final String BASELINEDIR = "TestCDMClient/baseline";
+    static final String TESTCDMINPUT = "TestCDMClient/testinput";
+    static final String TESTFILESINPUT = "testfiles";
+
+    static final String[] EXCLUDEDFILETESTS = new String[]{
+            "test_sequence_2.syn.raw"
+    };
+
+    //////////////////////////////////////////////////
+    // Type Declarations
+
+    static class TestCase
+    {
+        static private String root = null;
+
+        static void setRoot(String r)
+        {
+            root = r;
+        }
+
+        static String getRoot()
+        {
+            return root;
+        }
+
+        /////////////////////////
+
+        private String title;
+        private String dataset;
+        private String ext;
+        private boolean checksumming;
+        private String testpath;
+        private String baselinepath;
+        private String url;
+
+        TestCase(String url)
+        {
+            this(url, true);
+        }
+
+        TestCase(String url, boolean csum)
+        {
+            try {
+                URL u = new URL(url);
+                this.title = u.getPath();
+            } catch (MalformedURLException e) {
+                this.title = "unknown";
+            }
+            this.checksumming = csum;
+            this.url = url;
+            try {
+                URL u = new URL(url);
+                this.testpath = DapUtil.canonicalpath(u.getPath());
+                int i = this.testpath.lastIndexOf('/');
+                assert i > 0;
+                this.dataset = this.testpath.substring(i + 1, this.testpath.length());
+                // strip off any raw extension
+                if(this.dataset.endsWith(INPUTEXTENSION))
+                    this.dataset = this.dataset.substring(0,this.dataset.length() - INPUTEXTENSION.length());
+                this.baselinepath = root + "/" + BASELINEDIR + "/" + this.dataset + INPUTEXTENSION + BASEEXTENSION;
+            } catch (MalformedURLException e) {
+                throw new IllegalArgumentException(url);
+            }
+        }
+
+        public String getURL()
+        {
+            return this.url + DAP4TAG;
+        }
+
+        public String getPath()
+        {
+            return this.testpath;
+        }
+
+        public String getDataset()
+        {
+            return this.dataset;
+        }
+
+        public String getBaseline()
+        {
+            return this.baselinepath;
+        }
+
+        public String getTitle()
+        {
+            return this.title;
+        }
+
+        public String toString()
+        {
+            return this.url;
+        }
+    }
+
+    //////////////////////////////////////////////////
+    // Instance variables
+
+    // Test cases
+
+    protected List<TestCase> alltestcases = new ArrayList<TestCase>();
+    protected List<TestCase> chosentests = new ArrayList<TestCase>();
+
+    protected String resourceroot = null;
+
+    //////////////////////////////////////////////////
+
+    @Before
+    public void setup() throws Exception
+    {
+        testSetup();
+        this.resourceroot = getResourceRoot();
+        TestCase.setRoot(resourceroot);
+        defineAllTestcases();
+        chooseTestcases();
+    }
+
+    // convert an extension to a file or url prefix
+    String
+    prefix(String scheme, String ext)
+    {
+        if(ext.charAt(0) == '.') ext = ext.substring(1);
+        if(scheme.startsWith("http")) {
+            return "http://"
+                    + TestDir.dap4TestServer
+                    + "/d4ts";
+        } else if(scheme.equals("file")) {
+            if(ext.equals("raw"))
+                return "file:/"
+                        + this.resourceroot
+                        + "/"
+                        + TESTCDMINPUT;
+        }
+        throw new IllegalArgumentException();
+    }
+
+    //////////////////////////////////////////////////
+    // Define test cases
+
+    void
+    chooseTestcases()
+    {
+        if(false) {
+            chosentests = locate("file:", "test_atomic_array.nc.raw");
+            prop_visual = true;
+            prop_baseline = false;
+        } else {
+            prop_baseline = false;
+            for(TestCase tc : alltestcases) {
+                chosentests.add(tc);
+            }
+        }
+    }
+
+    void
+    defineAllTestcases()
+    {
+        System.err.printf("pwd=%s%n", System.getProperty("user.dir"));
+        List<String> matches = new ArrayList<>();
+        String dir = TestCase.getRoot() + "/" + TESTCDMINPUT;
+        TestFilter.filterfiles(dir, matches, "raw");
+        for(String f : matches) {
+            boolean excluded = false;
+            for(String x : EXCLUDEDFILETESTS) {
+                if(f.endsWith(x)) {
+                    excluded = true;
+                    break;
+                }
+            }
+            if(!excluded) {
+                add(f);
+            }
+        }
+    }
+
+    protected void
+    add(String path)
+    {
+        File f = new File(path);
+        if(!f.exists())
+            System.err.println("Non existent file test case: " + path);
+        else if(!f.canRead())
+            System.err.println("Unreadable file test case: " + path);
+        String ext = path.substring(path.lastIndexOf('.'), path.length());
+        String url = "file://"+path;
+        try {
+            URL u = new URL(url);
+            System.err.printf("Testcase: add: %s  path=%s%n",u.toString(),u.getPath());
+        } catch (MalformedURLException e) {
+            System.err.println("Malformed file test case: " + url);
+        }
+        TestCase tc = new TestCase(url);
+        for(TestCase t: this.alltestcases) {
+            assert !t.getURL().equals(tc.getURL()) : "Duplicate TestCases: " + t;
+        }
+        this.alltestcases.add(tc);
+    }
+
+    //////////////////////////////////////////////////
+    // Junit test method
+    @Test
+    public void testCDMClient()
+            throws Exception
+    {
+        for(TestCase testcase : chosentests) {
+            doOneTest(testcase);
+        }
+        System.err.println("*** PASS");
+    }
+
+    //////////////////////////////////////////////////
+    // Primary test method
+    void
+    doOneTest(TestCase testcase)
+            throws Exception
+    {
+        System.err.println("Testcase: " + testcase.getURL());
+        System.err.println("Baseline: " + testcase.getBaseline());
+
+        NetcdfDataset ncfile;
+        try {
+            ncfile = openDataset(testcase.getURL());
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new Exception("File open failed: " + testcase.getURL(), e);
+        }
+        assert ncfile != null;
+
+        String datasetname = testcase.getDataset();
+        String data = dumpdata(ncfile, datasetname);
+
+        if(prop_visual) {
+            visual(testcase.getTitle() + ".dap", data);
+        }
+        String baselinefile = testcase.getBaseline();
+
+        if(prop_baseline)
+            writefile(baselinefile, data);
+        else if(prop_diff) { //compare with baseline
+            // Read the baseline file(s)
+            String baselinecontent = readfile(baselinefile);
+            System.err.println("Comparison: vs " + baselinefile);
+            Assert.assertTrue("*** FAIL", same(getTitle(), baselinecontent, data));
+        }
+    }
+
+    String dumpmetadata(NetcdfDataset ncfile, String datasetname)
+            throws Exception
+    {
+        StringWriter sw = new StringWriter();
+        StringBuilder args = new StringBuilder("-strict");
+        if(datasetname != null) {
+            args.append(" -datasetname ");
+            args.append(datasetname);
+        }
+        // Print the meta-databuffer using these args to NcdumpW
+        try {
+            if(!ucar.nc2.NCdumpW.print(ncfile, args.toString(), sw, null))
+                throw new Exception("NcdumpW failed");
+        } catch (IOException ioe) {
+            throw new Exception("NcdumpW failed", ioe);
+        }
+        sw.close();
+        return sw.toString();
+    }
+
+    String dumpdata(NetcdfDataset ncfile, String datasetname)
+            throws Exception
+    {
+        StringBuilder args = new StringBuilder("-strict -vall");
+        if(datasetname != null) {
+            args.append(" -datasetname ");
+            args.append(datasetname);
+        }
+        StringWriter sw = new StringWriter();
+        // Dump the databuffer
+        sw = new StringWriter();
+        try {
+            if(!ucar.nc2.NCdumpW.print(ncfile, args.toString(), sw, null))
+                throw new Exception("NCdumpW failed");
+        } catch (IOException ioe) {
+            ioe.printStackTrace();
+            throw new Exception("NCdumpW failed", ioe);
+        }
+        sw.close();
+        return sw.toString();
+    }
+
+    //////////////////////////////////////////////////
+    // Utility methods
+
+    //Locate the test cases with given prefix
+    List<TestCase>
+    locate(String scheme, String s)
+    {
+        return locate(scheme, s, null);
+    }
+
+    List<TestCase>
+    locate(String scheme, String s, List<TestCase> list)
+    {
+        if(list == null) list = new ArrayList<>();
+        int matches = 0;
+        for(TestCase ct : this.alltestcases) {
+            if(!ct.getURL().startsWith(scheme)) continue;
+            if(ct.getPath().endsWith(s)) {
+                matches++;
+                list.add(ct);
+            }
+        }
+        assert matches > 0 : "No such testcase: " + s;
+        return list;
+    }
+
+    static boolean
+    report(String msg)
+    {
+        System.err.println(msg);
+        return false;
+    }
+
+}
diff --git a/dap4/d4tests/src/test/java/dap4/test/TestDSP.java b/dap4/d4tests/src/test/java/dap4/test/TestDSP.java
new file mode 100644
index 0000000000..cac57f7760
--- /dev/null
+++ b/dap4/d4tests/src/test/java/dap4/test/TestDSP.java
@@ -0,0 +1,399 @@
+package dap4.test;
+
+import dap4.core.data.DSP;
+import dap4.core.util.DapContext;
+import dap4.core.util.DapUtil;
+import dap4.dap4lib.DMRPrinter;
+import dap4.dap4lib.DSPPrinter;
+import dap4.dap4lib.FileDSP;
+import dap4.dap4lib.HttpDSP;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import ucar.unidata.util.test.TestDir;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.invoke.MethodHandles;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Test some of the DSP classes:
+ * AbstractDSP: tested by all the other DSPs
+ * CDMDSP: tested elsewhere (TestServlet)
+ * HttpDSP: tested elsewhere (TestCDMClient)
+ * FileDSP: tested here
+ * Nc4DSP: tested here
+ * SynDSP: tested here
+ * D4DSP: tested because superclass of FileDSP, HttpDSP, and SynDSP
+ * ThreddsDSP: not directly tested anywhere yet
+ */
+public class TestDSP extends DapTestCommon
+{
+    private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+    static final boolean DEBUG = false;
+    static final boolean SHOWTESTCASES = true;
+
+    static final String BASEEXTENSION = "txt";
+
+    static final String DAP4TAG = "#protocol=dap4";
+
+    //////////////////////////////////////////////////
+    // Constants
+
+    static final String DATADIR = "src/test/data/resources"; // relative to dap4 root
+    static final String BASELINEDIR = "TestDSP/baseline";
+    static final String TESTCDMINPUT = "TestCDMClient/testinput";
+    static final String TESTDSPINPUT = "TestDSP/testinput";
+    static final String TESTFILESINPUT = "testfiles";
+
+    static final String[] EXCLUDEDFILETESTS = new String[]{
+    };
+
+    //////////////////////////////////////////////////
+    // Type Declarations
+
+    static class TestCase
+    {
+        static protected String root = null;
+
+        static void setRoot(String r)
+        {
+            root = r;
+        }
+
+        static String getRoot()
+        {
+            return root;
+        }
+
+        /////////////////////////
+
+        private String title;
+        private String dataset;
+        private boolean checksumming;
+        private String testpath;
+        private String baselinepath;
+        private String url;
+
+        TestCase(String url)
+        {
+            this(url, true);
+        }
+
+        TestCase(String url, boolean csum)
+        {
+            this.title = dataset;
+            this.checksumming = csum;
+            this.url = url;
+            try {
+                URL u = new URL(url);
+                this.testpath = DapUtil.canonicalpath(u.getPath());
+                int i = this.testpath.lastIndexOf('/');
+                assert i > 0;
+                this.dataset = this.testpath.substring(i + 1, this.testpath.length());
+                // strip off any raw extension
+                this.baselinepath = root + "/" + BASELINEDIR + "/" + this.dataset + "." + BASEEXTENSION;
+            } catch (MalformedURLException e) {
+                throw new IllegalArgumentException(url);
+            }
+        }
+
+        public String getURL()
+        {
+            return this.url + DAP4TAG;
+        }
+
+        public String getPath()
+        {
+            return this.testpath;
+        }
+
+        public String getDataset()
+        {
+            return this.dataset;
+        }
+
+        public String getBaseline()
+        {
+            return this.baselinepath;
+        }
+
+        public String getTitle()
+        {
+            return this.title;
+        }
+
+        public String toString()
+        {
+            return this.url;
+        }
+    }
+
+    //////////////////////////////////////////////////
+    // Static variables and methods
+
+    protected DSP
+    dspFor(String surl)
+    {
+        URL url;
+        try {
+            url = new URL(surl);
+        } catch (MalformedURLException mue) {
+            throw new IllegalArgumentException("Malformed url: " + surl);
+        }
+        String proto = url.getProtocol();
+        String path = url.getPath();
+        int dot = path.lastIndexOf('.');
+        if(dot < 0) dot = path.length();
+        String ext = path.substring(dot, path.length());
+        DSP dsp = null;
+        if("file".equals(proto)) {
+            // discriminate on the extensions
+            if(".raw".equals(ext)) {
+                dsp = new FileDSP();
+            }
+        } else if("http".equals(proto)
+                || "https".equals(url.getProtocol())) {
+            dsp = new HttpDSP();
+        } else
+            throw new IllegalArgumentException("Cannot determine DSP class for: " + surl);
+        if(DEBUG)
+            System.err.printf("DSP: %s%n", dsp.getClass().getName());
+        return dsp;
+    }
+    //////////////////////////////////////////////////
+    // Instance variables
+
+    // Test cases
+
+    protected List<TestCase> alltestcases = new ArrayList<TestCase>();
+    protected List<TestCase> chosentests = new ArrayList<TestCase>();
+
+    protected String resourceroot = null;
+
+    //////////////////////////////////////////////////
+
+    @Before
+    public void setup() throws Exception
+    {
+        this.resourceroot = getResourceRoot();
+        this.resourceroot = DapUtil.absolutize(this.resourceroot); // handle problem of windows paths
+        TestCase.setRoot(resourceroot);
+        defineAllTestcases();
+        chooseTestcases();
+    }
+
+    // convert an extension to a file or url prefix
+    String
+    prefix(String scheme, String ext)
+    {
+        if(ext.charAt(0) == '.') ext = ext.substring(1);
+        if(scheme.startsWith("http")) {
+            return "http://"
+                    + TestDir.dap4TestServer
+                    + "/d4ts";
+        } else if(scheme.equals("file")) {
+            if(ext.equals("raw"))
+                return "file:/"
+                        + this.resourceroot
+                        + "/"
+                        + TESTCDMINPUT;
+            if(ext.equals("syn"))
+                return "file:/"
+                        + this.resourceroot
+                        + "/"
+                        + TESTDSPINPUT;
+            if(ext.equals("nc"))
+                return "file:/"
+                        + this.resourceroot
+                        + "/"
+                        + TESTFILESINPUT;
+        }
+        throw new IllegalArgumentException();
+    }
+
+    //////////////////////////////////////////////////
+    // Define test cases
+
+    void
+    chooseTestcases()
+    {
+        if(false) {
+            chosentests = locate("file:", "test_struct_nested3.hdf5.raw");
+            prop_visual = true;
+            prop_baseline = false;
+        } else {
+            prop_baseline = false;
+            for(TestCase tc : alltestcases) {
+                if(DEBUG)
+                    System.err.printf("Test case: %s%n", tc.dataset);
+                chosentests.add(tc);
+            }
+        }
+    }
+
+    void
+    defineAllTestcases()
+    {
+        List<String> matches = new ArrayList<>();
+        String dir = TestCase.root + "/" + TESTCDMINPUT;
+        TestFilter.filterfiles(dir, matches, "raw");
+        if(false) {
+            dir = TestCase.root + "/" + TESTFILESINPUT;
+            TestFilter.filterfiles(dir, matches, "nc", "syn");
+        }
+        for(String f : matches) {
+            boolean excluded = false;
+            for(String x : EXCLUDEDFILETESTS) {
+                if(f.indexOf(x) >= 0) {
+                    excluded = true;
+                    break;
+                }
+            }
+            if(!excluded)
+                add("file:/" + f);
+        }
+        if(SHOWTESTCASES) {
+            for(int i = 0; i < this.alltestcases.size(); i++) {
+                TestCase tc = this.alltestcases.get(i);
+                System.err.printf("ALLTESTS: %s%n", tc.getURL());
+            }
+        }
+    }
+
+    protected void
+    add(String url)
+    {
+        try {
+            URL u = new URL(url);
+            File f = new File(u.getPath());
+            if(!f.canRead()) {
+                System.err.println("Unreadable file test case: " + url);
+            }
+        } catch (MalformedURLException e) {
+            System.err.println("Malformed file test case: " + url);
+        }
+        String ext = url.substring(url.lastIndexOf('.'), url.length());
+        TestCase tc = new TestCase(url);
+        for(TestCase t : this.alltestcases) {
+            assert !t.getURL().equals(tc.getURL()) : "Duplicate TestCases: " + t;
+        }
+        this.alltestcases.add(tc);
+    }
+
+    //////////////////////////////////////////////////
+    // Junit test method
+    @Test
+    public void testDSP()
+            throws Exception
+    {
+        for(TestCase testcase : chosentests) {
+            doOneTest(testcase);
+        }
+        System.err.println("*** PASS");
+    }
+
+    //////////////////////////////////////////////////
+    // Primary test method
+    void
+    doOneTest(TestCase testcase)
+            throws Exception
+    {
+        System.err.println("Testcase: " + testcase.getURL());
+        System.err.println("Baseline: " + testcase.getBaseline());
+
+        DSP dsp = dspFor(testcase.getURL());
+
+        dsp.setContext(new DapContext());
+        dsp.open(testcase.getURL());
+
+        String metadata = dumpmetadata(dsp);
+        if(prop_visual)
+            visual(testcase.getURL() + ".dmr", metadata);
+        String data = dumpdata(dsp);
+        if(prop_visual)
+            visual(testcase.getURL() + ".dap", data);
+
+        String baselinefile = testcase.getBaseline();
+
+        String testoutput = metadata + data;
+
+        if(prop_baseline)
+            writefile(baselinefile, testoutput);
+        else if(prop_diff) { //compare with baseline
+            // Read the baseline file(s)
+            String baselinecontent = readfile(baselinefile);
+            System.err.println("Comparison: vs " + baselinefile);
+            Assert.assertTrue("*** FAIL", same(getTitle(), baselinecontent, testoutput));
+        }
+    }
+
+    String dumpmetadata(DSP dsp)
+            throws Exception
+    {
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        // Print the meta-databuffer using these args to NcdumpW
+        DMRPrinter p = new DMRPrinter(dsp.getDMR(), pw);
+        p.testprint();
+        pw.close();
+        sw.close();
+        return sw.toString();
+    }
+
+    String dumpdata(DSP dsp)
+            throws Exception
+    {
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        // Print the meta-databuffer using these args to NcdumpW
+        DSPPrinter p = new DSPPrinter(dsp, pw).flag(DSPPrinter.Flags.CONTROLCHAR);
+        p.print();
+        pw.close();
+        sw.close();
+        return sw.toString();
+    }
+
+    //////////////////////////////////////////////////
+    // Utility methods
+
+    //Locate the test cases with given prefix
+    List<TestCase>
+    locate(String scheme, String s)
+    {
+        return locate(scheme, s, null);
+    }
+
+    List<TestCase>
+    locate(String scheme, String s, List<TestCase> list)
+    {
+        if(list == null) list = new ArrayList<>();
+        int matches = 0;
+        for(TestCase ct : this.alltestcases) {
+            if(!ct.getURL().startsWith(scheme)) continue;
+            if(ct.getPath().endsWith(s)) {
+                matches++;
+                list.add(ct);
+            }
+        }
+        assert matches > 0 : "No such testcase: " + s;
+        return list;
+    }
+
+    static boolean
+    report(String msg)
+    {
+        System.err.println(msg);
+        return false;
+    }
+
+
+}
diff --git a/dap4/d4tests/src/test/java/dap4/test/TestH5Iosp.java b/dap4/d4tests/src/test/java/dap4/test/TestH5Iosp.java
new file mode 100644
index 0000000000..f24051cd2e
--- /dev/null
+++ b/dap4/d4tests/src/test/java/dap4/test/TestH5Iosp.java
@@ -0,0 +1,314 @@
+package dap4.test;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import ucar.nc2.dataset.NetcdfDataset;
+import ucar.unidata.util.test.category.NotJenkins;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.lang.invoke.MethodHandles;
+import java.math.BigInteger;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.List;
+
+@Category(NotJenkins.class)
+public class TestH5Iosp extends DapTestCommon
+{
+    private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+    static protected final boolean DEBUG = false;
+
+    static protected final boolean NCDUMP = true;
+
+    static protected final Mode mode = Mode.BOTH;
+
+    //////////////////////////////////////////////////
+    // Constants
+
+    static protected String DATADIR = "src/test/data"; // relative to dap4 root
+    static protected String TESTDATADIR = DATADIR + "/resources/";
+    static protected String BASELINEDIR = DATADIR + "/resources/TestIosp/baseline";
+    static protected String TESTINPUTDIR = DATADIR + "/resources/testfiles";
+
+    static protected final BigInteger MASK = new BigInteger("FFFFFFFFFFFFFFFF", 16);
+
+    //////////////////////////////////////////////////
+    // Type Declarations
+
+    static protected class H5IospTest
+    {
+        static String root = null;
+        String title;
+        String dataset;
+        String testinputpath;
+        String baselinepath;
+
+        H5IospTest(String dataset)
+        {
+            this.title = dataset;
+            this.dataset = dataset;
+            this.testinputpath
+                    = root + "/" + TESTINPUTDIR + "/" + dataset;
+            this.baselinepath
+                    = root + "/" + BASELINEDIR + "/" + dataset + ".hdf5";
+        }
+
+        public String toString()
+        {
+            return dataset;
+        }
+    }
+
+    static protected enum Mode
+    {
+        DMR, DATA, BOTH;
+    }
+
+    //////////////////////////////////////////////////
+    // Instance variables
+
+    // Misc variables
+    protected boolean isbigendian = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
+
+    // Test cases
+
+    protected List<H5IospTest> alltestcases = new ArrayList<H5IospTest>();
+
+    protected List<H5IospTest> chosentests = new ArrayList<H5IospTest>();
+
+    protected String datasetpath = null;
+
+    protected String testroot = null;
+
+    //////////////////////////////////////////////////
+    @Before
+    public void setup() throws Exception
+    {
+        this.testroot = getTestFilesDir();
+        File f = new File(testroot + "/" + BASELINEDIR);
+        if(!f.exists()) f.mkdir();
+        this.datasetpath = this.testroot + "/" + DATADIR;
+        defineAllTestcases(this.testroot);
+        chooseTestcases();
+    }
+
+    protected String
+    getTestFilesDir()
+    {
+        return TESTINPUTDIR;
+    }
+
+    //////////////////////////////////////////////////
+    // Define test cases
+
+    void
+    chooseTestcases()
+    {
+        if(false) {
+            chosentests = locate("test_enum.nc");
+            //chosentests.add(new H5IospTest("test_test.nc"));
+        } else {
+            for(H5IospTest tc : alltestcases) {
+                chosentests.add(tc);
+            }
+        }
+    }
+
+    void defineAllTestcases(String root)
+    {
+        H5IospTest.root = root;
+        this.alltestcases.add(new H5IospTest("test_one_var.nc"));
+        this.alltestcases.add(new H5IospTest("test_one_vararray.nc"));
+        this.alltestcases.add(new H5IospTest("test_atomic_types.nc"));
+        this.alltestcases.add(new H5IospTest("test_atomic_array.nc"));
+        this.alltestcases.add(new H5IospTest("test_enum.nc"));
+        this.alltestcases.add(new H5IospTest("test_enum_array.nc"));
+        this.alltestcases.add(new H5IospTest("test_struct_type.nc"));
+        this.alltestcases.add(new H5IospTest("test_struct_array.nc"));
+        this.alltestcases.add(new H5IospTest("test_struct_nested.nc"));
+        this.alltestcases.add(new H5IospTest("test_vlen1.nc"));
+        this.alltestcases.add(new H5IospTest("test_vlen2.nc"));
+        this.alltestcases.add(new H5IospTest("test_vlen3.nc"));
+        this.alltestcases.add(new H5IospTest("test_vlen4.nc"));
+        this.alltestcases.add(new H5IospTest("test_vlen5.nc"));
+    }
+
+
+    //////////////////////////////////////////////////
+    // Junit test methods
+
+    @Test
+    public void testH5Iosp()
+            throws Exception
+    {
+        for(H5IospTest testcase : chosentests) {
+            if(!doOneTest(testcase)) {
+                Assert.assertTrue(false);
+            }
+        }
+    }
+
+    //////////////////////////////////////////////////
+    // Primary test method
+    boolean
+    doOneTest(H5IospTest testcase)
+            throws Exception
+    {
+        boolean pass = true;
+
+        System.out.println("Testcase: " + testcase.testinputpath);
+
+        NetcdfDataset ncfile = openDataset(testcase.testinputpath);
+
+        String metadata = null;
+        String data = null;
+        if(mode == Mode.DMR || mode == Mode.BOTH) {
+            metadata = (NCDUMP ? ncdumpmetadata(ncfile,testcase.dataset) : null);
+            if(prop_visual)
+                visual("Meta Data: ", metadata);
+        }
+        if(mode == Mode.DATA || mode == Mode.BOTH) {
+            data = (NCDUMP ? ncdumpdata(ncfile,testcase.dataset) : null);
+            if(prop_visual)
+                visual("Data: ", data);
+        }
+
+        String baselinefile = String.format("%s", testcase.baselinepath);
+        if(prop_baseline) {
+            if(mode == Mode.DMR || mode == Mode.BOTH)
+                writefile(baselinefile + ".dmr", metadata);
+            if(mode == Mode.DATA || mode == Mode.BOTH)
+                writefile(baselinefile + ".dap", data);
+        } else if(prop_diff) { //compare with baseline
+            String baselinecontent = null;
+            if(mode == Mode.DMR || mode == Mode.BOTH) {
+                // Read the baseline file(s)
+                System.out.println("DMR Comparison:");
+                baselinecontent = readfile(baselinefile + ".dmr");
+                pass = pass && same(getTitle(), baselinecontent, metadata);
+                System.out.println(pass ? "Pass" : "Fail");
+            }
+            if(mode == Mode.DATA || mode == Mode.BOTH) {
+                System.out.println("DATA Comparison:");
+                baselinecontent = readfile(baselinefile + ".dap");
+                pass = pass && same(getTitle(), baselinecontent, data);
+                System.out.println(pass ? "Pass" : "Fail");
+            }
+        }
+        return pass;
+    }
+
+    //////////////////////////////////////////////////
+    // Utility methods
+
+    boolean
+    report(String msg)
+    {
+        System.err.println(msg);
+        prop_generate = false;
+        return false;
+    }
+
+
+    // Locate the test cases with given prefix
+    List<H5IospTest>
+    locate(String prefix)
+    {
+        List<H5IospTest> results = new ArrayList<H5IospTest>();
+        for(H5IospTest ct : this.alltestcases) {
+            if(ct.dataset.startsWith(prefix))
+                results.add(ct);
+        }
+        return results;
+    }
+    //////////////////////////////////////////////////
+    // Stand alone
+
+    static public void
+    main(String[] argv)
+    {
+        try {
+            new TestH5Iosp().testH5Iosp();
+        } catch (Exception e) {
+            System.err.println("*** FAIL");
+            e.printStackTrace();
+            System.exit(1);
+        }
+        System.err.println("*** PASS");
+        System.exit(0);
+    }// main
+
+    //////////////////////////////////////////////////
+    // Dump methods
+
+    String ncdumpmetadata(NetcdfDataset ncfile, String datasetname)
+    {
+        boolean ok = false;
+        String metadata = null;
+        StringWriter sw = new StringWriter();
+
+        StringBuilder args = new StringBuilder("-strict");
+        if(datasetname != null) {
+            args.append(" -datasetname ");
+            args.append(datasetname);
+        }
+
+        // Print the meta-databuffer using these args to NcdumpW
+        ok = false;
+        try {
+            ok = ucar.nc2.NCdumpW.print(ncfile, args.toString(), sw, null);
+        } catch (IOException ioe) {
+            ioe.printStackTrace();
+            ok = false;
+        }
+        try {
+            sw.close();
+        } catch (IOException e) {
+        }
+        if(!ok) {
+            System.err.println("NcdumpW failed");
+            System.exit(1);
+        }
+        return shortenFileName(sw.toString(), ncfile.getLocation());
+    }
+
+    String ncdumpdata(NetcdfDataset ncfile, String datasetname)
+    {
+        boolean ok = false;
+        StringWriter sw = new StringWriter();
+
+        StringBuilder args = new StringBuilder("-strict -vall");
+        if(datasetname != null) {
+            args.append(" -datasetname ");
+            args.append(datasetname);
+        }
+        // Dump the databuffer
+        sw = new StringWriter();
+        ok = false;
+        try {
+            ok = ucar.nc2.NCdumpW.print(ncfile, args.toString(), sw, null);
+        } catch (IOException ioe) {
+            ioe.printStackTrace();
+            ok = false;
+        }
+        try {
+            sw.close();
+        } catch (IOException e) {
+        }
+        ;
+        if(!ok) {
+            System.err.println("NcdumpW failed");
+            System.exit(1);
+        }
+        return shortenFileName(sw.toString(), ncfile.getLocation());
+    }
+
+}
+
diff --git a/dap4/d4tests/src/test/java/dap4/test/TestHyrax.java b/dap4/d4tests/src/test/java/dap4/test/TestHyrax.java
new file mode 100644
index 0000000000..ed7ffe51fe
--- /dev/null
+++ b/dap4/d4tests/src/test/java/dap4/test/TestHyrax.java
@@ -0,0 +1,425 @@
+package dap4.test;
+
+import dap4.core.util.DapUtil;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import ucar.nc2.dataset.NetcdfDataset;
+import ucar.unidata.util.test.UnitTestCommon;
+import ucar.unidata.util.test.category.NotJenkins;
+import ucar.unidata.util.test.category.NotTravis;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.lang.invoke.MethodHandles;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Test OpenDap Server at the NetcdfDataset level
+ */
+public class TestHyrax extends DapTestCommon
+{
+    private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+    static final boolean DEBUG = false;
+
+    static final boolean NCDUMP = true; // Use NcDumpW instead of NCPrint
+
+    static final String EXTENSION = (NCDUMP ? "ncdump" : "dmp");
+
+    static final String TESTEXTENSION = "dmr";
+
+    // Mnemonic
+    static final boolean HEADERONLY = false;
+
+    static final String IP = "ec2-54-204-231-163";
+    //////////////////////////////////////////////////
+    // Constants
+
+    static final String DATADIR = "src/test/data"; // relative to dap4 root
+    static final String TESTDATADIR = DATADIR + "/resources/TestHyrax";
+    static final String BASELINEDIR = TESTDATADIR + "/baseline";
+
+    //Define the names of the xfail tests
+    static final String[] XFAIL_TESTS = {"test_struct_array.nc"};
+
+    // Order is important; testing reachability is in the order
+    // listed
+    static final String[] SOURCES = new String[]{
+            "hyrax",
+            "http://" + IP + ".compute-1.amazonaws.com:8080/opendap/data/reader/dap4/dap4.html",
+            "dap4://" + IP + ".compute-1.amazonaws.com:8080/opendap/data/reader/dap4"
+    };
+
+    static boolean isXfailTest(String t)
+    {
+        for(String s : XFAIL_TESTS) {
+            if(s.equals(t)) return true;
+        }
+        return false;
+    }
+
+    //////////////////////////////////////////////////
+    // Type Declarations
+
+    static class Source
+    {
+        public String name;
+        public String testurl;
+        public String prefix;
+
+        public Source(String name, String testurl, String prefix)
+        {
+            this.name = name;
+            this.prefix = prefix;
+            this.testurl = testurl;
+        }
+    }
+
+    static class ClientTest
+    {
+        static String root = null;
+        static String server = null;
+        static int counter = 0;
+
+        boolean checksumming = true;
+        boolean xfail = false;
+        boolean headeronly = false;
+
+        String title;
+        String dataset; // path minus the server url part.
+        String datasetpath; // Hyrax test databuffer is segregated into multiple directories
+        String baselinepath;
+        String constraint;
+        int id;
+
+        ClientTest(String dataset)
+        {
+            this(0, dataset, null);
+        }
+
+        ClientTest(int id, String datasetpath, String constraint)
+        {
+            // Break off the final file set name
+            int index = datasetpath.lastIndexOf('/');
+            this.dataset = datasetpath.substring(index + 1, datasetpath.length());
+            this.datasetpath = datasetpath;
+            this.title = this.dataset;
+            this.id = id;
+            this.constraint = (constraint.length() == 0 ? null : constraint);
+            this.baselinepath
+                    = root + "/" + BASELINEDIR + "/" + dataset;
+            if(this.constraint != null)
+                this.baselinepath += ("." + String.valueOf(this.id));
+        }
+
+        public ClientTest nochecksum()
+        {
+            this.checksumming = false;
+            return this;
+        }
+
+        public ClientTest xfail()
+        {
+            this.xfail = true;
+            return this;
+        }
+
+        public ClientTest headeronly()
+        {
+            this.headeronly = true;
+            return this;
+        }
+
+        String makeurl()
+        {
+            String url = url = server + "/" + datasetpath;
+            if(constraint != null)
+                url += ("?" + constraint);
+            return url;
+        }
+
+        public String toString()
+        {
+            return dataset;
+        }
+    }
+
+    //////////////////////////////////////////////////
+    // Instance variables
+
+    // Test cases
+
+    List<ClientTest> alltestcases = new ArrayList<ClientTest>();
+    List<ClientTest> chosentests = new ArrayList<ClientTest>();
+
+    String resourceroot = null;
+    String datasetpath = null;
+
+    String sourceurl = null;
+
+    //////////////////////////////////////////////////
+
+    @Before
+    public void setup() throws Exception
+    {
+        this.resourceroot = getResourceRoot();
+        this.resourceroot = DapUtil.absolutize(this.resourceroot); // handle problem of windows paths
+        System.out.println("Using source url " + this.sourceurl);
+        defineAllTestcases(this.resourceroot, this.sourceurl);
+        chooseTestcases();
+    }
+
+    //////////////////////////////////////////////////
+    // Define test cases
+
+    void
+    chooseTestcases()
+    {
+        if(false) {
+            chosentests = locate("dmr-testsuite/test_array_7.xml");
+        } else {
+            for(ClientTest tc : alltestcases) {
+                chosentests.add(tc);
+            }
+        }
+    }
+
+    boolean
+    defineAllTestcases(String root, String server)
+    {
+
+        boolean what = HEADERONLY;
+
+        ClientTest.root = root;
+        ClientTest.server = server;
+        if(false) {
+            alltestcases.add(new ClientTest(1, "D4-xml/DMR_4.xml", "b1"));
+        }
+        if(false) {
+            alltestcases.add(new ClientTest("test_simple_1.dmr"));
+            //deleted: alltestcases.add(new TestCase("dmr-testsuite/testall.xml"));
+        }
+        if(false) {
+            alltestcases.add(new ClientTest("dmr-testsuite/test_array_1.xml"));
+            alltestcases.add(new ClientTest("dmr-testsuite/test_array_2.xml"));
+            strings:
+            alltestcases.add(new ClientTest("dmr-testsuite/test_array_3.xml"));
+            alltestcases.add(new ClientTest("dmr-testsuite/test_array_4.xml"));
+            alltestcases.add(new ClientTest("dmr-testsuite/test_array_5.xml"));
+            alltestcases.add(new ClientTest("dmr-testsuite/test_array_6.xml"));
+            alltestcases.add(new ClientTest("dmr-testsuite/test_array_7.xml"));
+            alltestcases.add(new ClientTest("dmr-testsuite/test_array_8.xml"));
+            alltestcases.add(new ClientTest("dmr-testsuite/test_array_10.xml"));
+            alltestcases.add(new ClientTest("dmr-testsuite/test_array_11.xml"));
+
+        }
+        if(false) {
+            alltestcases.add(new ClientTest("dmr-testsuite/test_simple_1.xml"));
+            alltestcases.add(new ClientTest("dmr-testsuite/test_simple_2.xml"));
+            alltestcases.add(new ClientTest("dmr-testsuite/test_simple_3.xml"));
+            alltestcases.add(new ClientTest("dmr-testsuite/test_simple_4.xml"));
+            alltestcases.add(new ClientTest("dmr-testsuite/test_simple_5.xml"));
+            alltestcases.add(new ClientTest("dmr-testsuite/test_simple_6.xml"));
+            //sequence: alltestcases.add(new TestCase("dmr-testsuite/test_simple_7.xml"));
+            //sequence: alltestcases.add(new TestCase("dmr-testsuite/test_simple_8.xml"));
+            alltestcases.add(new ClientTest("dmr-testsuite/test_simple_9.xml"));
+            alltestcases.add(new ClientTest("dmr-testsuite/test_simple_9.1.xml"));
+            alltestcases.add(new ClientTest("dmr-testsuite/test_simple_10.xml"));
+        }
+        if(false) {
+            // alltestcases.add(new TestCase("D4-xml/DMR_0.1.xml"));  needs fixing
+            alltestcases.add(new ClientTest("D4-xml/DMR_0.xml"));
+            alltestcases.add(new ClientTest("D4-xml/DMR_1.xml"));
+            alltestcases.add(new ClientTest("D4-xml/DMR_2.xml"));
+            alltestcases.add(new ClientTest("D4-xml/DMR_2.1.xml"));
+            alltestcases.add(new ClientTest("D4-xml/DMR_3.xml"));
+            alltestcases.add(new ClientTest("D4-xml/DMR_3.1.xml"));
+            alltestcases.add(new ClientTest("D4-xml/DMR_3.2.xml"));
+            alltestcases.add(new ClientTest("D4-xml/DMR_3.3.xml"));
+            alltestcases.add(new ClientTest("D4-xml/DMR_3.4.xml"));
+            alltestcases.add(new ClientTest("D4-xml/DMR_3.5.xml"));
+            alltestcases.add(new ClientTest("D4-xml/DMR_4.xml"));
+            alltestcases.add(new ClientTest("D4-xml/DMR_4.1.xml"));
+            alltestcases.add(new ClientTest("D4-xml/DMR_5.xml"));
+            alltestcases.add(new ClientTest("D4-xml/DMR_5.1.xml"));
+            //serial:  alltestcases.add(new TestCase("D4-xml/DMR_6.xml"));
+            //serial: alltestcases.add(new TestCase("D4-xml/DMR_6.1.xml"));
+            //serial: alltestcases.add(new TestCase("D4-xml/DMR_6.2.xml"));
+            alltestcases.add(new ClientTest("D4-xml/DMR_7.xml"));
+            alltestcases.add(new ClientTest("D4-xml/DMR_7.1.xml"));
+            alltestcases.add(new ClientTest("D4-xml/DMR_7.2.xml"));
+            alltestcases.add(new ClientTest("D4-xml/DMR_7.3.xml"));
+            alltestcases.add(new ClientTest("D4-xml/DMR_7.4.xml"));
+            alltestcases.add(new ClientTest("D4-xml/DMR_7.5.xml"));
+            alltestcases.add(new ClientTest("D4-xml/DMR_8.xml"));
+        }
+
+        if(false) {
+            alltestcases.add(new ClientTest("dmr-testsuite/test_simple_3_error_1.xml").xfail());
+            alltestcases.add(new ClientTest("dmr-testsuite/test_simple_3_error_2.xml").xfail());
+            alltestcases.add(new ClientTest("dmr-testsuite/test_simple_3_error_3.xml").xfail());
+        }
+        for(ClientTest test : alltestcases) {
+            if(what == HEADERONLY) test.headeronly();
+        }
+        return true;
+    }
+
+    //////////////////////////////////////////////////
+    // Junit test method
+
+    @Test
+    @Category({NotJenkins.class, NotTravis.class})
+    public void testHyrax()
+            throws Exception
+    {
+        boolean pass = true;
+        for(ClientTest testcase : chosentests) {
+            if(!doOneTest(testcase)) pass = false;
+        }
+        Assert.assertTrue("*** Fail: TestHyrax", pass);
+    }
+
+    //////////////////////////////////////////////////
+    // Primary test method
+    boolean
+    doOneTest(ClientTest testcase)
+            throws Exception
+    {
+        boolean pass = true;
+        System.out.println("Testcase: " + testcase.dataset);
+        String url = testcase.makeurl();
+        NetcdfDataset ncfile = null;
+        try {
+            ncfile = openDataset(url);
+        } catch (Exception e) {
+            System.err.println(testcase.xfail ? "XFail" : "Fail");
+            e.printStackTrace();
+            return testcase.xfail;
+        }
+        String usethisname = UnitTestCommon.extractDatasetname(url,null);
+        String metadata = (NCDUMP ? ncdumpmetadata(ncfile,usethisname) : null);
+        if(prop_visual) {
+            visual(testcase.title + ".dmr", metadata);
+        }
+
+        String data = null;
+        if(!testcase.headeronly) {
+            data = (NCDUMP ? ncdumpdata(ncfile,usethisname) : null);
+            if(prop_visual) {
+                visual(testcase.title + ".dap", data);
+            }
+        }
+
+        String testoutput = (testcase.headeronly ? metadata : (NCDUMP ? data : metadata + data));
+
+        String baselinefile = testcase.baselinepath + "." + EXTENSION;
+
+        if(prop_baseline)
+            writefile(baselinefile, testoutput);
+
+        if(prop_diff) { //compare with baseline
+            // Read the baseline file(s)
+            String baselinecontent = readfile(baselinefile);
+            System.out.println("Comparison: vs " + baselinefile);
+            pass = pass && same(getTitle(), baselinecontent, testoutput);
+            System.out.println(pass ? "Pass" : "Fail");
+        }
+        return pass;
+    }
+
+
+    String ncdumpmetadata(NetcdfDataset ncfile, String datasetname)
+            throws Exception
+    {
+        StringWriter sw = new StringWriter();
+
+        StringBuilder args = new StringBuilder("-strict");
+        if(datasetname != null) {
+            args.append(" -datasetname ");
+            args.append(datasetname);
+        }
+        // Print the meta-databuffer using these args to NcdumpW
+        try {
+            if(!ucar.nc2.NCdumpW.print(ncfile, args.toString(), sw, null))
+                throw new Exception("NcdumpW failed");
+        } catch (IOException ioe) {
+            throw new Exception("NcdumpW failed", ioe);
+        }
+        sw.close();
+        return sw.toString();
+    }
+
+    String ncdumpdata(NetcdfDataset ncfile, String datasetname)
+            throws Exception
+    {
+        StringWriter sw = new StringWriter();
+
+        StringBuilder args = new StringBuilder("-strict -vall");
+        if(datasetname != null) {
+            args.append(" -datasetname ");
+            args.append(datasetname);
+        }
+
+        // Dump the databuffer
+        sw = new StringWriter();
+        try {
+            if(!ucar.nc2.NCdumpW.print(ncfile, args.toString(), sw, null))
+                throw new Exception("NCdumpW failed");
+        } catch (IOException ioe) {
+            ioe.printStackTrace();
+            throw new Exception("NCdumpW failed", ioe);
+        }
+        sw.close();
+        return sw.toString();
+    }
+
+    //////////////////////////////////////////////////
+    // Utility methods
+
+
+    //Locate the test cases with given prefix
+    List<ClientTest>
+    locate(String prefix)
+    {
+        List<ClientTest> results = new ArrayList<ClientTest>();
+        for(ClientTest ct : this.alltestcases) {
+            if(!ct.datasetpath.startsWith(prefix))
+                continue;
+            results.add(ct);
+        }
+        return results;
+    }
+
+    static boolean
+    report(String msg)
+    {
+        System.err.println(msg);
+        return false;
+    }
+
+
+    //////////////////////////////////////////////////
+    // Stand alone
+
+    static public void
+    main(String[] argv)
+    {
+        try {
+            new TestHyrax().testHyrax();
+        } catch (Exception e) {
+            System.err.println("*** FAIL");
+            e.printStackTrace();
+            System.exit(1);
+        }
+        System.err.println("*** PASS");
+        System.exit(0);
+    }// main
+
+} // class TestHyrax
+
diff --git a/dap4/d4tests/src/test/java/dap4/test/TestNc4Iosp.java b/dap4/d4tests/src/test/java/dap4/test/TestNc4Iosp.java
new file mode 100644
index 0000000000..d8c28262b8
--- /dev/null
+++ b/dap4/d4tests/src/test/java/dap4/test/TestNc4Iosp.java
@@ -0,0 +1,312 @@
+package dap4.test;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import ucar.nc2.dataset.NetcdfDataset;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.lang.invoke.MethodHandles;
+import java.math.BigInteger;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.List;
+
+public class TestNc4Iosp extends DapTestCommon
+{
+    private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+    static protected final boolean DEBUG = false;
+
+    static protected final boolean NCDUMP = true;
+
+    static protected final Mode mode = Mode.BOTH;
+
+    //////////////////////////////////////////////////
+    // Constants
+
+    static protected final String RESOURCEPATH = "/src/test/data/resources"; // wrt getTestInputFilesDIr
+    static protected final String TESTINPUTDIR = "/testfiles";
+    static protected final String BASELINEDIR = "/TestIosp/baseline";
+
+    static protected final BigInteger MASK = new BigInteger("FFFFFFFFFFFFFFFF", 16);
+
+    //////////////////////////////////////////////////
+    // Type Declarations
+
+    static protected class Nc4IospTest
+    {
+        static String inputroot = null;
+        static String baselineroot = null;
+
+        static public void
+        setRoots(String input, String baseline)
+        {
+            inputroot = input;
+            baselineroot = baseline;
+        }
+
+        String title;
+        String dataset;
+        String testinputpath;
+        String baselinepath;
+
+        Nc4IospTest(String dataset)
+        {
+            this.title = dataset;
+            this.dataset = dataset;
+            this.testinputpath = canonjoin(this.inputroot, dataset);
+            this.baselinepath = canonjoin(this.baselineroot, dataset) + ".nc4";
+        }
+
+        public String toString()
+        {
+            return dataset;
+        }
+    }
+
+    static protected enum Mode
+    {
+        DMR, DATA, BOTH;
+    }
+
+    //////////////////////////////////////////////////
+    // Instance variables
+
+    // Misc variables
+    protected boolean isbigendian = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
+
+    // Test cases
+
+    protected List<Nc4IospTest> alltestcases = new ArrayList<Nc4IospTest>();
+
+    protected List<Nc4IospTest> chosentests = new ArrayList<Nc4IospTest>();
+
+    protected String datasetpath = null;
+
+    protected String root = null;
+
+    //////////////////////////////////////////////////
+    @Before
+    public void setup() throws Exception
+    {
+        this.root = getResourceRoot();
+        testSetup();
+        Nc4IospTest.setRoots(canonjoin(getResourceRoot(), TESTINPUTDIR),
+                canonjoin(getResourceRoot(), BASELINEDIR));
+        defineAllTestcases();
+        chooseTestcases();
+    }
+
+    protected String
+    getTestFilesDir()
+    {
+        return "";
+    }
+
+    //////////////////////////////////////////////////
+    // Define test cases
+
+    void
+    chooseTestcases()
+    {
+        if(false) {
+            chosentests = locate("test_struct_array.nc");
+            prop_visual = true;
+            prop_debug = true;
+            //chosentests.add(new Nc4IospTest("test_test.nc"));
+        } else {
+            prop_baseline = false;
+            for(Nc4IospTest tc : alltestcases) {
+                chosentests.add(tc);
+            }
+        }
+    }
+
+    void defineAllTestcases()
+    {
+        this.alltestcases.add(new Nc4IospTest("test_one_var.nc"));
+        this.alltestcases.add(new Nc4IospTest("test_one_vararray.nc"));
+        this.alltestcases.add(new Nc4IospTest("test_atomic_types.nc"));
+        this.alltestcases.add(new Nc4IospTest("test_atomic_array.nc"));
+        this.alltestcases.add(new Nc4IospTest("test_enum.nc"));
+        this.alltestcases.add(new Nc4IospTest("test_enum_array.nc"));
+        this.alltestcases.add(new Nc4IospTest("test_struct_type.nc"));
+        this.alltestcases.add(new Nc4IospTest("test_struct_array.nc"));
+        this.alltestcases.add(new Nc4IospTest("test_struct_nested.nc"));
+        this.alltestcases.add(new Nc4IospTest("test_vlen1.nc"));
+        this.alltestcases.add(new Nc4IospTest("test_vlen2.nc"));
+        this.alltestcases.add(new Nc4IospTest("test_vlen3.nc"));
+        this.alltestcases.add(new Nc4IospTest("test_vlen4.nc"));
+        this.alltestcases.add(new Nc4IospTest("test_vlen5.nc"));
+    }
+
+
+    //////////////////////////////////////////////////
+    // Junit test methods
+
+    @Test
+    public void testNc4Iosp()
+            throws Exception
+    {
+        for(Nc4IospTest testcase : chosentests) {
+            doOneTest(testcase);
+        }
+    }
+
+    //////////////////////////////////////////////////
+    // Primary test method
+    void
+    doOneTest(Nc4IospTest testcase)
+            throws Exception
+    {
+        System.err.println("Testcase: " + testcase.testinputpath);
+
+        NetcdfDataset ncfile = openDataset(testcase.testinputpath);
+
+        String metadata = null;
+        String data = null;
+        if(mode == Mode.DMR || mode == Mode.BOTH) {
+            metadata = (NCDUMP ? ncdumpmetadata(ncfile,testcase.dataset) : null);
+            if(prop_visual)
+                visual("Meta Data: ", metadata);
+        }
+        if(mode == Mode.DATA || mode == Mode.BOTH) {
+            data = (NCDUMP ? ncdumpdata(ncfile,testcase.dataset) : null);
+            if(prop_visual)
+                visual("Data: ", data);
+        }
+
+        String baselinefile = String.format("%s", testcase.baselinepath);
+        System.err.println("Testpath: " + testcase.testinputpath);
+        System.err.println("Baseline: " + baselinefile);
+        if(prop_baseline) {
+            if(mode == Mode.DMR || mode == Mode.BOTH)
+                writefile(baselinefile + ".dmr", metadata);
+            if(mode == Mode.DATA || mode == Mode.BOTH)
+                writefile(baselinefile + ".dap", data);
+        } else if(prop_diff) { //compare with baseline
+            String baselinecontent = null;
+            if(mode == Mode.DMR || mode == Mode.BOTH) {
+                // Read the baseline file(s)
+                System.err.println("DMR Comparison:");
+                try {
+                    baselinecontent = readfile(baselinefile + ".dmr");
+                    boolean pass = same(getTitle(), baselinecontent, metadata);
+                    Assert.assertTrue("***Fail", pass);
+                } catch (IOException ioe) {
+                    Assert.assertTrue("baselinefile" + ".dmr: " + ioe.getMessage(), false);
+                }
+            }
+            if(mode == Mode.DATA || mode == Mode.BOTH) {
+                System.err.println("DATA Comparison:");
+                try {
+                    baselinecontent = readfile(baselinefile + ".dap");
+                    Assert.assertTrue("***Data Fail", same(getTitle(), baselinecontent, data));
+
+                } catch (IOException ioe) {
+                    Assert.assertTrue("baselinefile" + ".dap: " + ioe.getMessage(), false);
+                }
+            }
+        }
+    }
+
+    //////////////////////////////////////////////////
+    // Utility methods
+
+    boolean
+    report(String msg)
+    {
+        System.err.println(msg);
+        prop_generate = false;
+        return false;
+    }
+
+
+    // Locate the test cases with given prefix
+    List<Nc4IospTest>
+    locate(String prefix)
+    {
+        List<Nc4IospTest> results = new ArrayList<Nc4IospTest>();
+        for(Nc4IospTest ct : this.alltestcases) {
+            if(ct.dataset.startsWith(prefix))
+                results.add(ct);
+        }
+        return results;
+    }
+
+    //////////////////////////////////////////////////
+    // Dump methods
+
+    String ncdumpmetadata(NetcdfDataset ncfile, String datasetname)
+    {
+        boolean ok = false;
+        String metadata = null;
+        StringWriter sw = new StringWriter();
+
+        StringBuilder args = new StringBuilder("-strict");
+        if(datasetname != null) {
+            args.append(" -datasetname ");
+            args.append(datasetname);
+        }
+
+        // Print the meta-databuffer using these args to NcdumpW
+        ok = false;
+        try {
+            ok = ucar.nc2.NCdumpW.print(ncfile, args.toString(), sw, null);
+        } catch (IOException ioe) {
+            ioe.printStackTrace();
+            ok = false;
+        }
+        try {
+            sw.close();
+        } catch (IOException e) {
+        }
+
+        if(!ok) {
+            System.err.println("NcdumpW failed");
+            System.exit(1);
+        }
+        //return shortenFileName(sw.toString(), ncfile.getLocation());
+        return sw.toString();
+    }
+
+    String ncdumpdata(NetcdfDataset ncfile, String datasetname)
+    {
+        boolean ok = false;
+        StringWriter sw = new StringWriter();
+
+        StringBuilder args = new StringBuilder("-strict -vall");
+        if(datasetname != null) {
+            args.append(" -datasetname ");
+            args.append(datasetname);
+        }
+
+        // Dump the databuffer
+        sw = new StringWriter();
+        ok = false;
+        try {
+            ok = ucar.nc2.NCdumpW.print(ncfile, args.toString(), sw, null);
+        } catch (IOException ioe) {
+            ioe.printStackTrace();
+            ok = false;
+        }
+        try {
+            sw.close();
+        } catch (IOException e) {
+        }
+        ;
+        if(!ok) {
+            System.err.println("NcdumpW failed");
+            System.exit(1);
+        }
+        //return shortenFileName(sw.toString(), ncfile.getLocation());
+        return sw.toString();
+    }
+
+
+}
+
diff --git a/dap4/d4tests/src/test/java/dap4/test/TestParserCE.java b/dap4/d4tests/src/test/java/dap4/test/TestParserCE.java
new file mode 100644
index 0000000000..f9cc8d105c
--- /dev/null
+++ b/dap4/d4tests/src/test/java/dap4/test/TestParserCE.java
@@ -0,0 +1,284 @@
+/* Copyright 2012, UCAR/Unidata.
+   See the LICENSE file for more information.
+*/
+
+package dap4.test;
+
+
+import dap4.core.ce.CECompiler;
+import dap4.core.ce.CEConstraint;
+import dap4.core.ce.parser.CEParserImpl;
+import dap4.core.dmr.DMRFactory;
+import dap4.core.dmr.DapDataset;
+import dap4.core.dmr.parser.DOM4Parser;
+import dap4.core.dmr.parser.Dap4Parser;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.lang.invoke.MethodHandles;
+import java.util.ArrayList;
+import java.util.List;
+
+public class TestParserCE extends DapTestCommon
+{
+    private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+    //////////////////////////////////////////////////
+    // Constants
+    static final boolean DUMPDMR = false;
+    static final boolean DMRPARSEDEBUG = false;
+    static final boolean CEPARSEDEBUG = false;
+
+    static final String TESTCASEDIR = "src/test/data/resources/TestParsers"; // relative to dap4 root
+
+    static final boolean USEDOM = false;
+
+    //////////////////////////////////////////////////
+    // Type decls
+    static class TestSet
+    {
+        public String dmr;
+        public String constraint;
+        public String expected = null;
+        public String[] debug = null;
+        public int id = 0;
+
+        public TestSet(int id, String cedmr, String ces, String expected)
+                throws IOException
+        {
+            this.id = id;
+            this.dmr = cedmr;
+            this.constraint = ces;
+            this.expected = expected;
+        }
+
+        public TestSet setdebug(String[] debug)
+        {
+            this.debug = debug;
+            return this;
+        }
+
+        public TestSet setdebug(String debug)
+        {
+            return setdebug(new String[]{debug});
+        }
+
+        public String
+        toString()
+        {
+            return constraint;
+        }
+
+    }
+
+    //////////////////////////////////////////////////
+    // Instance methods
+
+    // All test cases
+    List<TestSet> alltestsets = new ArrayList<>();
+    List<TestSet> chosentests = new ArrayList<>();
+
+    DapDataset dmr = null;
+
+    //////////////////////////////////////////////////
+    @Before
+    public void setup()
+    {
+        try {
+            defineAllTestCases();
+            chooseTestcases();
+        } catch (IOException ioe) {
+            ioe.printStackTrace();
+        }
+    }
+
+    //////////////////////////////////////////////////
+    // Misc. methods
+
+    protected void
+    chooseTestcases()
+    {
+        if(false) {
+            chosentests = locate(7);
+            assert chosentests.size() > 0 : "Not tests chosen";
+        } else {
+            for(TestSet tc : alltestsets) {
+                chosentests.add(tc);
+            }
+        }
+    }
+
+    // Locate the test cases
+    List<TestSet>
+    locate(Object ce)
+    {
+        List<TestSet> results = new ArrayList<>();
+        for(TestSet ct : this.alltestsets) {
+            if(ce instanceof String) {
+                if(ct.constraint.equals(ce))
+                    results.add(ct);
+            } else if(ce instanceof Integer) {
+                if(ct.id == ((Integer) ce))
+                    results.add(ct);
+            }
+        }
+        return results;
+    }
+
+    protected void
+    defineAllTestCases()
+            throws IOException
+    {
+        alltestsets.add(new TestSet(1, CE1_DMR, "/a[1]", "/a[1]"));
+        alltestsets.add(new TestSet(2, CE1_DMR, "/b[10:16]", "/b[10:16]"));
+        alltestsets.add(new TestSet(3, CE1_DMR, "/c[8:2:15]", "/c[8:2:15]"));
+        alltestsets.add(new TestSet(4, CE1_DMR, "/a[1];/b[10:16];/c[8:2:15]", "/a[1];/b[10:16];/c[8:2:15]"));
+        alltestsets.add(new TestSet(5, CE1_DMR, "/d[1][0:2:2];/a[1];/e[1][0];/f[0][1]", "/d[1][0:2:2];/a[1];/e[1][0];/f[0][1]"));
+        alltestsets.add(new TestSet(6, CE1_DMR, "/s[0:3][0:2].x;/s[0:3][0:2].y", "/s[0:3][0:2]"));
+        alltestsets.add(new TestSet(7, CE1_DMR, "/seq|i1<0", "/seq|i1<0"));
+        alltestsets.add(new TestSet(8, CE1_DMR, "/seq|0<i1<10", "/seq|i1>0,i1<10"));
+        alltestsets.add(new TestSet(9, CE2_DMR, "vo[1:1][0,0]", "/vo[1][0,0]"));
+    }
+
+    //////////////////////////////////////////////////
+    // Junit test method
+
+    @Test
+    public void testParserCE()
+            throws Exception
+    {
+        for(TestSet testset : chosentests) {
+            if(!doOneTest(testset)) {
+                Assert.assertTrue(false);
+                System.exit(1);
+            }
+        }
+    }
+
+    boolean
+    doOneTest(TestSet testset)
+            throws Exception
+    {
+        boolean pass = true;
+
+        System.out.println("Test Set: " + testset.constraint);
+
+        if(DUMPDMR) {
+            visual("DMR:",testset.dmr);
+        }
+
+        // Create the DMR tree
+        System.out.println("Parsing DMR");
+        Dap4Parser parser;
+        if(!USEDOM)
+            parser = new DOM4Parser(new DMRFactory());
+        if(DMRPARSEDEBUG)
+            parser.setDebugLevel(1);
+        boolean parseok = parser.parse(testset.dmr);
+        if(parseok)
+            dmr = parser.getDMR();
+        if(dmr == null)
+            parseok = false;
+        if(!parseok)
+            throw new Exception("DMR Parse failed");
+        System.out.flush();
+        System.err.flush();
+
+        // Iterate over the constraints
+        String results = "";
+        CEConstraint ceroot = null;
+        System.out.println("constraint: " + testset.constraint);
+        System.out.flush();
+        CEParserImpl ceparser = null;
+        try {
+            ceparser = new CEParserImpl(dmr);
+            if(CEPARSEDEBUG)
+                ceparser.setDebugLevel(1);
+            parseok = ceparser.parse(testset.constraint);
+            CECompiler compiler = new CECompiler();
+            ceroot = compiler.compile(dmr, ceparser.getCEAST());
+        } catch (Exception e) {
+            e.printStackTrace();
+            parseok = false;
+        }
+        if(ceroot == null)
+            parseok = false;
+        if(!parseok)
+            throw new Exception("CE Parse failed");
+
+        // Dump the parsed CE for comparison purposes
+        String cedump = ceroot.toConstraintString();
+        if(prop_visual)
+            visual("|" + testset.constraint + "|", cedump);
+        results += (cedump + "\n");
+        if(prop_diff) { //compare with baseline
+            // Read the baseline file
+            String baselinecontent = testset.expected;
+            pass = same(getTitle(), baselinecontent, results);
+        }
+        return pass;
+    }
+
+
+    ////////////////////////////////////
+    // Data for the tests
+
+    String CE1_DMR =
+            "<Dataset"
+                    + "         name=\"ce1\""
+                    + "         dapVersion=\"4.0\""
+                    + "         dmrVersion=\"1.0\""
+                    + "         ns=\"http://xml.opendap.org/ns/DAP/4.0#\">"
+                    + "  <Dimension name=\"d10\" size=\"10\"/>"
+                    + "  <Dimension name=\"d17\" size=\"17\"/>"
+                    + "  <Int32 name=\"a\">"
+                    + "    <Dim name=\"/d17\"/>"
+                    + "  </Int32>"
+                    + "  <Int32 name=\"b\">"
+                    + "    <Dim name=\"/d17\"/>"
+                    + "  </Int32>"
+                    + "  <Int32 name=\"c\">"
+                    + "    <Dim name=\"/d17\"/>"
+                    + "  </Int32>"
+                    + "  <Int32 name=\"d\">"
+                    + "    <Dim name=\"/d10\"/>"
+                    + "    <Dim name=\"/d17\"/>"
+                    + "  </Int32>"
+                    + "  <Int32 name=\"e\">"
+                    + "    <Dim name=\"/d10\"/>"
+                    + "    <Dim name=\"/d17\"/>"
+                    + "  </Int32>"
+                    + "  <Int32 name=\"f\">"
+                    + "    <Dim name=\"/d10\"/>"
+                    + "    <Dim name=\"/d17\"/>"
+                    + "  </Int32>"
+                    + "  <Structure name=\"s\">"
+                    + "      <Int32 name=\"x\"/>"
+                    + "      <Int32 name=\"y\"/>"
+                    + "    <Dim name=\"/d10\"/>"
+                    + "    <Dim name=\"/d10\"/>"
+                    + "  </Structure>"
+                    + "  <Sequence name=\"seq\">"
+                    + "    <Int32 name=\"i1\"/>"
+                    + "    <Int16 name=\"sh1\"/>"
+                    + "  </Sequence>"
+                    + "</Dataset>";
+
+
+    String CE2_DMR =
+            "<Dataset"
+                    + "         name=\"ce2\""
+                    + "         dapVersion=\"4.0\""
+                    + "         dmrVersion=\"1.0\""
+                    + "         ns=\"http://xml.opendap.org/ns/DAP/4.0#\">"
+                    + "  <Dimension name=\"d2\" size=\"2\"/>"
+                    + "  <Opaque name=\"vo\">"
+                    + "    <Dim name=\"/d2\"/>"
+                    + "    <Dim name=\"/d2\"/>"
+                    + "  </Opaque>"
+                    + "</Dataset>";
+}
diff --git a/dap4/d4tests/src/test/java/dap4/test/TestParserDMR.java b/dap4/d4tests/src/test/java/dap4/test/TestParserDMR.java
new file mode 100644
index 0000000000..f2b3a69092
--- /dev/null
+++ b/dap4/d4tests/src/test/java/dap4/test/TestParserDMR.java
@@ -0,0 +1,262 @@
+/* Copyright 2012, UCAR/Unidata.
+   See the LICENSE file for more information.
+*/
+
+package dap4.test;
+
+import dap4.core.dmr.DMRFactory;
+import dap4.core.dmr.DapDataset;
+import dap4.core.dmr.ErrorResponse;
+import dap4.core.dmr.parser.DOM4Parser;
+import dap4.core.dmr.parser.Dap4Parser;
+import dap4.core.dmr.parser.ParseUtil;
+import dap4.dap4lib.DMRPrinter;
+import org.junit.Assert;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.invoke.MethodHandles;
+import java.util.ArrayList;
+import java.util.List;
+
+
+public class TestParserDMR extends DapTestCommon
+{
+    private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+    static final boolean PARSEDEBUG = false;
+
+    // Do a special test to compare the dmr parser print output
+    // to the original input. This will often fail in non-essential
+    // ways, so it must be verified by hand.
+    static final boolean BACKCOMPARE = false;
+
+    //////////////////////////////////////////////////
+    // Constants
+    // Define the input set(s)
+    static protected final String DIR1 = "/TestParsers/dmrset"; // relative to dap4  root
+    static protected final String DIR2 = "/TestServlet/baseline"; // relative to dap4  root
+    static protected final String BASELINE = "/TestParsers/baseline"; // relative to dap4 root
+
+    //////////////////////////////////////////////////
+
+    static protected class TestCase
+    {
+        static public String resourceroot = null;
+
+        String name;
+        String dir;
+        String ext;
+        String input;
+        String baseline;
+
+        public TestCase(String dir, String name, String ext)
+        {
+            this.name = name;
+            this.dir = dir;
+            this.ext = ext;
+            this.input = resourceroot + dir + "/" + name + "." + ext;
+            this.baseline = resourceroot + BASELINE + "/" + name + "." + "dmp";
+        }
+    }
+    //////////////////////////////////////////////////
+    // Instance methods
+
+    // Test cases
+    protected List<TestCase> alltestcases = new ArrayList<TestCase>();
+    protected List<TestCase> chosentests = new ArrayList<TestCase>();
+    protected int flags = ParseUtil.FLAG_NONE;
+    protected boolean debug = false;
+
+    //////////////////////////////////////////////////
+
+    public TestParserDMR()
+    {
+        super();
+        setControls();
+        defineTestCases();
+        chooseTestcases();
+    }
+
+    //////////////////////////////////////////////////
+    // Misc. methods
+
+    protected void
+    chooseTestcases()
+    {
+        if(false) {
+            chosentests = locate("test_struct_nested.hdf5");
+            prop_visual = true;
+            assert chosentests.size() > 0 : "No tests chosen";
+        } else {
+            for(TestCase tc : alltestcases) {
+                chosentests.add(tc);
+            }
+        }
+    }
+
+    // Locate the test cases with given prefix
+    List<TestCase>
+    locate(String prefix)
+    {
+        List<TestCase> results = new ArrayList<TestCase>();
+        for(TestCase ct : this.alltestcases) {
+            if(ct.name.startsWith(prefix))
+                results.add(ct);
+        }
+        return results;
+    }
+
+    protected void defineTestCases()
+    {
+        String root = getResourceRoot();
+        TestCase.resourceroot = root;
+        loadDir(DIR1, "dmr");
+        loadDir(DIR2, "dmr");
+    }
+
+    void loadDir(String dirsuffix, String... extensions)
+    {
+        File dir = new File(TestCase.resourceroot + dirsuffix);
+        File[] filelist = dir.listFiles();
+        for(int i = 0; i < filelist.length; i++) {
+            File file = filelist[i];
+            String name = file.getName();
+            // check the extension
+            String match = null;
+            for(String ext : extensions) {
+                if(name.endsWith(ext)) {
+                    match = ext;
+                    break;
+                }
+            }
+            if(match != null) {
+                String basename = name.substring(0, name.length() - (match.length() + 1));
+                TestCase ct = new TestCase(dirsuffix, basename, match);
+                addtestcase(ct);
+            }
+        }
+    }
+
+    protected void addtestcase(TestCase ct)
+    {
+        if(DEBUG) {
+            System.err.printf("Adding Test: input=%s%n", ct.input);
+            if(!new File(ct.input).exists())
+                System.err.printf("             +++%s does not exist%n", ct.input);
+            System.err.printf("             baseline=%s%n", ct.baseline);
+            if(!new File(ct.baseline).exists())
+                System.err.printf("             ***%s does not exist%n", ct.baseline);
+            System.err.flush();
+        }
+        this.alltestcases.add(ct);
+    }
+
+    void setControls()
+    {
+        if(prop_controls == null)
+            return;
+        flags = ParseUtil.FLAG_NOCR; // always
+        for(int i = 0; i < prop_controls.length(); i++) {
+            char c = prop_controls.charAt(i);
+            switch (c) {
+            case 'w':
+                flags |= ParseUtil.FLAG_TRIMTEXT;
+                break;
+            case 'l':
+                flags |= ParseUtil.FLAG_ELIDETEXT;
+                break;
+            case 'e':
+                flags |= ParseUtil.FLAG_ESCAPE;
+                break;
+            case 'T':
+                flags |= ParseUtil.FLAG_TRACE;
+                break;
+            case 'd':
+                debug = true;
+                break;
+            default:
+                System.err.println("unknown X option: " + c);
+                break;
+            }
+        }
+    }
+
+    //////////////////////////////////////////////////
+    // Junit test method
+
+    @Test
+    public void testParser()
+            throws Exception
+    {
+        int ntests = 0;
+        for(TestCase testcase : chosentests) {
+            ntests++;
+            doOneTest(testcase);
+        }
+        Assert.assertTrue("***Pass ", true);
+    }
+
+    void
+    doOneTest(TestCase testcase)
+            throws Exception
+    {
+        String document;
+        int i, c;
+
+        String testinput = testcase.input;
+        String baseline = testcase.baseline;
+
+        System.err.println("Testcase: " + testinput);
+        System.err.println("Baseline: " + baseline);
+        System.err.flush();
+
+        document = readfile(testinput);
+
+        Dap4Parser parser = new DOM4Parser(new DMRFactory());
+        if(PARSEDEBUG || debug)
+            parser.setDebugLevel(1);
+
+        if(!parser.parse(document))
+            throw new Exception("DMR Parse failed: " + testinput);
+        DapDataset dmr = parser.getDMR();
+        ErrorResponse err = parser.getErrorResponse();
+        if(err != null)
+            System.err.println("Error response:\n" + err.buildXML());
+        if(dmr == null) {
+            System.err.println("No dataset created");
+            return;
+        }
+
+        // Dump the parsed DMR for comparison purposes
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        DMRPrinter dapprinter = new DMRPrinter(dmr, pw);
+        dapprinter.testprint();
+        pw.close();
+        sw.close();
+        String testresult = sw.toString();
+
+        // Read the baseline file
+        String baselinecontent;
+        if(BACKCOMPARE)
+            baselinecontent = document;
+        else
+            baselinecontent = readfile(baseline);
+        if(prop_visual) {
+            visual("Baseline", baselinecontent);
+            visual("Output", testresult);
+        }
+
+        if(prop_baseline) {
+            writefile(baseline, testresult);
+        } else if(prop_diff) { //compare with baseline
+            Assert.assertTrue("Files are different",
+                    same(getTitle(), baselinecontent, testresult));
+        }
+    }
+}
diff --git a/dap4/d4tests/src/test/java/dap4/test/TestPrinter.java b/dap4/d4tests/src/test/java/dap4/test/TestPrinter.java
new file mode 100644
index 0000000000..9c6ba9608f
--- /dev/null
+++ b/dap4/d4tests/src/test/java/dap4/test/TestPrinter.java
@@ -0,0 +1,130 @@
+/* Copyright 2012, UCAR/Unidata.
+   See the LICENSE file for more information.
+*/
+
+package dap4.test;
+
+import dap4.cdm.nc2.DapNetcdfFile;
+import dap4.core.dmr.DapDataset;
+import dap4.core.util.*;
+import dap4.core.data.DSP;
+import dap4.dap4lib.DMRPrinter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import ucar.nc2.*;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.lang.invoke.MethodHandles;
+import java.util.Map;
+
+/**
+ * Dump DMR and/or data part of a DSP
+ */
+
+public class TestPrinter
+{
+    private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+    //////////////////////////////////////////////////
+    // Constants
+
+    // Could use enumset, but it is so ugly,
+    // so use good old OR'able flags
+    static final int NILFLAGS = 0;
+    static final int PERLINE = 1; // print xml attributes 1 per line
+    static final int NONAME = 2; // do not print name xml attribute
+    static final int NONNIL = 4; // print empty xml attributes
+
+    //////////////////////////////////////////////////
+    // Instance Variables
+
+    protected NetcdfFile ncfile = null; // dsp can be extracted from this
+    protected DSP dsp = null;
+    protected DapDataset dmr = null;
+    protected PrintWriter writer = null;
+    protected Map<Variable, ParsedSectionSpec> varmap = null;
+    protected IndentWriter printer = null;
+
+    //////////////////////////////////////////////////
+    // Constructor(s)
+
+    public TestPrinter(NetcdfFile ncfile, PrintWriter writer)
+    {
+        try {
+            setDataset(ncfile);
+        } catch (DapException de) {
+            System.err.println("Bad NetcdfFile");
+            System.exit(1);
+        }
+        setWriter(writer);
+        setVarMap(null);
+    }
+
+    public TestPrinter(DSP dsp, PrintWriter writer)
+    {
+        try {
+            setDSP(dsp);
+        } catch (DapException de) {
+            System.err.println("Bad DSP");
+            System.exit(1);
+        }
+        setWriter(writer);
+        setVarMap(null);
+    }
+
+    //////////////////////////////////////////////////
+    // Accessors
+
+    public void setWriter(PrintWriter writer)
+    {
+        this.writer = writer;
+        this.printer = new IndentWriter(writer);
+    }
+
+    public void setDataset(NetcdfFile ncfile)
+        throws DapException
+    {
+        this.ncfile = ncfile;
+        setDSP(((DapNetcdfFile) this.ncfile).getDSP());
+    }
+
+    public void setDSP(DSP dsp)
+        throws DapException
+    {
+        this.dsp = dsp;
+        this.dmr = dsp.getDMR();
+    }
+
+    public void setVarMap(Map<Variable, ParsedSectionSpec> map)
+    {
+        this.varmap = map;
+    }
+
+    //////////////////////////////////////////////////
+    // Print methods
+
+    public void flush()
+        throws IOException
+    {
+        printer.flush();
+        writer.flush();
+    }
+
+    /**
+     * Print the CDM metadata for a NetcdfFile object in DMR format
+     *
+     * @throws IOException
+     */
+
+    public void
+    print()
+        throws IOException
+    {
+        printer.setIndent(0);
+        DMRPrinter dmrprinter = new DMRPrinter(this.dmr,writer);
+        dmrprinter.print();
+        dmrprinter.flush();
+    }
+
+} // class TestPrinter
diff --git a/dap4/d4tests/src/test/java/dap4/test/TestSerial.java b/dap4/d4tests/src/test/java/dap4/test/TestSerial.java
new file mode 100644
index 0000000000..58d609da88
--- /dev/null
+++ b/dap4/d4tests/src/test/java/dap4/test/TestSerial.java
@@ -0,0 +1,332 @@
+package dap4.test;
+
+import dap4.core.util.DapUtil;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import ucar.nc2.dataset.NetcdfDataset;
+import ucar.unidata.util.test.TestDir;
+import ucar.unidata.util.test.UnitTestCommon;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.lang.invoke.MethodHandles;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Test at the NetcdfDataset level; access .ser files on server.
+ */
+public class TestSerial extends DapTestCommon
+{
+    private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+    static protected final boolean DEBUG = false;
+
+    static protected final String TESTINPUTDIR = "/testfiles";
+
+    static protected final boolean NCDUMP = true; // Use NcDumpW instead of D4Print
+
+    static protected final String EXTENSION = (NCDUMP ? "ncdump" : "dmp");
+
+    static protected final String DAP4TAG = "#dap4";
+
+    static protected final String[] EMPTY = new String[]{""};
+
+    //////////////////////////////////////////////////
+    // Constants
+
+    static protected final String DATADIR = "src/test/data"; // relative to dap4 root
+    static protected final String TESTDATADIR = DATADIR + "/resources/TestCDMClient";
+    static protected final String BASELINEDIR = TESTDATADIR + "/baseline";
+
+    static protected final String alpha = "abcdefghijklmnopqrstuvwxyz"
+            + "abcdefghijklmnopqrstuvwxyz".toUpperCase();
+
+    //////////////////////////////////////////////////
+    // Type Declarations
+
+    static protected class ClientTest
+    {
+        static protected String root = null;
+        static protected String server = null;
+
+        String title;
+        String dataset;
+        String baselinepath;
+        String[] constraints;
+
+        ClientTest(String dataset)
+        {
+            this(dataset, EMPTY);
+        }
+
+        ClientTest(String dataset, String[] constraints)
+        {
+            this.title = dataset;
+            this.dataset = dataset;
+            this.baselinepath
+                    = root + "/" + BASELINEDIR + "/" + dataset;
+            assert constraints != null && constraints.length > 0;
+            this.constraints = constraints;
+        }
+
+        String makeurl(String ce)
+        {
+            StringBuilder url = new StringBuilder();
+            url.append("http://");
+            url.append(this.server);
+            url.append("/d4ts");
+            url.append("/");
+            url.append(TESTINPUTDIR);
+            url.append("/");
+            url.append(this.dataset);
+            url.append(".");
+            url.append("nc");
+            url.append(DAP4TAG);
+            if(ce != null && ce.length() > 0) {
+                url.append("?");
+                url.append(DapTestCommon.CONSTRAINTTAG);
+                url.append("=");
+                url.append(ce);
+            }
+            return url.toString();
+        }
+
+        public String toString()
+        {
+            StringBuilder buf = new StringBuilder();
+            buf.append(dataset);
+            buf.append("{");
+            if(constraints != null)
+                for(int i = 0; i < constraints.length; i++) {
+                    if(i > 0) buf.append(",");
+                    String ce = constraints[i];
+                    buf.append(ce == null ? "all" : ce);
+                }
+            buf.append("}");
+            return buf.toString();
+        }
+    }
+
+    //////////////////////////////////////////////////
+    // Instance variables
+
+    // Test cases
+
+    protected List<ClientTest> alltestcases = new ArrayList<ClientTest>();
+    protected List<ClientTest> chosentests = new ArrayList<ClientTest>();
+
+    protected String resourceroot = null;
+    protected String datasetpath = null;
+
+    protected String sourceurl = null;
+
+    //////////////////////////////////////////////////
+
+    @Before
+    public void setup() throws Exception
+    {
+        this.resourceroot = getResourceRoot();
+        this.resourceroot = DapUtil.absolutize(this.resourceroot);
+        this.datasetpath = this.resourceroot + "/" + BASELINEDIR;
+        //findServer(this.datasetpath);
+        //this.sourceurl = this.d4tsserver;
+        this.sourceurl = TestDir.dap4TestServer;
+        System.out.println("Using source url " + this.sourceurl);
+        defineAllTestcases(this.resourceroot, this.sourceurl);
+        chooseTestcases();
+    }
+
+    //////////////////////////////////////////////////
+    // Define test cases
+
+    void
+    chooseTestcases()
+    {
+        if(false) {
+            chosentests = locate("test_atomic_array");
+        } else {
+            for(ClientTest tc : alltestcases) {
+                chosentests.add(tc);
+            }
+        }
+    }
+
+    void
+    defineAllTestcases(String root, String server)
+    {
+        ClientTest.root = root;
+        ClientTest.server = server;
+        alltestcases.add(new ClientTest("test_one_var"));
+        alltestcases.add(new ClientTest("test_atomic_types"));
+        alltestcases.add(new ClientTest("test_atomic_array"));
+
+    }
+
+    //////////////////////////////////////////////////
+    // Junit test method
+
+    @Test
+    public void testSerial()
+            throws Exception
+    {
+        for(ClientTest testcase : chosentests) {
+            if(!doOneTest(testcase)) {
+                Assert.assertTrue(false);
+            }
+        }
+    }
+
+    //////////////////////////////////////////////////
+    // Primary test method
+    boolean
+    doOneTest(ClientTest testcase)
+            throws Exception
+    {
+        boolean pass = true;
+        int testcounter = 0;
+
+        System.out.println("Testcase: " + testcase.dataset);
+
+        String[] constraints = testcase.constraints;
+        for(int i = 0; i < constraints.length; i++) {
+            String url = testcase.makeurl(constraints[i]);
+            NetcdfDataset ncfile = null;
+            try {
+                ncfile = openDataset(url);
+            } catch (Exception e) {
+                throw e;
+            }
+
+            String usethisname = UnitTestCommon.extractDatasetname(url,null);
+            String metadata = (NCDUMP ? ncdumpmetadata(ncfile,usethisname) : null);
+            String data = (NCDUMP ? ncdumpdata(ncfile,usethisname) : null);
+
+            if(prop_visual) {
+                visual("DMR: " + url, metadata);
+                visual("DAP: " + url, data);
+            }
+
+            String testoutput = (NCDUMP ? data : metadata + data);
+
+            String baselinefile = String.format("%s.nc.%s",
+                    testcase.baselinepath,
+                    EXTENSION);
+            if(prop_baseline)
+                writefile(baselinefile, testoutput);
+
+            if(prop_diff) { //compare with baseline
+                // Read the baseline file(s)
+                String baselinecontent = readfile(baselinefile);
+                System.out.println("Comparison:");
+                pass = pass && same(getTitle(), baselinecontent, testoutput);
+                System.out.println(pass ? "Pass" : "Fail");
+            }
+        }
+        return pass;
+    }
+
+    //////////////////////////////////////////////////
+    // Dump methods
+
+    String ncdumpmetadata(NetcdfDataset ncfile, String datasetname)
+    {
+        boolean ok = false;
+        String metadata = null;
+        StringWriter sw = new StringWriter();
+
+        StringBuilder args = new StringBuilder("-strict");
+        if(datasetname != null) {
+            args.append(" -datasetname ");
+            args.append(datasetname);
+        }
+
+        // Print the meta-databuffer using these args to NcdumpW
+        ok = false;
+        try {
+            ok = ucar.nc2.NCdumpW.print(ncfile, args.toString(), sw, null);
+        } catch (IOException ioe) {
+            ioe.printStackTrace();
+            ok = false;
+        }
+        try {
+            sw.close();
+        } catch (IOException e) {
+        }
+        ;
+        if(!ok) {
+            System.err.println("NcdumpW failed");
+            System.exit(1);
+        }
+        return sw.toString();
+    }
+
+    String ncdumpdata(NetcdfDataset ncfile, String datasetname)
+    {
+        boolean ok = false;
+        StringWriter sw = new StringWriter();
+
+        StringBuilder args = new StringBuilder("-strict -vall");
+        if(datasetname != null) {
+            args.append(" -datasetname ");
+            args.append(datasetname);
+        }
+
+        // Dump the databuffer
+        sw = new StringWriter();
+        ok = false;
+        try {
+            ok = ucar.nc2.NCdumpW.print(ncfile, args.toString(), sw, null);
+        } catch (IOException ioe) {
+            ioe.printStackTrace();
+            ok = false;
+        }
+        try {
+            sw.close();
+        } catch (IOException e) {
+        }
+        ;
+        if(!ok) {
+            System.err.println("NcdumpW failed");
+            System.exit(1);
+        }
+        return sw.toString();
+    }
+
+    //////////////////////////////////////////////////
+    // Utility methods
+
+
+    // Locate the test cases with given prefix
+    ClientTest
+    locate1(String prefix)
+    {
+        List<ClientTest> tests = locate(prefix);
+        assert tests.size() > 0;
+        return tests.get(0);
+    }
+
+    //Locate the test cases with given prefix and optional constraint
+    List<ClientTest>
+    locate(String prefix)
+    {
+        List<ClientTest> results = new ArrayList<ClientTest>();
+        for(ClientTest ct : this.alltestcases) {
+            if(!ct.dataset.startsWith(prefix))
+                continue;
+            results.add(ct);
+        }
+        return results;
+    }
+
+    static protected boolean
+    report(String msg)
+    {
+        System.err.println(msg);
+        return false;
+    }
+
+} // class TestConstraints
diff --git a/dap4/d4tests/src/test/resources/logback-test.xml b/dap4/d4tests/src/test/resources/logback-test.xml
new file mode 100644
index 0000000000..d24280d3c9
--- /dev/null
+++ b/dap4/d4tests/src/test/resources/logback-test.xml
@@ -0,0 +1,43 @@
+<configuration>
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <!-- Encoders are assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder by default. -->
+        <encoder>
+            <!-- See https://logback.qos.ch/manual/layouts.html#ClassicPatternLayout -->
+            <pattern>%highlight([%d{HH:mm:ss.SSS} %-5level %logger{36}]) %message%n</pattern>
+        </encoder>
+    </appender>
+    
+    <!-- LOOK: Below are two example logging configurations. Use them as references when you need to selectively enable
+         loggers, such as during development/debugging. Please make sure that you revert that config before committing
+         to master; we don't want unnecessary log messages clogging our CI output.
+    -->
+    
+    <!-- Log all messages from the "thredds.featurecollection" family of loggers at level DEBUG or higher to STDOUT.
+    
+         Each of our classes has its own logger, and that logger has the same name as the class itself.
+         So, when we reference the "thredds.featurecollection" logger family, we're configuring the loggers of all
+         classes in the "thredds.featurecollection" package, both main and test.
+         
+         Setting the additivity attribute to "false" prevents messages from being propagated to any logger that is
+         higher in the hierarchy (such as the root logger). We don't want duplicate messages printed to STDOUT.
+    -->
+    <!--
+    <logger name="thredds.featurecollection" level="DEBUG" additivity="false">
+        <appender-ref ref="STDOUT" />
+    </logger>
+    -->
+    
+    <!-- This configuration element is similar to the one above except that it only affects a single logger:
+         the one in thredds.featurecollection.TestFeatureDatasetCapabilitiesXML.
+    -->
+    <!--
+    <logger name="thredds.featurecollection.TestFeatureDatasetCapabilitiesXML" level="DEBUG" additivity="false">
+        <appender-ref ref="STDOUT" />
+    </logger>
+    -->
+    
+    <!-- Log all messages at level WARN or higher to STDOUT. -->
+    <root level="WARN">
+        <appender-ref ref="STDOUT" />
+    </root>
+</configuration>
diff --git a/gradle/any/dependencies.gradle b/gradle/any/dependencies.gradle
index b6a667e186..51e2cde9cc 100644
--- a/gradle/any/dependencies.gradle
+++ b/gradle/any/dependencies.gradle
@@ -67,16 +67,15 @@ libraries["jruby-gradle-plugin"] = "com.github.jruby-gradle:jruby-gradle-plugin:
 
 versions["spring"] = "4.3.20.RELEASE"
 
-//libraries["spring-core"] = "org.springframework:spring-core:${versions["spring"]}"
-
+// d4test and ui(?)
 libraries["spring-context"] = "org.springframework:spring-context:${versions["spring"]}"
 
-//libraries["spring-beans"] = "org.springframework:spring-beans:${versions["spring"]}"
-//
-//libraries["spring-web"] = "org.springframework:spring-web:${versions["spring"]}"
-//
-//libraries["spring-webmvc"] = "org.springframework:spring-webmvc:${versions["spring"]}"
-//
+// d4test
+libraries["spring-core"] = "org.springframework:spring-core:${versions["spring"]}"
+libraries["spring-beans"] = "org.springframework:spring-beans:${versions["spring"]}"
+libraries["spring-web"] = "org.springframework:spring-web:${versions["spring"]}"
+libraries["spring-webmvc"] = "org.springframework:spring-webmvc:${versions["spring"]}"
+
 //////////////////////////////////////////// Spring security //////////////////////////////////////////
 //
 //versions["spring-security"] = "4.2.12.RELEASE"
@@ -119,11 +118,14 @@ libraries["logback-classic"] = "ch.qos.logback:logback-classic:1.2.3"
 
 //////////////////////////////////////////// Testing //////////////////////////////////////////
 
+// d4tests
+libraries["spring-test"] = "org.springframework:spring-test:${versions["spring"]}"
+
 libraries["junit"] = "junit:junit:4.12"
 
 libraries["JUnitParams"] = "pl.pragmatists:JUnitParams:1.0.5"
 
-//libraries["spring-test"] = "org.springframework:spring-test:${versions["spring"]}"
+
 //
 //libraries["hamcrest-core"] = "org.hamcrest:hamcrest-core:1.3"
 
diff --git a/gradle/any/gretty.gradle b/gradle/any/gretty.gradle
index 2275dfb616..1cbc5e2b7f 100644
--- a/gradle/any/gretty.gradle
+++ b/gradle/any/gretty.gradle
@@ -66,6 +66,14 @@ gretty {
     }
 }
 
+farm {
+    // used by :dap4 test
+    webapp 'edu.ucar:d4ts:5.0.0-SNAPSHOT', contextPath: '/d4ts'
+    // :opendap and :httpservices test.
+    webapp 'edu.ucar:dtswar:5.0.0-SNAPSHOT', contextPath: '/dts'
+    integrationTestTask = 'test'
+}
+
 /**
  * Overlay the named project onto this project and apply its Gretty config to this project as well. The named project
  * is expected to have a property named 'grettyConfig' that modifies a org.akhikhl.gretty.GrettyExtension object.
diff --git a/gradle/root/sonarqube.gradle b/gradle/root/sonarqube.gradle
index d9c79c9645..315962d27e 100644
--- a/gradle/root/sonarqube.gradle
+++ b/gradle/root/sonarqube.gradle
@@ -99,50 +99,6 @@ gradle.projectsEvaluated {
         }
     }
     
-    /*
-     * :opendap is a module with both source code and a child module. Due to SONARGRADL-5, it will not be analyzed by
-     * Sonar. Again, only "leaf" modules are allowed to have source code. So, if we want both :opendap and
-     * :opendap:dtswar to be analyzed, we must merge them together into one leaf module.
-     *
-     * We do this by assigning all of dtswar's sources, binaries, and libraries to opendap, and then setting dtswar's
-     * "skipProject" property to "true". This effectively deletes dtswar from the the module structure, leaving
-     * opendap as a leaf.
-     */
-    project(":opendap") {
-        sonarqube {
-            properties {
-                // Due to the deferred evaluation of this SonarQubeProperties Action (see https://goo.gl/skuBHE),
-                // many of dtswar's Sonar properties (such as ":opendap:dtswar.sonar.sources") aren't available here.
-                // So, we have to come up with those values ourselves. See https://goo.gl/sAKb3j
-                SourceSetContainer dtswarSourceSets = rootProject.project(":opendap:dtswar").sourceSets
-    
-                // Merge dtswar's source code into opendap's source code.
-                def sources = files(properties["sonar.sources"] ?: [],
-                        dtswarSourceSets.main.allSource.srcDirs ?: [], // :opendap:dtswar.sonar.sources
-                        dtswarSourceSets.test.allSource.srcDirs ?: []  // :opendap:dtswar.sonar.tests
-                ).flatten()
-                properties["sonar.sources"] = nukeDupesAndNonExistent(sources)
-    
-                // Merge dtswar's binaries into opendap's binaries.
-                def binaries = files(properties["sonar.java.binaries"] ?: [],
-                        dtswarSourceSets.main.output.classesDir ?: [], // :opendap:dtswar.sonar.java.binaries
-                        dtswarSourceSets.test.output.classesDir ?: []  // :opendap:dtswar.sonar.java.test.binaries
-                ).flatten()
-                properties["sonar.java.binaries"] = nukeDupesAndNonExistent(binaries)
-    
-                // Merge dtswar's libraries into opendap's libraries.
-                def libraries = files(properties["sonar.java.libraries"] ?: [],
-                        dtswarSourceSets.main.compileClasspath ?: [], // :opendap:dtswar.sonar.java.libraries
-                        dtswarSourceSets.test.compileClasspath ?: []  // :opendap:dtswar.sonar.java.test.libraries
-                ).flatten()
-                properties["sonar.java.libraries"] = nukeDupesAndNonExistent(libraries)
-            }
-        }
-    }
-    
-    // Causes :opendap to become a leaf module.
-    project(":opendap:dtswar").sonarqube.skipProject = true
-    
     boolean debug = false
     
     tasks.sonarqube {
diff --git a/httpservices/build.gradle b/httpservices/build.gradle
index 2f1f9a4984..a032517a6e 100755
--- a/httpservices/build.gradle
+++ b/httpservices/build.gradle
@@ -18,9 +18,7 @@ dependencies {
     testRuntime libraries["logback-classic"]
 }
 
-gretty {
-    // We're going to simply use dtswar as an endpoint for our HTTP tests.
-    overlayAndApplyConfigOf ':opendap:dtswar'
-    
-    integrationTestTask = 'test'
+test {
+    dependsOn("farmBeforeIntegrationTest")
+    finalizedBy("farmAfterIntegrationTest")
 }
diff --git a/opendap/build.gradle b/opendap/build.gradle
index 8a52940643..2341c48ec3 100644
--- a/opendap/build.gradle
+++ b/opendap/build.gradle
@@ -30,8 +30,7 @@ dependencies {
     testCompile libraries["JUnitParams"]
 }
 
-gretty {
-    overlayAndApplyConfigOf ':opendap:dtswar'
-    
-    integrationTestTask = 'test'
+test {
+    dependsOn("farmBeforeIntegrationTest")
+    finalizedBy("farmAfterIntegrationTest")
 }
diff --git a/opendap/dtswar/build.gradle b/opendap/dtswar/build.gradle
index b83ac0af22..fa2b667866 100644
--- a/opendap/dtswar/build.gradle
+++ b/opendap/dtswar/build.gradle
@@ -20,12 +20,4 @@ dependencies {
     compile libraries["slf4j-api"]
     runtime libraries["log4j-slf4j-impl"]
     runtime libraries["log4j-web"]
-}
-
-// This will be used by :dtswar, :opendap, and :httpservices.
-ext.grettyConfig = {
-    httpPort = 8082
-    contextPath = '/dts'
-}
-
-gretty grettyConfig
+}
\ No newline at end of file
diff --git a/opendap/src/test/data/baselinemisc/test.02.cdl b/opendap/src/test/data/baselinemisc/test.02.cdl
index a50f0465a8..b66aa95c18 100755
--- a/opendap/src/test/data/baselinemisc/test.02.cdl
+++ b/opendap/src/test/data/baselinemisc/test.02.cdl
@@ -1,4 +1,4 @@
-netcdf dods://localhost:8082/dts/test.02 {
+netcdf dods://localhost:8080/dts/test.02 {
   variables:
     ubyte b(25);
 
diff --git a/opendap/src/test/data/baselinemisc/test.22ce.cdl b/opendap/src/test/data/baselinemisc/test.22ce.cdl
index 876ff3e418..998d3e1160 100644
--- a/opendap/src/test/data/baselinemisc/test.22ce.cdl
+++ b/opendap/src/test/data/baselinemisc/test.22ce.cdl
@@ -1,4 +1,4 @@
-netcdf dods://localhost:8082/dts/test.22?exp.ThreeD[5:1:7][5:8][1:3] {
+netcdf dods://localhost:8080/dts/test.22?exp.ThreeD[5:1:7][5:8][1:3] {
   dimensions:
     x = 3;
     y = 4;
diff --git a/opendap/src/test/java/opendap/test/TestSources.java b/opendap/src/test/java/opendap/test/TestSources.java
index acc3aed6b1..8d2c4780e3 100644
--- a/opendap/src/test/java/opendap/test/TestSources.java
+++ b/opendap/src/test/java/opendap/test/TestSources.java
@@ -159,5 +159,4 @@ protected void setup()
         set.tests = X1;
         TestSets.put(TestSetEnum.Experimental, set);
     }
-
 }
diff --git a/settings.gradle b/settings.gradle
index a198260c6f..2019fc31d0 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -9,13 +9,13 @@ include 'clcommon'
 include 'dap4:d4core'
 include 'dap4:d4lib'
 include 'dap4:d4cdm'
+include 'dap4:d4tests'
 include 'docs'
 include 'grib'
 include 'httpservices'
 include 'legacy'
 include 'netcdf4'
 include 'opendap'
-include 'opendap:dtswar'
 include 'testUtil'
 include 'udunits'
 include 'ui'
diff --git a/testUtil/src/main/java/ucar/unidata/util/test/TestDir.java b/testUtil/src/main/java/ucar/unidata/util/test/TestDir.java
index aabc8085ef..887f019186 100644
--- a/testUtil/src/main/java/ucar/unidata/util/test/TestDir.java
+++ b/testUtil/src/main/java/ucar/unidata/util/test/TestDir.java
@@ -87,13 +87,13 @@ public class TestDir {
 
   static public String dap2TestServerPropName = "dts";
 
-  static public String dap2TestServer = "localhost:8082";
+  static public String dap2TestServer = "localhost:8080";
 
   // DAP4 Test server (for testing)
 
   static public String dap4TestServerPropName = "d4ts";
 
-  static public String dap4TestServer = "localhost:8083";
+  static public String dap4TestServer = "localhost:8080";
 
   //////////////////////////////////////////////////
 
