[med-svn] [sra-sdk] 01/07: New upstream version 2.8.2-3+dfsg

Andreas Tille tille at debian.org
Thu Oct 19 22:15:21 UTC 2017


This is an automated email from the git hooks/post-receive script.

tille pushed a commit to branch master
in repository sra-sdk.

commit 03cd16f2ed4af0969306801d3de69f587d2d4693
Author: Andreas Tille <tille at debian.org>
Date:   Thu Oct 19 23:58:11 2017 +0200

    New upstream version 2.8.2-3+dfsg
---
 CHANGES.md                                         |  30 ++
 build/Makefile.vers                                |   2 +-
 setup/konfigure.perl                               |  96 +++--
 shared/toolkit.vers                                |   2 +-
 shared/toolkit.vers.h                              |   2 +-
 test/Makefile                                      |   1 +
 test/dbgap-mount/jaba/App.java                     | 212 ++++++++++
 test/dbgap-mount/jaba/AppTerminator.java           |  11 +
 test/dbgap-mount/jaba/DbGapMountTest.java          |  54 +++
 test/dbgap-mount/jaba/DbGapMountTestEnv.java       | 242 +++++++++++
 test/dbgap-mount/jaba/Utils.java                   | 396 +++++++++++++++++
 test/dbgap-mount/jaba/WrapCmd.java                 | 280 ++++++++++++
 test/dbgap-mount/jaba/platform/Platform.java       |  85 ++++
 test/dbgap-mount/jaba/platform/PlatformLinux.java  |  33 ++
 test/dbgap-mount/jaba/platform/PlatformMac.java    |  40 ++
 test/dbgap-mount/jaba/platform/PlatformSuper.java  | 166 ++++++++
 test/dbgap-mount/jaba/platform/PlatformWin.java    |  78 ++++
 test/dbgap-mount/jaba/test/Test.java               |  30 ++
 test/dbgap-mount/jaba/test/TestBasicBase.java      | 120 ++++++
 test/dbgap-mount/jaba/test/TestFunctionality.java  |  97 +++++
 .../jaba/test/TestRunStopBadConfig.java            |  92 ++++
 test/dbgap-mount/jaba/test/TestRunStopDaemon.java  | 124 ++++++
 .../jaba/test/TestRunStopGoodConfig.java           | 106 +++++
 .../dbgap-mount/jaba/test/TestRunStopNoConfig.java |  92 ++++
 .../jaba/test/TestRunStopNoParameters.java         |  87 ++++
 test/dbgap-mount/jaba/test/TestSuper.java          | 467 +++++++++++++++++++++
 test/dbgap-mount/jaba/test/TestWorkspace.java      | 179 ++++++++
 test/dbgap-mount/jaba/test/Tests.java              | 171 ++++++++
 test/dbgap-mount/py/main.py                        |  17 +
 test/dbgap-mount/py/platform/__init__.py           |  14 +
 test/dbgap-mount/py/platform/base.py               | 123 ++++++
 test/dbgap-mount/py/platform/lin.py                |   9 +
 test/dbgap-mount/py/platform/mac.py                |  12 +
 test/dbgap-mount/py/platform/win.py                |  33 ++
 test/dbgap-mount/py/test/__init__.py               |   7 +
 test/dbgap-mount/py/test/base.py                   | 160 +++++++
 test/dbgap-mount/py/test/test.py                   | 125 ++++++
 test/dbgap-mount/py/test/utils.py                  |  79 ++++
 test/general-loader/Makefile                       |   2 +
 .../VDB-3250}/Makefile                             |  57 ++-
 test/general-loader/VDB-3250/check_test_result.cpp | 385 +++++++++++++++++
 test/general-loader/VDB-3250/prepare_test_data.cpp | 257 ++++++++++++
 test/general-loader/VDB-3250/prepare_test_data.sh  | 190 +++++++++
 test/general-loader/VDB-3250/test_data.bin         | Bin 0 -> 122136 bytes
 test/general-loader/VDB-3250/test_data.vschema     |  65 +++
 test/sra-pileup/Makefile                           |  18 +
 test/sra-pileup/test_all_sam_dump_has_spotgroup.py |  92 ++++
 .../sra-pileup/test_diff_fastq_dump_vs_sam_dump.py | 245 +++++++++++
 build/Makefile.vers => test/vdb-config/Makefile    |  13 +-
 test/vdb-config/test-vdb-config.pl                 |  12 +
 tools/bam-loader/bam.c                             |   2 +
 tools/bam-loader/loader-imp.c                      |  10 +
 tools/bam-loader/sam.l                             | 172 ++++++++
 tools/bam-loader/sam.y                             | 396 +++++++++++++++++
 tools/bam-loader/samview.c                         |   1 +
 tools/general-loader/general-loader.hpp            |   2 +-
 tools/general-loader/protocol-parser.cpp           |   2 +-
 tools/prefetch/prefetch.c                          |  16 +-
 tools/sra-dump/fastq.c                             |   4 +-
 tools/sra-pileup/sam-aligned.c                     |   2 +-
 tools/sra-pileup/sam-unaligned.c                   |  96 ++++-
 tools/sra-stat/sra-stat.c                          |  69 ++-
 tools/util/pseudo-aligner.cpp                      |  35 +-
 tools/util/test-sra.c                              | 356 +++++++++++-----
 tools/vdb-config/configure.cpp                     |  52 ++-
 tools/vdb-config/util.cpp                          | 108 +++--
 tools/vdb-config/util.hpp                          |   5 +
 tools/vdb-config/vdb-config-model.cpp              |  25 +-
 tools/vdb-config/vdb-config.c                      |  86 ++--
 69 files changed, 6350 insertions(+), 299 deletions(-)

diff --git a/CHANGES.md b/CHANGES.md
index e30b783..9f02e9e 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,6 +1,36 @@
 # NCBI External Developer Release:
 
 
+## SRA Toolkit 2.8.2
+**March 6, 2017**
+
+  **blast**: Updated blast library to be able to process runs having empty rows  
+  **blast, build**: removed library dependencies that were preventing users from launching these tools  
+  **blast, sra-tools**: Prepared completely static build of blast tools for windows with HTTPS support  
+  **build**: **bam-load**: changed memcpy to memmove when regions overlap - seems to corrupt data on centos7  
+  **build**: Added ability to specify ncbi-vdb/configure --with-magic-prefix. Look for libraries in (lib lib64) when running "configure --with-...-prefix"  
+  **build**: configure detects location of ngs libraries  
+  **build**: configure was fixed to skip options unrecognized by gcc 4.4.7  
+  **build**: created sra-toolkit Debian package  
+  **build**: fixed a bug in 'configure' when in could not find source files in repository saved with non-standard name  
+  **build, ncbi-vdb, sra-tools**: installation will back up old configuration files if they differ from the ones being installed  
+  **cg-load**: added loading of CG File format v2.4  
+  **kns**: SRA tools respect standard set of environment variables for proxy specification  
+  **kns**: updated mbedtls library to version 2.4.1  
+  **ncbi-vdb, ngs, ngs-tools, sra-tools**: eliminated memcpy from sources due to potential for overlap  
+  **ngs, sra-search**: now supports search on reference  
+  **ngs-tools**: updated the NCBI download page to incorporate ngs versions into 3rd party package names  
+  **prefetch**: Fixed error message "path excessive while opening directory" when prefetch is trying to get vdbcache  
+  **prefetch**: Fixed regression in prefetch-2.8.1 when downloading dbGaP files via HTTP  
+  **prefetch**: Fixed regression in prefetch-2.8.1 when downloading vdbcache files from dbGaP via HTTP  
+  **sam-dump**: consistency of sam-dump in fastq-mod improved  
+  **sam-dump**: consistency of sam-dump in fastq-mode improved  
+  **sra-stat**: sra-stat does XML-escaping when printing spot-groups  
+  **test-sra**: extended test-sra to debug user problems with https connections to NCBI  
+  **test-sra**: test-sra print amount of available disk space in user repositories  
+  **vdb-config**: vdb-config correctly works when there is non-canonical path in configuration  
+
+
 ## SRA Toolkit 2.8.1-2
 **January 19, 2017**
 
diff --git a/build/Makefile.vers b/build/Makefile.vers
index 453b9a2..eb46295 100644
--- a/build/Makefile.vers
+++ b/build/Makefile.vers
@@ -23,4 +23,4 @@
 # ===========================================================================
 
 # SRA-TOOLS and library version
-VERSION = 2.8.1
+VERSION = 2.8.2
diff --git a/setup/konfigure.perl b/setup/konfigure.perl
index 5568cdd..1f44407 100644
--- a/setup/konfigure.perl
+++ b/setup/konfigure.perl
@@ -438,7 +438,8 @@ my @dependencies;
 my %DEPEND_OPTIONS;
 foreach my $href (DEPENDS()) {
     $_ = $href->{name};
-    my ($I, $L) = ($href->{Include});
+    my $I = $href->{Include};
+    my @L;
     my $o = "with-$_-prefix";
     ++$DEPEND_OPTIONS{$o};
     if ($OPT{$o}) {
@@ -448,9 +449,10 @@ foreach my $href (DEPENDS()) {
             my $t = File::Spec->catdir($I, 'libxml2');
             $I = $t if (-e $t);
         }
-        $L = File::Spec->catdir($OPT{$o}, 'lib');
+        push ( @L, File::Spec->catdir($OPT{$o}, 'lib') );
+        push ( @L, File::Spec->catdir($OPT{$o}, 'lib64') );
     }
-    my ($i, $l) = find_lib($_, $I, $L);
+    my ($i, $l) = find_lib($_, $I, @L);
     if (defined $i || $l) {
         my $d = 'HAVE_' . uc($_) . ' = 1';
         push @dependencies, $d;
@@ -485,6 +487,7 @@ foreach my $href (@REQ) {
     my $need_build = $a{type} =~ /B/;
     my $need_lib = $a{type} =~ /L|D/;
     my $need_itf = ! ($a{type} =~ /D/ || $a{type} =~ /E/ || $a{type} =~ /J/);
+    $need_itf = 1 if ($a{type} =~ /I/);
     my $need_jar = $a{type} =~ /J/;
 
     my ($bin, $inc, $lib, $ilib, $src)
@@ -1442,17 +1445,33 @@ sub check_tool {
     }
 }
 
-sub check_no_array_bounds {
-    check_compiler('O', '-Wno-array-bounds');
-}
-
 sub check_static_libstdcpp {
     my $option = '-static-libstdc++';
-    my $save = $TOOLS;
-    $TOOLS = $CPP;
-    $_ = check_compiler('O', $option);
-    $TOOLS = $save;
-    $_ ? $option : ''
+
+    print "checking whether $CPP accepts $option... ";
+
+    my $log = 'int main() {}\n';
+    my $cmd = $log;
+    $cmd =~ s/\\n/\n/g;
+    my $gcc = "echo -e '$log' | $CPP -xc $option - 2>&1";
+    print "\n\t\trunning $gcc\n" if ($OPT{'debug'});
+    my $out = `$gcc`;
+    my $ok = $? == 0;
+    if ( $ok && $out ) {
+        $ok = 0 if ( $out =~ /unrecognized option '-static-libstdc\+\+'/ );
+    }
+    print "$out\t" if ($OPT{'debug'});
+    println $ok ? 'yes' : 'no';
+
+    unlink 'a.out';
+
+    return '' if (!$ok);
+
+    return $option;
+}
+
+sub check_no_array_bounds {
+    check_compiler('O', '-Wno-array-bounds');
 }
 
 sub find_lib {
@@ -1460,7 +1479,7 @@ sub find_lib {
 }
 
 sub check_compiler {
-    my ($t, $n, $i, $l) = @_;
+    my ($t, $n, $I, @l) = @_;
     my $tool = $TOOLS;
 
     if ($t eq 'L') {
@@ -1506,37 +1525,54 @@ sub check_compiler {
             return;
         }
 
-        if ($i && ! -d $i) {
-            print "'$i': " if ($OPT{'debug'});
+        if ($I && ! -d $I) {
+            print "'$I': " if ($OPT{'debug'});
             println 'no';
             return;
         }
-        if ($l && ! -d $l) {
-            print "'$l': " if ($OPT{'debug'});            println 'no';
-            return;
+
+        for ( my $i = 0; $i <= $#l; ++ $i ) {
+            print "'$l[$i]': " if ($OPT{'debug'});
+            if ( $l [ $i ] ) {
+                if ( -d $l [ $i ] ) {
+                    last;
+                } elsif ( $i ==  $#l ) {
+                    println 'no';
+                    return;
+                }
+            }
         }
 
         my $cmd = $log;
         $cmd =~ s/\\n/\n/g;
 
-        my $gcc = "| $tool -xc $flags " . ($i ? "-I$i " : ' ')
+        push ( @l, '' ) unless ( @l );
+        for my $i ( 0 .. $#l ) {
+            my $l = $l [ $i ];
+            next if ( $l && ! -d $l );
+            my $gcc = "| $tool -xc $flags " . ($I ? "-I$I " : ' ')
                                       . ($l ? "-L$l " : ' ') . "- $library";
-        $gcc .= ' 2> /dev/null' unless ($OPT{'debug'});
+            $gcc .= ' 2> /dev/null' unless ($OPT{'debug'});
 
-        open GCC, $gcc or last;
-        print "\n\t\trunning echo -e '$log' $gcc\n" if ($OPT{'debug'});
-        print GCC "$cmd" or last;
-        my $ok = close GCC;
-        print "\t" if ($OPT{'debug'});
-        println $ok ? 'yes' : 'no';
+            open GCC, $gcc or last;
+            print "\n\t\trunning echo -e '$log' $gcc\n" if ($OPT{'debug'});
+            print GCC "$cmd" or last;
+            my $ok = close GCC;
+            print "\t" if ($OPT{'debug'});
+            if ( $ok ) {
+                println 'yes';
+            } else {
+                println 'no' if ( $i == $#l );
+            }
 
-        unlink 'a.out';
+            unlink 'a.out';
 
-        return if (!$ok);
+            return if ( ! $ok && ( $i == $#l ) );
 
-        return 1 if ($t eq 'O');
+            return 1 if ($t eq 'O');
 
-        return ($i, $l);
+            return ($I, $l) if ( $ok) ;
+        }
     }
 
     println "cannot run $tool: skipped";
diff --git a/shared/toolkit.vers b/shared/toolkit.vers
index dbe5900..1817afe 100644
--- a/shared/toolkit.vers
+++ b/shared/toolkit.vers
@@ -1 +1 @@
-2.8.1
+2.8.2
diff --git a/shared/toolkit.vers.h b/shared/toolkit.vers.h
index fd7da80..39e795b 100644
--- a/shared/toolkit.vers.h
+++ b/shared/toolkit.vers.h
@@ -1 +1 @@
-#define TOOLKIT_VERS 0x02080001
+#define TOOLKIT_VERS 0x02080002
diff --git a/test/Makefile b/test/Makefile
index 9f6464b..ae67bbe 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -35,6 +35,7 @@ include $(TOP)/build/Makefile.config
 # default
 #
 SUBDIRS =    \
+	vdb-config      \
 	fastq-loader    \
 	vcf-loader      \
 	kget            \
diff --git a/test/dbgap-mount/jaba/App.java b/test/dbgap-mount/jaba/App.java
new file mode 100644
index 0000000..70a9912
--- /dev/null
+++ b/test/dbgap-mount/jaba/App.java
@@ -0,0 +1,212 @@
+package jaba;
+
+import java.lang.Thread;
+import java.lang.Runnable;
+import java.lang.Process;
+import jaba.platform.Platform;
+import jaba.DbGapMountTestEnv;
+import java.io.InputStreamReader;
+
+public
+class
+App {
+
+private String _command = null;
+private String [] _env = null;
+private AppTerminator _terminator = null;
+
+private Thread _thread = null;
+private Process _process = null;
+
+private int _exitStatus = 0;
+private boolean _finished = false;
+private boolean _terminated = false;
+
+public
+App ( String command, String [] env )
+{
+    this ( command, env, null );
+}   /* App () */
+
+public
+App ( String command, String [] env, AppTerminator terminator )
+{
+    if ( command == null ) {
+        throw new RuntimeException ( "Application command is not defined" );
+    }
+
+    _command = command;
+    _env = env;
+    _terminator = terminator;
+
+    _thread = null;
+    _process = null;
+
+    _exitStatus = 0;
+    _finished = false;
+    _terminated = false;
+}   /* App () */
+
+private
+void
+runApp ()
+{
+    _exitStatus = 0;
+    _finished = false;
+    _terminated = false;
+
+    try {
+        _process = Runtime.getRuntime ().exec ( _command, _env );
+        if ( _process == null ) {
+            throw new RuntimeException ( "Can not run command [" + _command + "]" );
+        }
+
+        _process.waitFor ();
+
+        _exitStatus = _process.exitValue ();
+    }
+    catch ( Throwable Th ) {
+        System.err.println ( "App failed because: " + Th.toString () );
+
+        if ( _process != null ) {
+            stopApp ();
+        }
+        _exitStatus = 666;
+    } 
+
+    _finished = true;
+}   /* runApp () */
+
+protected
+void
+stopApp ()
+{ 
+    if ( isRunning () ) {
+        System.out.println ( "Terminating application [" + _command + "]" );
+        boolean FailedTerminate = _terminator != null
+                                    ? _terminator.gentleTerminate ()
+                                    : false
+                                    ;
+        if ( FailedTerminate ) {
+            _process.destroy ();
+        }
+    }
+}   /* stopApp () */
+
+public
+InputStreamReader
+getOutStream ()
+{
+    synchronized ( this ) {
+        if ( _process == null ) {
+            throw new RuntimeException ( "Can not get OutStream for NULL process" );
+        }
+
+        return new InputStreamReader( _process.getInputStream () );
+    }
+}   /* getOutStream () */
+
+public
+InputStreamReader
+getErrStream ()
+{
+    synchronized ( this ) {
+        if ( _process == null ) {
+            throw new RuntimeException ( "Can not get ErrStream for NULL process" );
+        }
+
+        return new InputStreamReader( _process.getErrorStream () );
+    }
+}   /* getErrStream () */
+
+public
+boolean
+isRunning ()
+{
+    synchronized ( this ) {
+        return _process != null && _finished == false;
+    }
+}   /* isRunning () */
+
+public
+void
+start ()
+{
+    start ( 0 );
+}   /* start () */
+
+public
+void
+start ( long timeoutSec )
+{
+    synchronized ( this ) {
+        if ( _thread != null ) {
+            throw new RuntimeException ( "Can not start allready running App" );
+        }
+        _thread = new Thread ( new Runnable () { public void run () { runApp (); } } );
+
+        _thread.start ();
+    }
+
+    if ( timeoutSec != 0 ) {
+        try {
+            Thread thread = new Thread (
+                                new Runnable () {
+                                    public
+                                    void
+                                    run ()
+                                    {
+                                        Utils.sleepSec ( timeoutSec );
+                                        stopApp ();
+                                    };
+                                }
+                            );
+            thread.start ();
+            thread = null;
+        }
+        catch ( Throwable Th ) {
+            System.out.println ( Th.toString () );
+        }
+    }
+}   /* start () */
+
+public
+void
+stop ()
+{
+    synchronized ( this ) {
+        if ( _thread == null ) { 
+            throw new RuntimeException ( "Can not stop allready stopped App" );
+        }
+
+        stopApp ();
+
+        _thread = null;
+    }
+}   /* stop () */
+
+public
+void
+waitFor ()
+{
+    try {
+            /* No check for NULL, cuz ... we eat everything */
+        _thread.join ();
+    }
+    catch ( Throwable Th ) {
+        throw new RuntimeException ( "Can not wait: " + Th.toString () );
+    }
+}   /* waitFor () */
+
+public
+int
+exitStatus ()
+{
+    if ( isRunning () ) {
+        throw new RuntimeException ( "Can not get exit status from running application" );
+    }
+
+    return _terminated ? 111 : _exitStatus;
+}   /* exitStatus () */
+
+};
diff --git a/test/dbgap-mount/jaba/AppTerminator.java b/test/dbgap-mount/jaba/AppTerminator.java
new file mode 100644
index 0000000..18290f9
--- /dev/null
+++ b/test/dbgap-mount/jaba/AppTerminator.java
@@ -0,0 +1,11 @@
+package jaba;
+
+public
+interface
+AppTerminator {
+
+public
+boolean
+gentleTerminate ();
+
+};
diff --git a/test/dbgap-mount/jaba/DbGapMountTest.java b/test/dbgap-mount/jaba/DbGapMountTest.java
new file mode 100644
index 0000000..d6d66da
--- /dev/null
+++ b/test/dbgap-mount/jaba/DbGapMountTest.java
@@ -0,0 +1,54 @@
+package jaba;
+
+import jaba.platform.Platform;
+import jaba.test.Tests;
+// import jaba.test.Test;
+
+public
+class
+DbGapMountTest {
+
+public static
+void
+main( String args [] )
+{
+    try {
+        if ( args.length != 1 ) {
+            System.out.println ( "Invalid arguments" );
+
+            printHelp ();
+
+            throw new RuntimeException ( "Invalid arguments" );
+        }
+
+        String ExeDir = args [ 0 ];
+
+        Platform Plt = Platform.getPlatform ( ExeDir );
+
+        Tests tests = new Tests ( Plt );
+
+        tests.run ();
+    }
+    catch ( Exception Expt ) {
+        Expt.printStackTrace ();
+    }
+}
+
+public static
+void
+printHelp ()
+{
+        /* Not sure what is better :LOL: */
+    String className = new Object() { }.getClass().getEnclosingClass().getName ();
+    // String className = new Object() { }.getClass().getEnclosingClass().getSimpleName ();
+
+    System.out.format (
+                        "\nSyntax: java %s bin_directory\n",
+                        className
+                        );
+    System.out.format (
+                        "\nWhere:\n\nbin_directory - is directory containing these utilites:\n                dbgap-mount-too, vdb-config, fasq-dump\n\n"
+                        );
+}   /* printHelp () */
+
+};
diff --git a/test/dbgap-mount/jaba/DbGapMountTestEnv.java b/test/dbgap-mount/jaba/DbGapMountTestEnv.java
new file mode 100644
index 0000000..b1245ae
--- /dev/null
+++ b/test/dbgap-mount/jaba/DbGapMountTestEnv.java
@@ -0,0 +1,242 @@
+package jaba;
+
+import jaba.platform.Platform;
+
+import java.nio.file.*;
+import java.io.OutputStream;
+import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+
+public
+class 
+DbGapMountTestEnv {
+
+private Platform _platform = null;
+
+public enum EnvType { Undef, NoConf, BadConf, GoodConf };
+private EnvType envType = EnvType.Undef;
+
+private String pathSeparator = null;
+
+private String vdbConfig = null;
+private String mountTool = null;
+private String fastqDump = null;
+
+
+public
+DbGapMountTestEnv ( Platform Platform )
+{
+    if ( Platform == null ) {
+        throw new RuntimeException ( "Undefined platform" );
+    }
+
+    _platform  = Platform;
+}   /* DbGapMountTestEnv () */
+
+public
+void
+createTestEnv ( EnvType EnvType )
+{
+    if ( envType != EnvType.Undef ) {
+        throw new RuntimeException ( "Can not create environment. Clear old first" );
+    }
+
+    if ( _platform == null ) {
+        throw new RuntimeException ( "Can not create environment. NULL Platform or BinDir passed" );
+    }
+
+    pathSeparator = System.getProperty ( "file.separator" );
+
+        /*  Removing data from previous experiments
+         */
+    Utils.unlink ( _platform.getTestDir () );
+
+        /*  Checking existance necessary files
+         */
+    checkExecutables ();
+
+        /*  Checking existance necessary other files
+         */
+    checkInputs ();
+
+        /*  Creating file tree
+         */
+    makeFileTree ();
+
+        /*  Configuring ();
+         */
+    configure ( EnvType );
+}   /* createTestEnv () */
+
+public
+void
+clearTestEnv ()
+{
+    if ( envType == EnvType.Undef ) {
+        return;
+    }
+
+    if ( _platform == null ) {
+        throw new RuntimeException ( "Can not clear environment. NULL Platform or BinDir passed" );
+    }
+
+        /*  Removing unnecessary data
+         */
+    Utils.unlink ( _platform.getTestDir () );
+
+    envType = EnvType.Undef;
+
+}   /* clearTestEnv () */
+
+private
+void
+makeFileTree ()
+{
+    System.out.format ( "Making file tree\n" );
+
+    Utils.mkdir (
+                _platform.getTestDir ()
+                );
+    Utils.mkdir (
+                _platform.getTarget ( Platform.TargetName.ConfigDir )
+                );
+    Utils.mkdir (
+                _platform.getTarget ( Platform.TargetName.DataDir )
+                );
+    Utils.mkdir (
+                _platform.getTarget ( Platform.TargetName.TempDir )
+                );
+    if ( _platform.needCreateMountPoint () ) {
+        Utils.mkdir (
+                _platform.getTarget ( Platform.TargetName.MountPoint )
+                );
+    }
+    else {
+        System.out.format ( "Does not need mount point to exist [%s]\n", _platform.getTarget ( Platform.TargetName.MountPoint ) ); 
+    }
+}   /* makeFileTree () */
+
+private 
+void
+checkExecutables ()
+{
+    System.out.format ( "Checking executables\n" );
+
+    Utils.checkExecutable (
+                _platform.getTarget ( Platform.TargetName.MountApp )
+                );
+    Utils.checkExecutable (
+                _platform.getTarget ( Platform.TargetName.ConfigApp )
+                );
+    Utils.checkExecutable (
+                _platform.getTarget ( Platform.TargetName.DumpApp )
+                );
+}   /* checkExecutables () */
+
+private
+void
+checkInputs ()
+{
+    System.out.format ( "Checking inputs\n" );
+
+    Utils.checkExists (
+                _platform.getTarget ( Platform.TargetName.NgcFile )
+                );
+    Utils.checkExists (
+                _platform.getTarget ( Platform.TargetName.KartFile )
+                );
+}   /* checkInputs () */
+
+private
+void
+configure ( EnvType Type )
+{
+    System.out.format ( "Configuring\n" );
+
+    if ( _platform == null ) {
+        throw new RuntimeException ( "Can not configure environment. NULL Platform or BinDir passed" );
+    }
+
+    if ( Type == EnvType.Undef ) {
+        throw new RuntimeException ( "Invalid environment type passed" );
+    }
+
+    envType = Type;
+
+    if ( envType == EnvType.NoConf ) {
+        /*  just return
+         */
+        return;
+    }
+
+        /*  Here we do create config file
+         */
+    try {
+        String ThePath = _platform.getTarget (
+                                    Platform.TargetName.ConfigFile
+                                    );
+        OutputStream Out = new BufferedOutputStream (
+                        Files.newOutputStream (
+                                Paths.get ( ThePath ),
+                                StandardOpenOption.CREATE,
+                                StandardOpenOption.TRUNCATE_EXISTING
+                                )
+                        );
+        String Jojoba = "## auto-generated configuration file - DO NOT EDIT ##\n\n";
+        byte Bytes [] = Jojoba.getBytes ();
+
+        Out.write ( Bytes, 0, Bytes.length );
+
+        Jojoba = "/repository/user/default-path = \""
+                    + Utils.pathToPosix ( _platform.getTarget ( Platform.TargetName.DataDir ) )
+                    + "\"\n"
+                    ;
+        Bytes = Jojoba.getBytes ();
+
+        Out.write ( Bytes, 0, Bytes.length );
+
+        Out.close ();
+
+    }
+    catch ( Throwable Th ) {
+        throw new RuntimeException ( "ERROR: Can not write config: " + Th.toString () );
+    }
+
+    if ( envType == EnvType.BadConf ) {
+            /* We just return after dummy config creation
+             */
+        return;
+    }
+
+    if ( envType == EnvType.GoodConf ) {
+        /*  Here we import NGC file
+         */
+        try {
+            String Cmd =   _platform.getTarget (
+                                        Platform.TargetName.ConfigApp
+                                        )
+                         +  " --import "
+                         + _platform.getTarget (
+                                        Platform.TargetName.NgcFile
+                                        );
+
+            Process proc = Runtime.getRuntime().exec ( Cmd, _platform.getProcessEnvironment() );
+            proc.waitFor ();
+
+            Utils.printProcessOut ( proc );
+            Utils.printProcessErr ( proc );
+
+        }
+        catch ( Throwable Th ) {
+            throw new RuntimeException ( "ERROR: Can not write config: " + Th.toString () );
+        }
+
+        return;
+    }
+
+    throw new RuntimeException ( "ERROR: Unknown environment type" ); 
+}   /* configure () */
+
+};
+
diff --git a/test/dbgap-mount/jaba/Utils.java b/test/dbgap-mount/jaba/Utils.java
new file mode 100644
index 0000000..ccf5439
--- /dev/null
+++ b/test/dbgap-mount/jaba/Utils.java
@@ -0,0 +1,396 @@
+package jaba;
+
+import java.nio.file.*;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.FileOutputStream;
+import java.io.FileInputStream;
+import java.util.Arrays;
+
+/*///
+ \\\    This file contains some simplicied methods
+ ///*/
+public
+class
+Utils {
+
+private static
+void
+doUnlink ( Path ThePath )
+    throws IOException
+{
+    if ( Files.isDirectory ( ThePath ) ) {
+        try ( DirectoryStream < Path > stream = Files.newDirectoryStream ( ThePath ) ) {
+            for ( Path entry : stream ) {
+                doUnlink ( entry );
+            }
+        }
+        catch ( Throwable Th ) {
+            throw new RuntimeException ( Th.toString () );
+        }
+    }
+
+    Files.delete ( ThePath );
+}   /* doUnlink () */
+
+public static
+void
+unlink ( String ThePath )
+{
+    if ( ThePath == null ) {
+        throw new RuntimeException ( "Error: NULL path passed" );
+    }
+
+    System.out.format ( "Deleting: %s\n", ThePath );
+
+    try {
+        Path FilePath = Paths.get ( ThePath );
+        if ( Files.exists ( FilePath ) ) {
+            doUnlink ( FilePath );
+        }
+    }
+    catch ( Throwable Th ) {
+        throw new RuntimeException ( " Error: can not unlink [" + ThePath + "] because [" + Th.toString () + "]" );
+    }
+}   /* unlink () */
+
+public static
+void
+mkdir ( String ThePath )
+{
+    if ( ThePath == null ) {
+        throw new RuntimeException ( "Error: NULL path passed" );
+    }
+
+    System.out.format ( "Creating Dir: %s\n", ThePath );
+
+    try {
+        Files.createDirectory ( Paths.get ( ThePath ) );
+    }
+    catch ( Throwable Th ) {
+        throw new RuntimeException ( " Error: can not create directory [" + ThePath + "] because [" + Th.toString () + "]" );
+    }
+}   /* mkdir () */
+
+public static
+void
+checkExecutable ( String ThePath )
+{
+    if ( ThePath == null ) {
+        throw new RuntimeException ( "Error: NULL path passed" );
+    }
+
+    if ( ! Files.isExecutable ( Paths.get ( ThePath ) ) ) {
+        throw new RuntimeException ( " Error: can not stat executable [" + ThePath + "]" );
+    }
+
+    System.out.format ( "Found Binary [%s]\n", ThePath );
+}   /* checkExecutable () */
+
+public static
+void
+checkExists ( String ThePath )
+{
+    if ( ThePath == null ) {
+        throw new RuntimeException ( "Error: NULL path passed" );
+    }
+
+    if ( ! Files.exists ( Paths.get ( ThePath ) ) ) {
+        throw new RuntimeException ( "Error: can not stat executable [" + ThePath + "]" );
+    }
+
+    System.out.format ( "Found File [%s]\n", ThePath );
+}   /* checkExists () */
+
+/*\ Dull converter of Windows notation to POSYX. No mex - no chex
+ \*/
+public static
+String
+pathToPosix ( String Path )
+{
+        /* All what we do is replacing second ':' to nothing
+         * and replacing all '\' with '/'.
+         * I totally agree, it is not correct, but it is enough
+         * for that test.
+         */
+
+        /*  First, we check if string starts from 'x:'
+         */
+    String RetVal;
+
+    if ( Path.matches ( "^[a-z,A-Z][:]\\p{Graph}*" ) ) {
+        RetVal = Path.substring ( 2 );
+        if ( RetVal.charAt ( 0 ) == '\\' ) {
+            RetVal = "/" + Path.charAt ( 0 ) + RetVal;
+        }
+        else {
+            RetVal = "/" + Path.charAt ( 0 ) + "/" + RetVal;
+        }
+    }
+    else {
+        RetVal = Path;
+    }
+
+    RetVal = RetVal.replace ( '\\', '/' );
+
+    return RetVal;
+}   /* pathToPosix () */
+
+public static
+void
+printProcessOut ( Process Proc )
+{
+    if ( Proc == null ) {
+        return;
+    }
+
+    try {
+        System.out.println ( "||<=== LOG ====" );
+        BufferedReader out = new BufferedReader (
+                        new InputStreamReader( Proc.getInputStream () )
+                        );
+        String line;
+        while ( ( line = out.readLine() ) != null ) {
+            System.out.println(line);
+        }
+
+        out.close ();
+        System.out.println ( "||<============" );
+    }
+    catch ( Throwable Th ) {
+        throw new RuntimeException ( Th.toString () );
+    }
+}   /* printProcessOut () */
+
+public static
+void
+printProcessErr ( Process Proc )
+{
+    if ( Proc == null ) {
+        return;
+    }
+
+    int exitValue = Proc.exitValue ();
+    if ( exitValue == 0 ) {
+        return;
+    }
+
+    try {
+        System.out.format ( "||<=== ERR [%s] ====\n", exitValue );
+        BufferedReader out = new BufferedReader (
+                        new InputStreamReader( Proc.getErrorStream () )
+                        );
+        String line;
+        while ( ( line = out.readLine() ) != null ) {
+            System.out.println(line);
+        }
+
+        out.close ();
+        System.out.println ( "||<============" );
+    }
+    catch ( Throwable Th ) {
+        throw new RuntimeException ( Th.toString () );
+    }
+}   /* printProcessErr () */
+
+public static
+void
+sleepSec ( long sec )
+{
+    try { Thread.sleep ( 1000 * sec ); } catch ( Throwable Th ) { };
+}   /* sleepSec () */
+
+public static
+long
+fileSize ( String name )
+{
+    long retVal = 0;
+    try {
+        System.out.printf ( "Retrieving size for file [%s]\n", name );
+
+        retVal = Files.size ( Paths.get ( name ) );
+
+        System.out.printf ( "File [%s] has size [%d]\n", name, retVal );
+    }
+    catch ( Throwable Th ) {
+        System.out.printf ( "ERROR: can not retrieve size for file [%s]\n", name );
+        throw new RuntimeException ( "Error: " + Th.toString () );
+    }
+
+    return retVal;
+}   /* fileSize () */
+
+public static
+void
+deleteFile ( String name )
+{
+    try {
+        System.out.printf ( "Deleting file [%s]\n", name );
+
+        Files.delete ( Paths.get ( name ) );
+
+        System.out.printf ( "File deleted [%s]\n", name );
+    }
+    catch ( Throwable Th ) {
+        System.out.printf ( "ERROR: can not delete file [%s]\n", name );
+        throw new RuntimeException ( "Error: " + Th.toString () );
+    }
+}   /* deleteFile () */
+
+public static
+void
+createDir ( String path )
+{
+    try {
+        System.out.printf ( "Creating directory [%s]\n", path );
+
+        Files.createDirectory ( Paths.get ( path ) );
+
+        System.out.printf ( "Directory created [%s]\n", path );
+    }
+    catch ( Throwable Th ) {
+        System.out.printf ( "ERROR: can not create directory [%s]\n", path );
+        throw new RuntimeException ( "Error: " + Th.toString () );
+    }
+}   /* createDir () */
+
+public static
+void
+createFile ( String name, int size )
+{
+    System.out.printf ( "Creating file [%s] with size [%d]\n", name, size );
+
+    String Line = "0123456789abcdef";
+    byte [] Bytes = Line.getBytes ();
+
+    try {
+        FileOutputStream out = new FileOutputStream ( name );
+
+        int acc_size = 0;
+
+        while ( acc_size < size ) {
+
+            int size_2_write = size - acc_size;
+            if ( Bytes.length < size_2_write ) {
+                size_2_write = Bytes.length;
+            }
+
+            out.write( Bytes, 0, size_2_write );
+
+            acc_size += size_2_write;
+        }
+
+        out.close();
+
+        System.out.printf ( "File created [%s]\n", name );
+
+        Utils.sleepSec ( 1 );
+    }
+    catch ( Throwable Th ) {
+        System.out.printf ( "ERROR: can not create file [%s]\n", name );
+        throw new RuntimeException ( "Error: " + Th.toString () );
+    }
+}   /* createFile () */
+
+public static
+void
+copyFile ( String from, String to )
+{
+    try {
+        System.out.printf ( "Copy file [%s] to [%s]\n", from, to );
+
+            /* Had to use FileInputStream cuz under windows java.nio
+             * does not work well with direct access to random disks
+             */
+        Files.copy (
+                new FileInputStream ( new File ( from ) ),
+                Paths.get ( to )
+                );
+
+        System.out.printf ( "File copied [%s] to [%s]\n", from, to );
+    }
+    catch ( Throwable Th ) {
+        System.out.printf ( "ERROR: can not copy file [%s] to [%s]\n", from, to );
+        throw new RuntimeException ( "Error: " + Th.toString () );
+    }
+}   /* copyFile () */
+
+public static
+boolean
+compareFiles ( String file1, String file2 )
+{
+    System.out.printf ( "Comparing files [%s] and [%s]\n", file1, file2 );
+    try {
+        long fs1 = fileSize ( file1 );
+        long fs2 = fileSize ( file2 );
+
+        if ( fs1 == fs2 ) {
+            byte [] bytes1 = Files.readAllBytes ( Paths.get ( file1 ) );
+            byte [] bytes2 = Files.readAllBytes ( Paths.get ( file2 ) );
+
+            if ( Arrays.equals ( bytes1, bytes2 ) == true ) {
+                System.out.printf ( "EQUAL files [%s] and [%s]\n", file1, file2 );
+                return true;
+            }
+        }
+    }
+    catch ( Throwable Th ) {
+        System.out.println ( "Error: " + Th.toString () );
+
+        throw new RuntimeException ( "Error: can not compare files [" + file1 + "] and [" + file2 + "]" );
+    }
+
+    System.out.printf ( "DIFFER files [%s] and [%s]\n", file1, file2 );
+
+    return false;
+}   /* compareFiles () */
+
+private static
+void
+doList ( Path path )
+    throws IOException
+{
+    String sig = "[F]";
+
+    if ( Files.isDirectory ( path ) ) {
+        try ( DirectoryStream < Path > stream = Files.newDirectoryStream ( path ) ) {
+            for ( Path entry : stream ) {
+                doList ( entry );
+            }
+        }
+        catch ( Throwable Th ) {
+            throw new RuntimeException ( Th.toString () );
+        }
+
+        sig = "[D]";
+    }
+
+    System.out.printf ( "%s%s\n", sig, path.toString () );
+
+}   /* doList () */
+
+public static
+void
+list ( String path )
+{
+    if ( path == null ) {
+        throw new RuntimeException ( "Error: NULL path passed" );
+    }
+
+    System.out.format ( "Listing of [%s]\n", path );
+
+    try {
+        Path the_path = Paths.get ( path );
+        if ( Files.exists ( the_path ) ) {
+            doList ( the_path );
+        }
+    }
+    catch ( Throwable Th ) {
+        throw new RuntimeException ( " Error: can not list [" + path + "] because [" + Th.toString () + "]" );
+    }
+}   /* list () */
+
+};
diff --git a/test/dbgap-mount/jaba/WrapCmd.java b/test/dbgap-mount/jaba/WrapCmd.java
new file mode 100644
index 0000000..59b1df7
--- /dev/null
+++ b/test/dbgap-mount/jaba/WrapCmd.java
@@ -0,0 +1,280 @@
+package jaba;
+
+import java.nio.file.*;
+import java.io.*;
+import java.util.Arrays;
+
+public
+class
+WrapCmd {
+
+final static String _sCreateDir = "CD";
+final static String _sCreateFile = "CF";
+final static String _sCopyFile = "CP";
+final static String _sCompFiles = "CM";
+final static String _sFileStat = "FS";
+final static String _sList = "LS";
+final static String _sUnlink = "UL";
+
+private static
+boolean
+checkIfHelp ( String args [] )
+{
+    if ( args.length <= 1 ) {
+        return true;
+    }
+
+    for ( int llp = 0; llp < args.length; llp ++ ) {
+        if ( args [ llp ].equals ( "-h" ) || args [ llp ].equals ( "--help" ) ) {
+            return true;
+        }
+    }
+
+    return false;
+}   /* checkIfHelp () */
+
+public static
+void
+main( String args [] ) throws Throwable
+{
+    if ( checkIfHelp ( args ) ) {
+        printHelp ();
+    }
+
+    String Cmd = args [ 0 ];
+
+    while ( true ) {
+        if ( Cmd.equals ( _sCreateDir ) ) {
+            if ( args.length != 2 ) { printHelp (); }
+
+            createDir ( args [ 1 ] );
+
+            break;
+        }
+
+        if ( Cmd.equals ( _sCreateFile ) ) {
+            if ( args.length != 3 ) { printHelp (); }
+
+            createFile ( args [ 1 ], Integer.parseInt ( args [ 2 ] ) );
+
+            break;
+        }
+        
+        if ( Cmd.equals ( _sCopyFile ) ) {
+            if ( args.length != 3 ) { printHelp (); }
+
+            copyFile ( args [ 1 ], args [ 2 ] );
+
+            break;
+        }
+        
+        if ( Cmd.equals ( _sCompFiles ) ) {
+            if ( args.length != 3 ) { printHelp (); }
+
+            compareFiles ( args [ 1 ], args [ 2 ] );
+
+            break;
+        }
+        
+        if ( Cmd.equals ( _sFileStat ) ) {
+            if ( args.length != 2 ) { printHelp (); }
+
+            fileStat ( args [ 1 ] );
+
+            break;
+        }
+        
+        if ( Cmd.equals ( _sList ) ) {
+            if ( args.length != 2 ) { printHelp (); }
+
+            list ( args [ 1 ] );
+
+            break;
+        }
+        
+        if ( Cmd.equals ( _sUnlink ) ) {
+            if ( args.length != 2 ) { printHelp (); }
+
+            unlink ( args [ 1 ] );
+
+            break;
+        }
+
+        throw new RuntimeException ( "Invalid command [" + Cmd + "]" );
+    }
+
+
+}
+
+public static
+void
+printHelp ()
+{
+        /* Not sure what is better :LOL: */
+    String className = new Object() { }.getClass().getEnclosingClass().getName ();
+    // String className = new Object() { }.getClass().getEnclosingClass().getSimpleName ();
+
+    System.out.printf (
+                        "\nSyntax: java %s command command_argument(s)\n",
+                        className
+                        );
+    System.out.printf ( "\nWhere:\n\n" );
+    System.out.printf ( "   command - one of %s, %s, %s, %s, %s, %s or %s\n", _sCreateDir, _sCreateFile, _sCopyFile, _sCompFiles, _sFileStat, _sList, _sUnlink );
+
+    System.out.printf ( "\nAvailabe commands and arguments:\n\n" );
+    System.out.printf ( "Create Directory:" );
+    System.out.printf ( "   %s directory_name\n", _sCreateDir );
+    System.out.printf ( "     Create File:" );
+    System.out.printf ( "   %s file_name file_size\n", _sCreateFile );
+    System.out.printf ( "       Copy File:" );
+    System.out.printf ( "   %s file_from file_to\n", _sCopyFile );
+    System.out.printf ( "   Compare Files:" );
+    System.out.printf ( "   %s file1 file2\n", _sCompFiles );
+    System.out.printf ( "       File Stat:" );
+    System.out.printf ( "   %s file_name\n", _sFileStat );
+    System.out.printf ( "List Recursively:" );
+    System.out.printf ( "   %s directory_name\n", _sList );
+    System.out.printf ( "Unlink File or Directory:" );
+    System.out.printf ( "   %s name\n", _sUnlink );
+    System.out.printf ( "\n" );
+
+    throw new RuntimeException ( "Invalid arguments" );
+}   /* printHelp () */
+
+private static
+void
+createDir ( String dirName ) throws IOException
+{
+    new File ( dirName ).mkdir ();
+    // Files.createDirectory ( Paths.get ( dirName ) );
+}   /* createDir () */
+
+private static
+void
+createFile ( String fileName, int fileSize ) throws IOException
+{
+    String Line = "0123456789abcdef";
+    byte [] Bytes = Line.getBytes ();
+
+    // new File ( fileName ) . createNewFile ();
+
+    FileOutputStream out = new FileOutputStream ( fileName );
+
+    int acc_size = 0;
+
+    while ( acc_size < fileSize ) {
+
+        int size_2_write = fileSize - acc_size;
+        if ( Bytes.length < size_2_write ) {
+            size_2_write = Bytes.length;
+        }
+
+        out.write( Bytes, 0, size_2_write );
+
+        acc_size += size_2_write;
+    }
+
+    out.close();
+}   /* createFile () */
+
+private static
+void
+copyFile ( String from, String to ) throws IOException
+{
+    Files.copy (
+                new FileInputStream ( new File ( from ) ),
+                Paths.get ( to )
+                );
+}   /* copyFile () */
+
+private static
+void
+compareFiles ( String file1, String file2 ) throws IOException
+{
+    long fs1 = Files.size ( Paths.get ( file1 ) );
+    long fs2 = Files.size ( Paths.get ( file2 ) );
+
+    if ( fs1 == fs2 ) {
+        byte [] bytes1 = Files.readAllBytes ( Paths.get ( file1 ) );
+        byte [] bytes2 = Files.readAllBytes ( Paths.get ( file2 ) );
+
+        if ( Arrays.equals ( bytes1, bytes2 ) == true ) {
+            return;
+        }
+    }
+
+    throw new RuntimeException ( "Files [" + file1 + "] and [" + file2 + "] are different" );
+}   /* compareFiles () */
+
+private static
+void
+fileStat ( String name ) throws IOException
+{
+    File file = new File ( name );
+
+    if ( file.exists () ) {
+        System.out.printf (
+                        "%s\t%d\n",
+                        ( file.isDirectory () ? "D" : "F" ),
+                        Files.size ( file.toPath () )
+                        );
+        return;
+    }
+
+    throw new RuntimeException ( "File [" + name + "] does not exist" );
+}   /* fileStat () */
+
+private static
+void
+doList ( Path path ) throws IOException
+{
+    System.out.println ( path.toString () );
+
+    if ( Files.isDirectory ( path ) ) {
+        DirectoryStream < Path > stream = Files.newDirectoryStream ( path );
+        for ( Path entry : stream ) {
+            doList ( entry );
+        }
+    }
+}   /* doList () */
+
+private static
+void
+list ( String name ) throws IOException
+{
+    Path path = Paths.get ( name );
+    if ( Files.exists ( path ) ) {
+        doList ( path );
+        return;
+    }
+    throw new RuntimeException ( "File [" + name + "] does not exist" );
+}   /* list () */
+
+private static
+void
+doUnlink ( Path path ) throws IOException
+{
+    if ( Files.isDirectory ( path ) ) {
+        DirectoryStream < Path > stream = Files.newDirectoryStream ( path );
+        for ( Path entry : stream ) {
+            doUnlink ( entry );
+        }
+    }
+
+    // ThePath.toFile ().delete ();
+    Files.delete ( path );
+}   /* doUnlink () */
+
+private static
+void
+unlink ( String name ) throws IOException
+{
+    Path path = Paths.get ( name );
+    if ( Files.exists ( path ) ) {
+        doUnlink ( path );
+        return;
+    }
+    throw new RuntimeException ( "File [" + name + "] does not exist" );
+}   /* unlink () */
+
+};
diff --git a/test/dbgap-mount/jaba/platform/Platform.java b/test/dbgap-mount/jaba/platform/Platform.java
new file mode 100644
index 0000000..bcece9f
--- /dev/null
+++ b/test/dbgap-mount/jaba/platform/Platform.java
@@ -0,0 +1,85 @@
+package jaba.platform;
+
+import java.lang.Exception;
+
+/*|| That interface contains platform dependable code, like mount point
+  || commands to launch process or what ever. Most of methods in that
+  || interface are 'default' cuz I do not like to implement all methods
+  || on all platforms in parallel
+  || Will make it Serializable or Externiolizable later
+  ||*/
+public
+interface
+Platform {
+
+public
+enum
+TargetName {
+    Separator,
+    ConfigDir,
+    DataDir,
+    TempDir,
+    MountPoint,
+    ConfigFile,
+    Project,
+    NgcFile,
+    KartFile,
+    MountApp,
+    ConfigApp,
+    DumpApp,
+    UmountApp
+};
+
+    /*> General, returns a name of OS
+     <*/
+public
+String
+getOS ();
+
+public
+String
+getTestDir ();
+
+public
+String
+getInputDataDir ();
+
+public
+String
+getAppDir ();
+
+public
+String
+getTarget ( TargetName Name );
+
+public
+boolean
+needCreateMountPoint ();
+
+public
+String []
+getProcessEnvironment ();
+
+    /*> Returns instance of Platform interface
+     <*/
+public static
+Platform
+getPlatform ( String AppDir )
+{
+    String OS = System.getProperty ( "os.name" );
+    if ( OS.startsWith ( "Lin" ) ) {
+        return new PlatformLinux ( AppDir );
+    }
+
+    if ( OS.startsWith ( "Mac" ) ) {
+        return new PlatformMac ( AppDir );
+    }
+
+    if ( OS.startsWith ( "Win" ) ) {
+        return new PlatformWin ( AppDir );
+    }
+
+    throw new RuntimeException ( "Unknown platform [" + OS + "]" );
+}   /* getPlatform () */
+
+};
diff --git a/test/dbgap-mount/jaba/platform/PlatformLinux.java b/test/dbgap-mount/jaba/platform/PlatformLinux.java
new file mode 100644
index 0000000..4621c20
--- /dev/null
+++ b/test/dbgap-mount/jaba/platform/PlatformLinux.java
@@ -0,0 +1,33 @@
+package jaba.platform;
+
+public
+class 
+PlatformLinux
+    extends PlatformSuper {
+
+public
+PlatformLinux ( String AppDir )
+{
+    super ( AppDir );
+}   /* PlatformLinux () */
+
+public
+String
+getOS ()
+{
+    return "Linux";
+}   /* getOS () */
+
+public
+String
+getTarget ( TargetName Name )
+{
+    switch ( Name ) {
+        case UmountApp:
+            return "/bin/fusermount -u";
+    }
+
+    return super.getTarget ( Name );
+}   /* getTarget () */
+
+};
diff --git a/test/dbgap-mount/jaba/platform/PlatformMac.java b/test/dbgap-mount/jaba/platform/PlatformMac.java
new file mode 100644
index 0000000..e28ac13
--- /dev/null
+++ b/test/dbgap-mount/jaba/platform/PlatformMac.java
@@ -0,0 +1,40 @@
+package jaba.platform;
+
+public
+class 
+PlatformMac
+    extends PlatformSuper {
+
+public
+PlatformMac ( String AppDir )
+{
+    super ( AppDir );
+}   /* PlatformMac () */
+
+public
+String
+getOS ()
+{
+    return "Mac";
+}   /* getOS () */
+
+public
+String
+getInputDataDir ()
+{
+    return "/net/pan1/trace_work/iskhakov/IMPORTANT_DIR";
+}   /* getInputDataDir () */
+
+public
+String
+getTarget ( TargetName Name )
+{
+    switch ( Name ) {
+        case UmountApp:
+            return "/sbin/umount";
+    }
+
+    return super.getTarget ( Name );
+}   /* getTarget () */
+
+};
diff --git a/test/dbgap-mount/jaba/platform/PlatformSuper.java b/test/dbgap-mount/jaba/platform/PlatformSuper.java
new file mode 100644
index 0000000..6a80021
--- /dev/null
+++ b/test/dbgap-mount/jaba/platform/PlatformSuper.java
@@ -0,0 +1,166 @@
+package jaba.platform;
+
+import java.lang.Exception;
+
+public abstract
+class
+PlatformSuper
+    implements Platform {
+
+final static String _sDbGapMountTest = "DbGapMountTest";
+
+private String _appDir = null;
+protected String _fileSeparator = null;
+protected String _home = null;
+
+public
+PlatformSuper ( String AppDir )
+{
+    System.out.println ( "Detected [" + getOS () + "] platform" );
+
+    _appDir = AppDir;
+
+    if ( _appDir == null ) {
+        throw new RuntimeException ( "NULL AppDir passed for os [" + getOS () + "]" );
+    }
+
+    _fileSeparator = System.getProperty ( "file.separator" );
+    if ( _fileSeparator == null ) {
+        throw new RuntimeException ( "'file.separator' undefined for [" + getOS () + "]" );
+    }
+
+    _home = System.getProperty ( "user.home" );
+    if ( _home == null ) {
+        throw new RuntimeException ( "'user.home' undefined for [" + getOS () + "]" );
+    }
+
+}   /* PlatformSuper () */
+
+
+    /*> General, returns a name of OS
+     <*/
+// public
+// String
+// getOS ();
+
+/*>>>   Configuration and environment related thins
+ <<<    We need to maintain individual configuration for test run.
+  >>>   We will use directory $HOME/DbGapMountTest$PLATFORM as root
+ <<<    That directory will contain following subdirectories :
+  >>>       .ncbi - configuration directory  
+ <<<        ncbi  - data directory
+  >>>       mount - mount point
+ <<<    Method getTestDir should return path to test root directory
+  >>>   
+ <<<    
+  >>>   Somewhere on PanFs suppose to be NGC and KART files, so thereis
+ <<<    getInputDataDir method to locate that place
+  >>>   
+ <<<    Somewhere else there should be binaries to test, and there is
+  >>>   getAppDir method to locate that place
+ <<<*/
+    /*> Returns mountpoint directory
+     <*/
+public
+String
+getTestDir ()
+{
+    return   _home + _fileSeparator + _sDbGapMountTest + getOS ();
+}   /* getTestDir () */
+
+public
+String
+getInputDataDir ()
+{
+    return "/panfs/pan1/trace_work/iskhakov/IMPORTANT_DIR";
+}   /* getInputDataDir () */
+
+public
+String
+getAppDir ()
+{
+    return _appDir;
+}   /* getAppDir () */
+
+public
+String
+getTarget ( TargetName Name )
+{
+    switch ( Name ) {
+        case Separator:
+                return _fileSeparator;
+        case ConfigDir:
+                return  getTestDir () + _fileSeparator + ".ncbi";
+        case DataDir:
+                return  getTestDir () + _fileSeparator + "ncbi";
+        case TempDir:
+                return  getTestDir () + _fileSeparator + "temp";
+        case ConfigFile:
+                return    getTarget ( TargetName.ConfigDir )
+                        + _fileSeparator
+                        + "user-settings.mkfg"
+                        ;
+        case MountPoint:
+                return  getTestDir () + _fileSeparator + "mount";
+        case Project:
+                return "6570";
+        case NgcFile:
+                return  getInputDataDir ()
+                        + _fileSeparator
+                        + _sDbGapMountTest
+                        + _fileSeparator
+                        + "prj_"
+                        + getTarget ( TargetName.Project )
+                        + ".ngc"
+                        ;
+        case KartFile:
+                return  getInputDataDir ()
+                        + _fileSeparator
+                        + _sDbGapMountTest
+                        + _fileSeparator
+                        + "kart_prj_"
+                        + getTarget ( TargetName.Project )
+                        + ".krt"
+                        ;
+        case MountApp:
+                return    getAppDir ()
+                        + _fileSeparator
+                        + "dbgap-mount-tool"
+                        ;
+        case ConfigApp:
+                return    getAppDir ()
+                        + _fileSeparator
+                        + "vdb-config"
+                        ;
+        case DumpApp:
+                return    getAppDir ()
+                        + _fileSeparator
+                        + "fastq-dump-new"
+                        ;
+    };
+
+    throw new RuntimeException ( "Invalid tartet for [" + getOS () + "]" );
+}   /* getTarget () */
+
+    /* For some platforms we do not need directory created 
+     */
+public
+boolean
+needCreateMountPoint ()
+{
+    return true;
+}   /* needCreateMountPoint () */
+
+public
+String []
+getProcessEnvironment ()
+{
+    String [] RetVal = {
+                    "HOME=" + _home,
+                    "NCBI_HOME=" + getTarget ( TargetName.ConfigDir )
+                    };
+
+    return RetVal;
+}   /* getProcessEnvironment () */
+
+};
diff --git a/test/dbgap-mount/jaba/platform/PlatformWin.java b/test/dbgap-mount/jaba/platform/PlatformWin.java
new file mode 100644
index 0000000..b5a15e8
--- /dev/null
+++ b/test/dbgap-mount/jaba/platform/PlatformWin.java
@@ -0,0 +1,78 @@
+package jaba.platform;
+
+public
+class 
+PlatformWin
+    extends PlatformSuper {
+
+public
+PlatformWin ( String AppDir )
+{
+    super ( AppDir );
+}   /* PlatformWin () */
+
+public
+String
+getOS ()
+{
+    return "Windows";
+}   /* getOS () */
+
+public
+String
+getInputDataDir ()
+{
+    return "\\\\panfs\\pan1\\trace_work\\iskhakov\\IMPORTANT_DIR";
+}   /* getInputDataDir () */
+
+    /*> Redefining, because under windows we tend to new VOLUME
+     <*/
+public
+String
+getTarget ( TargetName Name )
+{
+    switch ( Name ) {
+        case MountPoint:
+                return "r:";
+        case MountApp:
+                return    getAppDir ()
+                        + _fileSeparator
+                        + "dbgap-mount-tool.exe"
+                        ;
+        case ConfigApp:
+                return    getAppDir ()
+                        + _fileSeparator
+                        + "vdb-config.exe"
+                        ;
+        case DumpApp:
+                return    getAppDir ()
+                        + _fileSeparator
+                        + "fastq-dump-ngs.exe"
+                        ;
+        case UmountApp:
+                return "c:\\\\ProgramFiles (x86)\\Dokan\\DokanLibrary\\dokanctl.exe /u";
+    };
+
+    return super.getTarget ( Name );
+}   /* getTarget () */
+
+public
+boolean
+needCreateMountPoint ()
+{
+    return false;
+}   /* needCreateMountPoint () */
+
+public
+String []
+getProcessEnvironment ()
+{
+    String [] RetVal = {
+                    "USERPROFILE=" + _home,
+                    "NCBI_HOME=" + getTarget ( TargetName.ConfigDir )
+                    };
+
+    return RetVal;
+}   /* getProcessEnvironment () */
+
+};
diff --git a/test/dbgap-mount/jaba/test/Test.java b/test/dbgap-mount/jaba/test/Test.java
new file mode 100644
index 0000000..20f2158
--- /dev/null
+++ b/test/dbgap-mount/jaba/test/Test.java
@@ -0,0 +1,30 @@
+package jaba.test;
+
+import jaba.platform.Platform;
+import java.lang.reflect.Constructor;
+
+public
+interface
+Test {
+
+public
+String
+getName ();
+
+    /*>>  That method could return NULL or empty length array,
+     <<  it will be interpreted as ALL
+      >>
+     <<*/
+public
+String []
+tickets ();
+
+public
+void
+run ();
+
+public
+int
+exitStatus ();
+
+};
diff --git a/test/dbgap-mount/jaba/test/TestBasicBase.java b/test/dbgap-mount/jaba/test/TestBasicBase.java
new file mode 100644
index 0000000..5132a9e
--- /dev/null
+++ b/test/dbgap-mount/jaba/test/TestBasicBase.java
@@ -0,0 +1,120 @@
+package jaba.test;
+
+import jaba.App;
+import jaba.Utils;
+import jaba.platform.Platform;
+import jaba.DbGapMountTestEnv;
+import java.io.BufferedReader;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.Path;
+
+/*>>> Simple test. Should start mounter without parameters.
+ <<<  Program should print help and return non-zero code
+  >>>
+ <<<*/
+
+abstract public 
+class TestBasicBase
+    extends TestSuper {
+
+public
+TestBasicBase ( Platform platform )
+{
+    super ( platform );
+}   /* TestBasicBase () */
+
+protected
+void
+start ( boolean ReadOnly )
+{
+    if ( ReadOnly ) {
+        System.out.format ( "[Starting application in RO mode as daemon]\n" );
+    }
+    else {
+        System.out.format ( "[Starting application in RW mode as daemon]\n" );
+    }
+
+    String Cmd = _platform.getTarget ( Platform.TargetName.MountApp );
+
+    Cmd += " -d";
+    if ( ReadOnly ) {
+        Cmd += " ro ";
+    }
+    Cmd += " " + _platform.getTarget ( Platform.TargetName.Project );
+    Cmd += " " + _platform.getTarget ( Platform.TargetName.MountPoint );
+
+    System.out.format ( "[Starting application in daemon mode] [%s]\n", Cmd );
+
+        /*  First we need to start as daemon and wait application exit
+         */
+    App app = new App ( Cmd, _platform.getProcessEnvironment (), this );
+
+    app.start ( 5 );
+    app.waitFor ();
+
+    Utils.sleepSec ( 2 );
+
+    simpleMountCheck ( );
+
+    System.out.format ( "[Application started as daemon]\n" );
+}   /* start () */
+
+protected
+void
+stop ()
+{
+    if ( umount () != 0 ) {
+        throw new RuntimeException ( "Can umount [" + _platform.getTarget ( Platform.TargetName.MountPoint ) + "]" );
+    }
+}   /* stop () */
+
+    /* You should reimplement it
+     */
+abstract protected
+void
+runActualTest ();
+
+protected
+int
+runTest ()
+{
+    try {
+        _env.createTestEnv ( DbGapMountTestEnv.EnvType.GoodConf );
+
+        runActualTest ();
+
+        _env.clearTestEnv ();
+    }
+    catch ( Throwable Th ) {
+        System.out.printf ( "Test Failed : %s\n", Th.toString () );
+        return 1;
+    }
+
+    return 0;
+}   /* runTest () */
+
+protected
+String
+pathToFile ( String fileName )
+{
+    return    _platform.getTarget ( Platform.TargetName.MountPoint )
+            + _platform.getTarget ( Platform.TargetName.Separator )
+            + "workspace"
+            + _platform.getTarget ( Platform.TargetName.Separator )
+            + fileName
+            ;
+}   /* pathToFile () */
+
+protected
+String
+pathToTempFile ( String fileName )
+{
+    return    _platform.getTarget ( Platform.TargetName.TempDir )
+            + _platform.getTarget ( Platform.TargetName.Separator )
+            + fileName
+            ;
+}   /* pathToTempFile () */
+
+
+};
diff --git a/test/dbgap-mount/jaba/test/TestFunctionality.java b/test/dbgap-mount/jaba/test/TestFunctionality.java
new file mode 100644
index 0000000..9fe3fde
--- /dev/null
+++ b/test/dbgap-mount/jaba/test/TestFunctionality.java
@@ -0,0 +1,97 @@
+package jaba.test;
+
+import jaba.App;
+import jaba.platform.Platform;
+import jaba.DbGapMountTestEnv;
+import java.io.BufferedReader;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.Path;
+
+/*>>> Simple test. Should start mounter without parameters.
+ <<<  Program should print help and return non-zero code
+  >>>
+ <<<*/
+
+public 
+class TestFunctionality
+    extends TestSuper {
+
+public
+TestFunctionality ( Platform platform )
+{
+    super ( platform );
+}   /* TestFunctionality () */
+
+protected
+int
+runTest ()
+{
+    _env.createTestEnv ( DbGapMountTestEnv.EnvType.GoodConf );
+
+    System.out.format ( "[Starting application good config]\n" );
+
+    String Cmd = _platform.getTarget ( Platform.TargetName.MountApp );
+
+    Cmd += " " + _platform.getTarget ( Platform.TargetName.Project );
+    Cmd += " " + _platform.getTarget ( Platform.TargetName.MountPoint );
+
+    App app = new App ( Cmd, _platform.getProcessEnvironment (), this );
+
+    app.start ( 5 );
+
+        /*  We need that delay to allow system to wake up
+         */
+    sleepSec ( 2 );
+
+    simpleMountCheck ( );
+
+    if ( umount () != 0 ) {
+        throw new RuntimeException ( "Can umount [" + _platform.getTarget ( Platform.TargetName.MountPoint ) + "]" );
+    }
+
+    app.waitFor ();
+
+    try {
+        System.out.println ( "[OUT: Begin]" );
+
+        BufferedReader out = new BufferedReader ( app.getOutStream () );
+        String line;
+        while ( ( line = out.readLine() ) != null ) {
+            System.out.println ( line );
+        }
+        out.close ();
+
+        System.out.println ( "[OUT: End]" );
+    }
+    catch ( Throwable Th ) {
+        System.out.println ( Th.toString () );
+        return 1;
+    }
+
+    try {
+        System.out.println ( "[ERR: Begin]" );
+
+        BufferedReader out = new BufferedReader ( app.getErrStream () );
+        String line;
+        while ( ( line = out.readLine() ) != null ) {
+            System.out.println ( line );
+        }
+        out.close ();
+
+        System.out.println ( "[ERR: End]" );
+    }
+    catch ( Throwable Th ) {
+        System.out.println ( Th.toString () );
+        return 1;
+    }
+
+    int retVal = app.exitStatus ();
+    System.out.format ( "[Application exited with RC = %d]\n", retVal );
+
+    _env.clearTestEnv ();
+
+    return retVal;
+}
+
+};
diff --git a/test/dbgap-mount/jaba/test/TestRunStopBadConfig.java b/test/dbgap-mount/jaba/test/TestRunStopBadConfig.java
new file mode 100644
index 0000000..aa95f56
--- /dev/null
+++ b/test/dbgap-mount/jaba/test/TestRunStopBadConfig.java
@@ -0,0 +1,92 @@
+package jaba.test;
+
+import jaba.App;
+import jaba.platform.Platform;
+import jaba.DbGapMountTestEnv;
+import java.io.BufferedReader;
+
+/*>>> Simple test. Should start mounter without parameters.
+ <<<  Program should print help and return non-zero code
+  >>>
+ <<<*/
+
+public 
+class TestRunStopBadConfig
+    extends TestSuper {
+
+public
+TestRunStopBadConfig ( Platform platform )
+{
+    super ( platform );
+}   /* TestRunStopBadConfig () */
+
+protected
+int
+runTest ()
+{
+    _env.createTestEnv ( DbGapMountTestEnv.EnvType.BadConf );
+
+    System.out.format ( "[Starting application bad config]\n" );
+
+    String Cmd = _platform.getTarget ( Platform.TargetName.MountApp );
+
+    Cmd += " " + _platform.getTarget ( Platform.TargetName.Project );
+    Cmd += " " + _platform.getTarget ( Platform.TargetName.MountPoint );
+
+    App app = new App ( Cmd, _platform.getProcessEnvironment (), this );
+
+    app.start ( 5 );    /* I think that 5 seconds is OK */
+    app.waitFor ();
+
+    try {
+        System.out.println ( "[OUT: Begin]" );
+
+        BufferedReader out = new BufferedReader ( app.getOutStream () );
+        String line;
+        while ( ( line = out.readLine() ) != null ) {
+            System.out.println ( line );
+        }
+        out.close ();
+
+        System.out.println ( "[OUT: End]" );
+    }
+    catch ( Throwable Th ) {
+        System.out.println ( Th.toString () );
+        return 1;
+    }
+
+    try {
+        System.out.println ( "[ERR: Begin]" );
+
+        BufferedReader out = new BufferedReader ( app.getErrStream () );
+        boolean empty = true;
+        String line;
+        while ( ( line = out.readLine() ) != null ) {
+            System.out.println ( line );
+
+            if ( ! line.isEmpty () ) {
+                empty = false;
+            }
+        }
+        out.close ();
+
+        System.out.println ( "[ERR: End]" );
+
+        if ( empty ) {
+            throw new RuntimeException ( "Missed Error Message body" );
+        }
+    }
+    catch ( Throwable Th ) {
+        System.out.println ( Th.toString () );
+        return 1;
+    }
+
+    int retVal = app.exitStatus ();
+    System.out.format ( "[Application exited with RC = %d]\n", retVal );
+
+    _env.clearTestEnv ();
+
+    return retVal == 0 ? 1 : 0;
+}
+
+};
diff --git a/test/dbgap-mount/jaba/test/TestRunStopDaemon.java b/test/dbgap-mount/jaba/test/TestRunStopDaemon.java
new file mode 100644
index 0000000..b4dbede
--- /dev/null
+++ b/test/dbgap-mount/jaba/test/TestRunStopDaemon.java
@@ -0,0 +1,124 @@
+package jaba.test;
+
+import jaba.App;
+import jaba.platform.Platform;
+import jaba.DbGapMountTestEnv;
+import java.io.BufferedReader;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.Path;
+
+/*>>> Simple test. Should start mounter without parameters.
+ <<<  Program should print help and return non-zero code
+  >>>
+ <<<*/
+
+public 
+class TestRunStopDaemon
+    extends TestSuper {
+
+public
+TestRunStopDaemon ( Platform platform )
+{
+    super ( platform );
+}   /* TestRunStopDaemon () */
+
+public
+String []
+tickets ()
+{
+    String [] r = { "VDB-1528", "VDB-2841" };
+    return r;
+}   /* tickets () */
+
+protected
+int
+runTest ()
+{
+    _env.createTestEnv ( DbGapMountTestEnv.EnvType.GoodConf );
+
+    System.out.format ( "[Starting application in daemon mode]\n" );
+
+    String Cmd = _platform.getTarget ( Platform.TargetName.MountApp );
+
+    Cmd += " -d";
+    Cmd += " " + _platform.getTarget ( Platform.TargetName.Project );
+    Cmd += " " + _platform.getTarget ( Platform.TargetName.MountPoint );
+
+    System.out.format ( "[Starting application in daemon mode] [%s]\n", Cmd );
+
+        /*  First we need to start as daemon and wait application exit
+         */
+    App app = new App ( Cmd, _platform.getProcessEnvironment (), this );
+
+    app.start ( 5 );
+    app.waitFor ();
+
+    try {
+        System.out.println ( "[OUT: Begin]" );
+
+        BufferedReader out = new BufferedReader ( app.getOutStream () );
+        String line;
+        while ( ( line = out.readLine() ) != null ) {
+            System.out.println ( line );
+        }
+        out.close ();
+
+        System.out.println ( "[OUT: End]" );
+    }
+    catch ( Throwable Th ) {
+        System.out.println ( Th.toString () );
+        return 1;
+    }
+
+    try {
+        System.out.println ( "[ERR: Begin]" );
+
+        BufferedReader out = new BufferedReader ( app.getErrStream () );
+        String line;
+        while ( ( line = out.readLine() ) != null ) {
+            System.out.println ( line );
+        }
+        out.close ();
+
+        System.out.println ( "[ERR: End]" );
+    }
+    catch ( Throwable Th ) {
+        System.out.println ( Th.toString () );
+        return 1;
+    }
+
+    int retVal = app.exitStatus ();
+    if ( retVal != 0 ) {
+        System.out.format ( "[Application exited with RC = %d]\n", retVal );
+        return 1;
+    }
+    else {
+        System.out.format ( "[Application started in daemon mode]\n" );
+    }
+
+        /*  We need that delay to allow system to wake up and check
+         *  mount
+         */
+    sleepSec ( 2 );
+
+    try {
+        simpleMountCheck ( );
+    }
+    catch ( Throwable Th ) {
+        System.out.println ( "Mount check failed: " + Th.toString () );
+        retVal = 2;
+    }
+
+        /*  Umounting
+         */
+    if ( umount () != 0 ) {
+        throw new RuntimeException ( "Can umount [" + _platform.getTarget ( Platform.TargetName.MountPoint ) + "]" );
+    }
+
+    _env.clearTestEnv ();
+
+    return retVal;
+}
+
+};
diff --git a/test/dbgap-mount/jaba/test/TestRunStopGoodConfig.java b/test/dbgap-mount/jaba/test/TestRunStopGoodConfig.java
new file mode 100644
index 0000000..028b151
--- /dev/null
+++ b/test/dbgap-mount/jaba/test/TestRunStopGoodConfig.java
@@ -0,0 +1,106 @@
+package jaba.test;
+
+import jaba.App;
+import jaba.Utils;
+import jaba.platform.Platform;
+import jaba.DbGapMountTestEnv;
+import java.io.BufferedReader;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.Path;
+
+/*>>> Simple test. Should start mounter without parameters.
+ <<<  Program should print help and return non-zero code
+  >>>
+ <<<*/
+
+public 
+class TestRunStopGoodConfig
+    extends TestSuper {
+
+public
+TestRunStopGoodConfig ( Platform platform )
+{
+    super ( platform );
+}   /* TestRunStopGoodConfig () */
+
+public
+String []
+tickets ()
+{
+    String [] t = { "VDB-1528", "VDB-2779" };
+    return t;
+}   /* tickets () */
+
+protected
+int
+runTest ()
+{
+    _env.createTestEnv ( DbGapMountTestEnv.EnvType.GoodConf );
+
+    System.out.format ( "[Starting application good config]\n" );
+
+    String Cmd = _platform.getTarget ( Platform.TargetName.MountApp );
+
+    Cmd += " " + _platform.getTarget ( Platform.TargetName.Project );
+    Cmd += " " + _platform.getTarget ( Platform.TargetName.MountPoint );
+
+    App app = new App ( Cmd, _platform.getProcessEnvironment (), this );
+
+    app.start ( 10 );
+
+        /*  We need that delay to allow system to wake up
+         */
+    Utils.sleepSec ( 2 );
+
+    simpleMountCheck ( );
+
+    if ( umount () != 0 ) {
+        throw new RuntimeException ( "Can umount [" + _platform.getTarget ( Platform.TargetName.MountPoint ) + "]" );
+    }
+
+    app.waitFor ();
+
+    try {
+        System.out.println ( "[OUT: Begin]" );
+
+        BufferedReader out = new BufferedReader ( app.getOutStream () );
+        String line;
+        while ( ( line = out.readLine() ) != null ) {
+            System.out.println ( line );
+        }
+        out.close ();
+
+        System.out.println ( "[OUT: End]" );
+    }
+    catch ( Throwable Th ) {
+        System.out.println ( Th.toString () );
+        return 1;
+    }
+
+    try {
+        System.out.println ( "[ERR: Begin]" );
+
+        BufferedReader out = new BufferedReader ( app.getErrStream () );
+        String line;
+        while ( ( line = out.readLine() ) != null ) {
+            System.out.println ( line );
+        }
+        out.close ();
+
+        System.out.println ( "[ERR: End]" );
+    }
+    catch ( Throwable Th ) {
+        System.out.println ( Th.toString () );
+        return 1;
+    }
+
+    int retVal = app.exitStatus ();
+    System.out.format ( "[Application exited with RC = %d]\n", retVal );
+
+    _env.clearTestEnv ();
+
+    return retVal;
+}
+
+};
diff --git a/test/dbgap-mount/jaba/test/TestRunStopNoConfig.java b/test/dbgap-mount/jaba/test/TestRunStopNoConfig.java
new file mode 100644
index 0000000..d30eb5a
--- /dev/null
+++ b/test/dbgap-mount/jaba/test/TestRunStopNoConfig.java
@@ -0,0 +1,92 @@
+package jaba.test;
+
+import jaba.App;
+import jaba.platform.Platform;
+import jaba.DbGapMountTestEnv;
+import java.io.BufferedReader;
+
+/*>>> Simple test. Should start mounter without parameters.
+ <<<  Program should print help and return non-zero code
+  >>>
+ <<<*/
+
+public 
+class TestRunStopNoConfig
+    extends TestSuper {
+
+public
+TestRunStopNoConfig ( Platform platform )
+{
+    super ( platform );
+}   /* TestRunStopNoConfig () */
+
+protected
+int
+runTest ()
+{
+    _env.createTestEnv ( DbGapMountTestEnv.EnvType.NoConf );
+
+    System.out.format ( "[Starting application without config]\n" );
+
+    String Cmd = _platform.getTarget ( Platform.TargetName.MountApp );
+
+    Cmd += " " + _platform.getTarget ( Platform.TargetName.Project );
+    Cmd += " " + _platform.getTarget ( Platform.TargetName.MountPoint );
+
+    App app = new App ( Cmd, _platform.getProcessEnvironment (), this );
+
+    app.start ( 5 );    /* I think that 5 seconds is OK */
+    app.waitFor ();
+
+    try {
+        System.out.println ( "[OUT: Begin]" );
+
+        BufferedReader out = new BufferedReader ( app.getOutStream () );
+        String line;
+        while ( ( line = out.readLine() ) != null ) {
+            System.out.println ( line );
+        }
+        out.close ();
+
+        System.out.println ( "[OUT: End]" );
+    }
+    catch ( Throwable Th ) {
+        System.out.println ( Th.toString () );
+        return 1;
+    }
+
+    try {
+        System.out.println ( "[ERR: Begin]" );
+
+        BufferedReader out = new BufferedReader ( app.getErrStream () );
+        boolean empty = true;
+        String line;
+        while ( ( line = out.readLine() ) != null ) {
+            System.out.println ( line );
+
+            if ( ! line.isEmpty () ) {
+                empty = false;
+            }
+        }
+        out.close ();
+
+        System.out.println ( "[ERR: End]" );
+
+        if ( empty ) {
+            throw new RuntimeException ( "Missed Error Message body" );
+        }
+    }
+    catch ( Throwable Th ) {
+        System.out.println ( Th.toString () );
+        return 1;
+    }
+
+    int retVal = app.exitStatus ();
+    System.out.format ( "[Application exited with RC = %d]\n", retVal );
+
+    _env.clearTestEnv ();
+
+    return retVal == 0 ? 1 : 0;
+}
+
+};
diff --git a/test/dbgap-mount/jaba/test/TestRunStopNoParameters.java b/test/dbgap-mount/jaba/test/TestRunStopNoParameters.java
new file mode 100644
index 0000000..05b8ad0
--- /dev/null
+++ b/test/dbgap-mount/jaba/test/TestRunStopNoParameters.java
@@ -0,0 +1,87 @@
+package jaba.test;
+
+import jaba.App;
+import jaba.platform.Platform;
+import jaba.DbGapMountTestEnv;
+import java.io.BufferedReader;
+
+/*>>> Simple test. Should start mounter without parameters.
+ <<<  Program should print help and return non-zero code
+  >>>
+ <<<*/
+
+public 
+class TestRunStopNoParameters
+    extends TestSuper {
+
+public
+TestRunStopNoParameters ( Platform platform )
+{
+    super ( platform );
+}   /* TestRunStopNoParameters () */
+
+public
+boolean
+gentleTerminate ()
+{
+        /* Nothing to do
+         */
+    return false;
+}   /* gentleTerminate () */
+
+protected
+int
+runTest ()
+{
+    _env.createTestEnv ( DbGapMountTestEnv.EnvType.NoConf );
+
+    System.out.format ( "[Starting application without parameters]\n" );
+
+    App app = new App (
+                _platform.getTarget ( Platform.TargetName.MountApp ),
+                _platform.getProcessEnvironment (),
+                this
+                );
+
+    app.start ( 5 );    /* I think that 5 seconds is OK */
+    app.waitFor ();
+
+    try {
+        BufferedReader out = new BufferedReader ( app.getOutStream () );
+        boolean isUsage = false;
+
+        String line;
+        while ( ( line = out.readLine() ) != null ) {
+            System.out.println(line);
+
+            if ( line.indexOf ( "Usage" ) != 1 * - 1 ) {
+                isUsage = true;
+            }
+        }
+
+        out.close ();
+
+        if ( isUsage ) {
+            System.out.format ( "[Confirmed usage output]\n" );
+        }
+        else {
+            System.out.format ( "[ERROR: output does not contains usage information]\n" );
+            throw new RuntimeException ( "Application output does not contains usage information" );
+        }
+    }
+    catch ( Throwable Th ) {
+        System.out.println ( Th.toString () );
+
+        return 1;
+    }
+
+    int retVal = app.exitStatus ();
+
+    System.out.format ( "[Application exited with RC = %d]\n", retVal );
+
+    _env.clearTestEnv ();
+
+    return retVal == 0 ? 1 : 0;
+}
+
+};
diff --git a/test/dbgap-mount/jaba/test/TestSuper.java b/test/dbgap-mount/jaba/test/TestSuper.java
new file mode 100644
index 0000000..00623b2
--- /dev/null
+++ b/test/dbgap-mount/jaba/test/TestSuper.java
@@ -0,0 +1,467 @@
+package jaba.test;
+
+import jaba.platform.Platform;
+import jaba.DbGapMountTestEnv;
+import jaba.App;
+import jaba.AppTerminator;
+import jaba.Utils;
+import java.time.LocalDateTime;
+import java.nio.file.*;
+import java.io.File;
+import java.io.BufferedReader;
+import java.util.Vector;
+import java.util.StringTokenizer;
+
+public abstract
+class
+TestSuper
+    implements Test, AppTerminator {
+
+protected Platform _platform = null;
+protected DbGapMountTestEnv _env = null;
+private boolean _running = false; 
+private int _exitStatus = 0;
+
+public
+TestSuper ( Platform platform )
+{
+    _platform = platform;
+
+    _env = new DbGapMountTestEnv ( platform );
+
+    _running = false;
+    _exitStatus = 0;
+}   /* TestSuper () */
+
+public
+String
+getName ()
+{
+    return getClass ().getSimpleName ();
+}   /* getName () */
+
+    /*>>    By default test should be part of VDB-1528, which is
+      ||    umbrella for all other tickets ... or most of them
+      <<*/
+public  
+String []
+tickets ()
+{
+    String [] retVal = { "VDB-1528" };
+    return retVal;
+}   /* tickets () */
+
+public
+int
+umount ()
+{
+    Utils.sleepSec ( 2 );
+
+    String MP = _platform.getTarget ( Platform.TargetName.MountPoint );
+
+    String Cmd = _platform.getTarget ( Platform.TargetName.MountApp );
+    Cmd += " -u " + MP;
+
+    System.out.println ( "Unmounting [" + MP + "] [" + Cmd + "]" );
+
+    int RC = 0;
+
+try {
+    App app = new App ( Cmd, _platform.getProcessEnvironment () );
+    app.start ();
+    app.waitFor ();
+
+    RC = app.exitStatus ();
+}
+catch ( Throwable Th ) {
+System.out.println ( "Umount failed : " + Th.toString () );
+}
+
+    Utils.sleepSec ( 2 );
+
+    boolean failed = false;
+
+    try {
+        simpleUmountCheck ();
+    }
+    catch ( Throwable Th ) {
+        System.out.println ( "Umount check failed : " + Th.toString () );
+
+        failed = true;
+
+        RC = 2;
+    }
+
+    return RC;
+}   /* umount () */
+
+public
+boolean
+gentleTerminate ()
+{
+        /*  I am too lazy to write one more layer, so this would be
+         *  common as full, not empty.
+         */
+
+        /*  Two step process call "command -u mountpoint"
+         *  if does not work, call "dokancnt /m mountpoint" or 
+         *                         "fusermount -u mountpoint"
+         *  if does not work, return to parent method, destroying
+         *  process, but it does never work
+         */
+    if ( umount () == 0 ) {
+        return true;
+    }
+
+    String Cmd = _platform.getTarget ( Platform.TargetName.UmountApp );
+    Cmd += " " + _platform.getTarget ( Platform.TargetName.MountPoint );
+
+    App app = new App ( Cmd, _platform.getProcessEnvironment () );
+    app.start ();
+    app.waitFor ();
+    if ( app.exitStatus () == 0 ) {
+        return true;
+    }
+
+    return false;
+}   /* gentleTerminate () */
+
+public
+void
+intro ()
+{
+    System.out.println ( "" );
+    System.out.println ( "||<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" );
+    System.out.println ( "||<<< Test STARTED [" + getName () + "] [" + LocalDateTime.now () + "]" );
+    System.out.println ( "||<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" );
+}   /* intro () */
+
+public
+void
+outro ()
+{
+    System.out.println ( "||<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" );
+    if ( exitStatus () == 0 ) {
+        System.out.println ( "||<<< Test PASSED [" + getName () + "] [" + LocalDateTime.now () + "]" );
+    }
+    else {
+        System.out.println ( "||<<< Test FAILED [" + getName () + "] [" + LocalDateTime.now () + "]" );
+    }
+    System.out.println ( "||<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" );
+}   /* outro () */
+
+abstract protected
+int
+runTest ();
+
+public
+void
+run ()
+{
+    intro ();
+
+    _running = true;
+
+    try {
+        _exitStatus = 0;
+
+        _exitStatus = runTest ();
+    }
+    catch ( Throwable Th ) {
+        System.err.format ( "Test [%s] failed because: %s\n", getName (), Th.toString () );
+        _exitStatus = 666;
+    }
+
+    _running = false;
+
+    outro ();
+}   /* run () */
+
+public
+int
+exitStatus ()
+{
+    if ( _running ) {
+        throw new RuntimeException ( "Can not return exitStatus on running test [" + getName () + "]" );
+    }
+
+    return _exitStatus;
+}   /* exitStatus () */
+
+protected
+int
+runMounter ()
+{
+    return 0;
+}   /* runMounter () */
+
+protected
+void
+simpleMountCheck ( )
+{
+    System.out.println ( "Performing mount check on  ["
+                + _platform.getTarget ( Platform.TargetName.MountPoint )
+                + "]" )
+                ;
+
+
+    String [] Targets = { "cache", "kart-files", "karts", "workspace" };
+
+    for ( int i = 0; i < Targets.length; i ++ ) {
+        String ThePath =
+                  _platform.getTarget ( Platform.TargetName.MountPoint )
+                + _platform.getTarget ( Platform.TargetName.Separator )
+                + Targets [ i ]
+                ;
+        if ( !Files.isDirectory ( Paths.get ( ThePath ) ) ) {
+            throw new RuntimeException ( "Invalid mount : can not locate [" + Targets [ i ] + "] directory" );
+
+        }
+
+        System.out.println ( "Found [" + ThePath + "] directory" );
+    }
+
+}   /* simpleMountCheck () */
+
+protected
+void
+simpleUmountCheck ( )
+{
+    String MP = _platform.getTarget ( Platform.TargetName.MountPoint );
+
+    System.out.println ( "Performing umount check on  [" + MP + "]" ) ;
+
+    if ( _platform.needCreateMountPoint() ) {
+        File file = new File ( MP );
+        if ( file.isDirectory () ) {
+            if ( file.list () != null ) {
+                if ( file.list().length > 0 ) {
+                    throw new RuntimeException ( "Mount point still mounted [" + MP + "]" );
+                }
+            }
+        }
+        else {
+            throw new RuntimeException ( "Mount point is not a directory [" + MP + "]" );
+        }
+    }
+    else {
+        if ( new File ( MP ).exists () ) {
+            throw new RuntimeException ( "Mount point still exists [" + MP + "]" );
+        }
+    }
+}   /* simpleUmountCheck () */
+
+protected
+void
+sleepSec ( long sec )
+{
+    try { Thread.sleep ( 1000 * sec ); } catch ( Throwable Th ) { };
+}   /* sleepSec () */
+
+/* There are IO methods to use in tests. They are not cool, but I
+ * had to do that.
+ */
+
+private
+String []
+runWrapCmd ( String params, boolean return_out )
+{
+    String [] retVal = {};
+    String cmd = "java jaba.WrapCmd";
+
+    try {
+        cmd += " " + params;
+
+        // System.out.println ( "RUN[" + cmd + "]" );
+
+        App app = new App ( cmd, _platform.getProcessEnvironment () );
+        app.start ();
+        app.waitFor ();
+
+        int RC = app.exitStatus ();
+
+        if ( return_out ) {
+            Vector < String > lines = new Vector < String > ();
+            BufferedReader out = new BufferedReader ( app.getOutStream () );
+            String line;
+            while ( ( line = out.readLine() ) != null ) {
+                line = line.trim ();
+                if ( ! line.isEmpty () ) {
+                    lines.addElement ( line );
+                }
+            }
+            out.close ();
+
+            retVal = lines.toArray ( retVal );
+        }
+        else {
+            BufferedReader out = new BufferedReader ( app.getOutStream () );
+            String line;
+            boolean was_out = false;
+            while ( ( line = out.readLine() ) != null ) {
+                if ( ! was_out ) {
+                    System.out.println ( "[STDOUT: begin]" );
+                }
+                System.out.println ( line );
+            }
+            out.close ();
+
+            if ( was_out ) { System.out.println ( "[STDOUT: end]" ); }
+            // else { System.out.println ( "[STDOUT: empty]" ); }
+        }
+
+        {
+            BufferedReader out = new BufferedReader ( app.getErrStream () );
+            String line;
+            boolean was_out = false;
+            while ( ( line = out.readLine() ) != null ) {
+                if ( ! was_out ) {
+                    System.out.println ( "[STDERR: begin]" );
+                }
+                System.out.println ( line );
+            }
+            out.close ();
+
+            if ( was_out ) { System.out.println ( "[STDERR: end]" ); }
+            // else { System.out.println ( "[STDERR: empty]" ); }
+        }
+
+    }
+    catch ( Throwable Th ) {
+        System.out.println ( "Error: " + Th.toString () );
+
+        throw new RuntimeException ( "Error: can not run command [" + cmd + "]" );
+    }
+
+    return retVal;
+}   /* runWrapCmd () */
+
+protected
+void
+createFile ( String fileName, int fileSize, boolean deleteAfter )
+{
+    System.out.printf ( "createFile [%s] with size [%d]\n", fileName, fileSize );
+    String params =   "CF "
+                    + fileName
+                    + " "
+                    + new Integer ( fileSize ).toString ()
+                    ;
+    runWrapCmd ( params, false );
+
+    sleepSec ( 1 );
+
+    int size = fileSize ( fileName );
+    if ( size != fileSize ) {
+        throw new RuntimeException ( "Invalid file size [" + fileName + "]" );
+    }
+
+    sleepSec ( 1 );
+
+    if ( deleteAfter ) {
+        unlink ( fileName );
+    }
+
+    sleepSec ( 1 );
+}   /* createFile () */
+
+protected
+void
+createDir ( String dirName )
+{
+    System.out.printf ( "createDir [%s]\n", dirName );
+    runWrapCmd ( "CD " + dirName, false );
+}   /* createDir () */
+
+protected
+void
+copyFile ( String from, String to )
+{
+    System.out.printf ( "copyFile [%s] to [%s]\n", from, to );
+    runWrapCmd ( "CP " + from + " " + to, false );
+}   /* createFile () */
+
+protected
+boolean
+compareFiles ( String file1, String file2 )
+{
+    try {
+        System.out.printf ( "compareFiles [%s] and [%s]\n", file1, file2 );
+        runWrapCmd ( "CM " + file1 + " " + file2, false );
+        return true;
+    }
+    catch ( Throwable Th ) { }
+
+    return false;
+}   /* compareFiles () */
+
+class FileStat {
+    FileStat () 
+    {
+        _type = null;
+        _size = 0;
+    }
+
+    FileStat ( String line ) {
+        StringTokenizer st = new StringTokenizer ( line );
+        _type = st.nextToken ();
+        _size = Integer.parseInt ( st.nextToken () );
+
+        if ( ! _type.equals ( "F" ) && ! _type.equals ( "D" ) ) {
+            throw new RuntimeException ( "Invalid file tupe [" + _type + "]" );
+        }
+    }
+
+    protected String _type;
+    protected int _size;
+};
+
+protected
+FileStat
+fileStat ( String path )
+{
+    String [] ar = runWrapCmd ( "FS " + path, true );
+    if ( ar.length == 1 ) {
+        return new FileStat ( ar [ 0 ] );
+    }
+
+    throw new RuntimeException ( "Error: invalid [FS] command output format" );
+}   /* fileStat () */
+
+protected
+int
+fileSize ( String path )
+{
+    System.out.printf ( "fileSize [%s]\n", path );
+    return fileStat ( path )._size;
+}   /* fileSize () */
+
+protected
+boolean
+isDirectory ( String path )
+{
+    System.out.printf ( "isDirectory [%s]\n", path );
+    return fileStat ( path )._type.equals ( "D" );
+}   /* isDirectory () */
+
+protected
+void
+list ( String path )
+{
+    System.out.printf ( "list [%s]\n", path );
+    String [] the_list = runWrapCmd ( "LS " + path, true );
+    if ( the_list != null ) {
+        for ( int llp = 0; llp < the_list.length; llp ++ ) {
+            System.out.printf ( "%s\n", the_list [ llp ] );
+        }
+    }
+}   /* list () */
+
+protected
+void
+unlink ( String path )
+{
+    System.out.printf ( "unlink [%s]\n", path );
+    runWrapCmd ( "UL " + path, false );
+}   /* unlink () */
+
+};
diff --git a/test/dbgap-mount/jaba/test/TestWorkspace.java b/test/dbgap-mount/jaba/test/TestWorkspace.java
new file mode 100644
index 0000000..1553402
--- /dev/null
+++ b/test/dbgap-mount/jaba/test/TestWorkspace.java
@@ -0,0 +1,179 @@
+package jaba.test;
+
+import jaba.App;
+import jaba.platform.Platform;
+import jaba.DbGapMountTestEnv;
+import java.io.BufferedReader;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.Path;
+
+/*>>> Simple test. Should start mounter without parameters.
+ <<<  Program should print help and return non-zero code
+  >>>
+ <<<*/
+
+public 
+class TestWorkspace
+    extends TestBasicBase {
+
+public
+TestWorkspace ( Platform platform )
+{
+    super ( platform );
+}   /* TestWorkspace () */
+
+public
+String []
+tickets ()
+{
+    String [] r = {
+              "VDB-1528"
+            , "VDB-1527"    /* Dokan module for bi-directional
+                             * encryption on Windows
+                             */
+            , "VDB-1526"    /* FUSE module for bi-directional
+                             * encryption on Linux and Mac
+                             */
+            , "VDB-1563"    /* Debug directory-level of FUSE/Dokan
+                             * implementation
+                             */
+            , "VDB-2701"    /* Implement Read Only mode for
+                             * encrypted file sytem and remove
+                             * from Cache directory
+                             */
+            };
+    return r;
+}   /* tickets () */
+
+    /* The ticket VDB-1563 is main issue: if size of written file
+     * is fraction of 32K, file get corrupted. So, we check it.
+     * Start Tool Daemon. Create file 32K, write. Stop Tool.
+     * Start Tool Daemon and compare files. Stop tool.
+     * That chould 
+     */
+protected
+void
+runActualTest ()
+{
+
+    String dirPath = pathToFile ( "dir_1" );
+    String dirPathFile =
+                  dirPath
+               + _platform.getTarget ( Platform.TargetName.Separator )
+               + ".nested_file"
+               ;
+
+        /* Creatin' and manipulating files
+         */
+    try {
+        start ( false );
+
+            /* Creatin' random file and deleting it
+             */
+        createFile ( pathToFile ( "file_0" ), 33, true );
+
+            /* Creatin' 32K file and smaller file
+             */
+        createFile ( pathToFile ( "file_1" ), 32768, false );
+
+            /* Makin' copy of file
+             */
+        copyFile (
+                pathToFile ( "file_1" ),
+                pathToTempFile ( "file_1" )
+                );
+
+            /* Checkin' copy of file
+             */
+        if ( ! compareFiles (
+                pathToFile ( "file_1" ),
+                pathToTempFile ( "file_1" )
+                ) ) {
+            throw new RuntimeException ( "ERROR: copied files are different [" + pathToFile ( "file_1" ) + "] and [" + pathToTempFile ( "file_1" ) + "]" );
+        }
+
+            /* Creatin' deletin' directory and nested file
+             */
+        createDir ( dirPath );
+        createFile ( dirPathFile, 33, false );
+        unlink ( dirPath );
+
+            /* Creatin' directory and nested file
+             */
+        createDir ( dirPath );
+        createFile ( dirPathFile, 33, false );
+        list ( pathToFile ( "" ) );
+
+        stop ();
+    }
+    catch ( Throwable Th ) {
+        stop ();
+
+        System.out.println ( "ERROR: " + Th.toString () );
+
+        throw Th;
+    }
+
+    sleepSec ( 2 );
+
+if ( true ) return;
+
+        /* Checkin' RO mode and validity of workspace files
+         */
+    try {
+        start ( true );
+
+            /* Checkin' content of file one more time after remount
+             */
+        if ( ! compareFiles (
+                pathToFile ( "file_1" ),
+                pathToTempFile ( "file_1" )
+                ) ) {
+            throw new RuntimeException ( "ERROR: copied files are different [" + pathToFile ( "file_1" ) + "] and [" + pathToTempFile ( "file_1" ) + "]" );
+        }
+
+            /* Checkin' if we are able to create file
+             */
+        boolean wrong = false;
+        try {
+            createFile ( "file_0", 33, true );
+            wrong = true;
+        } catch ( Throwable Th ) { /* That's is OK */ }
+        if ( wrong ) {
+            throw new RuntimeException ( "ERROR: was able to create file [file_0]" );
+        }
+
+            /* Checkin' if we are able to delete file
+             */
+        wrong = false;
+        try {
+            unlink ( pathToFile ( "file_1" ) );
+            wrong = true;
+        } catch ( Throwable Th ) { /* That's is OK */ }
+        if ( wrong ) {
+            throw new RuntimeException ( "ERROR: was able to delete file [file_1]" );
+        }
+
+            /* Checking' directory and nested file
+             */
+        if ( ! Files.exists ( Paths.get ( dirPath ) ) ) {
+            throw new RuntimeException ( "ERROR: can not find directory [dir_1]" );
+        }
+        if ( ! Files.exists ( Paths.get ( dirPathFile ) ) ) {
+            throw new RuntimeException ( "ERROR: can not find file [dir_1/.nested_file]" );
+        }
+        list ( pathToFile ( "" ) );
+
+        stop ();
+    }
+    catch ( Throwable Th ) {
+        stop ();
+
+        System.out.println ( "ERROR: " + Th.toString () );
+
+        throw Th;
+    }
+}
+
+};
diff --git a/test/dbgap-mount/jaba/test/Tests.java b/test/dbgap-mount/jaba/test/Tests.java
new file mode 100644
index 0000000..9e31c83
--- /dev/null
+++ b/test/dbgap-mount/jaba/test/Tests.java
@@ -0,0 +1,171 @@
+package jaba.test;
+
+import jaba.platform.Platform;
+import java.io.File;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.BufferedReader;
+import java.util.Vector;
+import java.lang.reflect.Constructor;
+
+/* That class will open file Test.list in the same package,
+ * read list of tests available
+ */
+
+public
+class
+Tests {
+
+
+private Platform _platform = null;
+private String [] _tests = {};
+
+public
+Tests ( Platform platform )
+{
+    if ( platform == null ) {
+        throw new RuntimeException ( "NULL platform passed" );
+    }
+
+    _platform = platform;
+
+    loadTests ();
+
+}   /* Tests () */
+
+public
+void
+run ( String TestName ) 
+{
+    if ( TestName == null ) {
+        throw new RuntimeException ( "ERROR: NULL test name passed" );
+    }
+
+    Test test = testForName ( TestName );
+    if ( test == null ) {
+        throw new RuntimeException ( "ERROR: Can not find test for [" + TestName + "]" );
+    }
+
+    test.run ();
+
+    if ( test.exitStatus () != 0 ) {
+        throw new RuntimeException ( "ERROR: Test failed [" + TestName + "[" );
+    }
+}   /* run () */
+
+public
+void
+run ()
+{
+    for ( int llp = 0; llp < _tests.length; llp ++ ) {
+        run ( _tests [ llp ] );
+    }
+}   /* run () */
+
+public
+void
+printTests ( boolean WithTickets )
+{
+}   /* printTests () */
+
+public
+void
+printTickets ( boolean WithTests )
+{
+}   /* printTests () */
+
+private
+void
+loadTests ()
+{
+    try { 
+        String rName = getClass ().getSimpleName () + ".list";
+
+        InputStream in = getClass ().getResourceAsStream ( rName );
+
+        BufferedReader rd = new BufferedReader (
+                        new InputStreamReader (
+                            getClass ().getResourceAsStream ( rName )
+                        )
+                    );
+
+        Vector < String > tests = new Vector < String > ();
+        String line;
+        while ( ( line = rd.readLine () ) != null ) {
+            String test = parseLine ( line );
+
+            if ( test != null ) {
+                tests.addElement ( test );
+            }
+        }
+
+        rd.close ();
+
+        _tests = tests.toArray ( _tests );
+    } 
+    catch ( Throwable Th ) {
+        throw new RuntimeException ( Th.toString () );
+    }
+}   /* loadTests () */
+
+private
+String
+parseLine ( String line )
+{
+        /* Simple : trim and check if it does not start with "#"
+         */
+    String retVal = line.trim ();
+    if ( retVal.isEmpty () ) {
+        return null;
+    }
+
+    return retVal.charAt (0) == '#' ? null : retVal; 
+}   /* parseLine () */
+
+    /*>> We suppose that all Test classes have only one constructor
+     <<  which required instance of 'jaba.platform.Platform' class
+      >> We will load class by it's name then. Simple algo: if class
+     <<  name contains '.' we suppose it is full name with package,
+      >> overwise it will use name "java.test.Test##Name"
+     <<*/
+private
+Test
+testForName ( String Name )
+{
+    if ( Name == null ) {
+        throw new RuntimeException ( "Test name missed for platform [" + _platform.getOS () + "]" );
+    }
+
+    try {
+        String className = Name;
+        if ( Name.indexOf ( '.' ) == 1 * - 1 ) {
+            className = getClass ().getPackage().getName() + ".Test" + Name;
+        }
+
+        Class testClass = Class.forName ( className );
+        if ( testClass == null ) {
+            throw new RuntimeException ( "Can not find class for [" + className + "] on [" + _platform + "] platform" );
+        }
+
+        Constructor constructor = testClass.getConstructor (
+                                                        Platform.class
+                                                        );
+        if ( constructor == null ) {
+            throw new RuntimeException ( "Can not find constructor for class [" + className + "] on [" + _platform + "] platform" );
+        }
+
+        Object object = constructor.newInstance (
+                                            new Object [] { _platform }
+                                            );
+        if ( object == null ) {
+            throw new RuntimeException ( "Can not construct instance for class [" + className + "] on [" + _platform + "] platform" );
+        }
+
+        return ( Test ) object;
+    }
+    catch ( Throwable Th ) {
+        throw new RuntimeException ( Th.toString () );
+    }
+}   /* testForName () */
+
+};
diff --git a/test/dbgap-mount/py/main.py b/test/dbgap-mount/py/main.py
new file mode 100644
index 0000000..9a467d6
--- /dev/null
+++ b/test/dbgap-mount/py/main.py
@@ -0,0 +1,17 @@
+import sys
+
+import platform
+
+import test
+
+if len ( sys.argv ) != 2 :
+    print ( "Invalid arguments\n" )
+    exit ( 1 )
+
+plt = platform.Platform ( sys.argv [ 1 ] )
+
+# plt.about ()
+
+tst = test.Test ( plt )
+
+tst.run ()
diff --git a/test/dbgap-mount/py/platform/__init__.py b/test/dbgap-mount/py/platform/__init__.py
new file mode 100644
index 0000000..13cc003
--- /dev/null
+++ b/test/dbgap-mount/py/platform/__init__.py
@@ -0,0 +1,14 @@
+import sys
+
+# We should load appropriate module for appropriate OS
+#
+
+if sys.platform == 'linux2':
+    from platform.lin import *
+elif sys.platform == 'darwin':
+    from platform.mac import *
+elif sys.platform == 'win32':
+    from platform.win import *
+else:
+    raise ImportError ( "Platfrom '%s' is not supported" %(sys.platform) )
+
diff --git a/test/dbgap-mount/py/platform/base.py b/test/dbgap-mount/py/platform/base.py
new file mode 100644
index 0000000..af21ea9
--- /dev/null
+++ b/test/dbgap-mount/py/platform/base.py
@@ -0,0 +1,123 @@
+import os
+import os.path
+
+class Base:
+
+    TEST_DIR_NAME = "DbGapMountTest"
+
+    def __init__ ( self, appd ):
+        if os.path.exists ( appd ) == False:
+            raise OSError ( "Can not stat directory '%s'" %( appd ) )
+
+        self._app_dir = appd
+        self._sep = os.sep
+        self._user_dir = os.path.expanduser("~")
+
+    def get_os ( self ):
+        raise NameError ( "Unsupported OS" )
+
+    def input_data_dir ( self ):
+        return "/panfs/pan1/trace_work/iskhakov/IMPORTANT_DIR"
+
+    def separator ( self ):
+        return self._sep
+
+    def user_dir ( self ):
+        return self._user_dir
+
+    def app_dir ( self ):
+        return self._app_dir
+
+    def test_dir ( self ):
+        return self.user_dir () \
+                    + self.separator () \
+                    + self.TEST_DIR_NAME \
+                    + self.get_os ()
+
+    def config_dir ( self ):
+        return self.test_dir () \
+                    + self.separator () \
+                    + ".ncbi"
+
+    def data_dir ( self ):
+        return self.test_dir () \
+                    + self.separator ()    \
+                    + "ncbi"
+
+    def temp_dir ( self ):
+        return self.test_dir () \
+                    + self.separator ()    \
+                    + "temp"
+
+    def config_file ( self ):
+        return self.config_dir () \
+                    + self.separator ()     \
+                    + "user-settings.mkfg"
+
+    def mount_point ( self ):
+        return self.test_dir () \
+                    + self.separator ()     \
+                    + "mount"
+
+    def project ( self ):
+        return 6570
+
+    def ngc_file ( self ):
+        return self.input_data_dir ()   \
+                    + self.separator () \
+                    + self.TEST_DIR_NAME \
+                    + self.separator () \
+                    + "prj_"    \
+                    + str ( self.project () )   \
+                    + ".ngc"
+
+    def kart_file ( self ):
+        return self.input_data_dir ()   \
+                    + self.separator () \
+                    + self.TEST_DIR_NAME \
+                    + self.separator () \
+                    + "kart_prj_"    \
+                    + str ( self.project () )   \
+                    + ".krt"
+
+    def mount_app ( self ):
+        return self.app_dir ()  \
+                    + self.separator () \
+                    + "dbgap-mount-tool"
+
+    def config_app ( self ):
+        return self.app_dir ()  \
+                    + self.separator () \
+                    + "vdb-config"
+
+    def dump_app ( self ):
+        return self.app_dir ()  \
+                    + self.separator () \
+                    + "fastq-dump-new"
+
+    def umount_app ( self ):
+        raise NameError ( "Unsupported OS" )
+
+    def create_mount_point ( self ):
+        return True
+
+    def set_environment ( self ):
+        os.putenv ( "NCBI_HOME", self.config_dir () )
+
+    def about ( self ):
+        print ( str ( self ) )
+        print ( self.separator () )
+        print ( self.config_dir () )
+        print ( self.test_dir () )
+        print ( self.data_dir () )
+        print ( self.temp_dir () )
+        print ( self.config_file () )
+        print ( self.mount_point () )
+        print ( str ( self.project () ) )
+        print ( str ( self.ngc_file () ) )
+        print ( str ( self.kart_file () ) )
+        print ( self.mount_app () )
+        print ( self.config_app () )
+        print ( self.dump_app () )
+        print ( self.umount_app () )
+        print ( str ( self.create_mount_point () ) )
diff --git a/test/dbgap-mount/py/platform/lin.py b/test/dbgap-mount/py/platform/lin.py
new file mode 100644
index 0000000..a0b141d
--- /dev/null
+++ b/test/dbgap-mount/py/platform/lin.py
@@ -0,0 +1,9 @@
+import platform.base
+
+class Platform(platform.base.Base):
+
+    def get_os ( self ):
+        return "Lnx"
+
+    def umount_app ( self ):
+        return "/bin/fusermount -u"
diff --git a/test/dbgap-mount/py/platform/mac.py b/test/dbgap-mount/py/platform/mac.py
new file mode 100644
index 0000000..8ab06e9
--- /dev/null
+++ b/test/dbgap-mount/py/platform/mac.py
@@ -0,0 +1,12 @@
+import platform.base
+
+class Platform(platform.base.Base):
+
+    def get_os ( self ):
+        return "Mac"
+
+    def input_data_dir ( self ):
+        return "/net/pan1/trace_work/iskhakov/IMPORTANT_DIR"
+
+    def umount_app ( self ):
+        return "/sbin/umount"
diff --git a/test/dbgap-mount/py/platform/win.py b/test/dbgap-mount/py/platform/win.py
new file mode 100644
index 0000000..904df95
--- /dev/null
+++ b/test/dbgap-mount/py/platform/win.py
@@ -0,0 +1,33 @@
+import platform.base
+
+class Platform(platform.base.Base):
+
+    def get_os ( self ):
+        return "Win"   
+
+    def input_data_dir ( self ):
+        return "\\\\panfs\\pan1\\trace_work\\iskhakov\\IMPORTANT_DIR"
+
+    def umount_app ( self ):
+        return "c:\\\\ProgramFiles (x86)\\Dokan\\DokanLibrary\\dokanctl.exe /u"
+
+    def mount_point ( self ):
+        return "r:"
+
+    def mount_app ( self ):
+        return self.app_dir ()   \
+                    + self.separator () \
+                    + "dbgap-mount-tool.exe"
+
+    def config_app ( self ):
+        return self.app_dir ()   \
+                    + self.separator () \
+                    + "vdb-config.exe"
+
+    def dump_app ( self ):
+        return self.app_dir ()   \
+                    + self.separator () \
+                    + "fastq-dump-ngs.exe"
+
+    def create_mount_point ( self ):
+        return False
diff --git a/test/dbgap-mount/py/test/__init__.py b/test/dbgap-mount/py/test/__init__.py
new file mode 100644
index 0000000..38e199c
--- /dev/null
+++ b/test/dbgap-mount/py/test/__init__.py
@@ -0,0 +1,7 @@
+# Here we will store all test modules
+#
+
+
+from base import *
+from test import *
+from utils import *
diff --git a/test/dbgap-mount/py/test/base.py b/test/dbgap-mount/py/test/base.py
new file mode 100644
index 0000000..e1682be
--- /dev/null
+++ b/test/dbgap-mount/py/test/base.py
@@ -0,0 +1,160 @@
+import platform
+import os.path
+import shutil
+import subprocess
+
+class Base ( object ):
+
+    _platform = None
+
+    def __init__ ( self, plt ):
+        self._platform = plt
+
+    def platform ( self ):
+        return self._platform
+
+## Various checks
+##
+    def checkPath ( self, path ):
+        if not os.path.exists ( path ):
+            raise OSError ( "Can not find path [" + path + "]" )
+
+    def checkDir ( self, path ):
+        self.checkPath ( path )
+        if not os.path.isdir ( path ):
+            raise OSError ( "Path is not a directory [" + path + "]" )
+
+    def checkFile ( self, path ):
+        self.checkPath ( path )
+        if not os.path.isfile ( path ):
+            raise OSError ( "Path is not a file [" + path + "]" )
+
+    def checkExecutable ( self, path ):
+        self.checkFile ( path )
+        if not os.access ( path, os.X_OK ):
+            raise OSError ( "File is not executable [" + path + "]" )
+
+    def checkExecutables ( self ):
+        print ( "# Checking Executables" )
+        self.checkExecutable ( self.platform ().mount_app () )
+        self.checkExecutable ( self.platform ().config_app () )
+        self.checkExecutable ( self.platform ().dump_app () )
+
+    def checkInputs ( self ):
+        print ( "# Checking Input Files" )
+        self.checkFile ( self.platform ().ngc_file () )
+        self.checkFile ( self.platform ().kart_file () )
+
+    def makeDirectory ( self, path ):
+        if not os.path.exists ( path ):
+            print ( "# Create Directory [" + path + "]" )
+            os.mkdir ( path )
+
+    def makeDirectories ( self ):
+        print ( "# Making Directories" )
+        self.makeDirectory ( self.platform ().test_dir () )
+        self.makeDirectory ( self.platform ().config_dir () )
+        self.makeDirectory ( self.platform ().data_dir () )
+        self.makeDirectory ( self.platform ().temp_dir () )
+        if ( self.platform ().create_mount_point () ):
+            self.makeDirectory ( self.platform ().mount_point () )
+
+    def configureNo ( self ):
+        cfg_file = self.platform ().config_file ()
+        if os.path.exists ( cfg_file ):
+            os.delete ( cfg_file )
+
+    def configureBad ( self ):
+        self.configureNo ()
+        cfg_file = self.platform ().config_file ()
+        print ( "# Configuring [" + cfg_file + "]" )
+        file = open ( cfg_file, "w" )
+        file.write ( "## auto-generated configuration file - DO NOT EDIT ##\n\n" )
+        file.write ( "/repository/user/default-path = \"" + self.pathToPosix ( self.platform ().data_dir () ) + "\"\n" )
+        print ( "/repository/user/default-path = \"" + self.pathToPosix ( self.platform ().data_dir () ) + "\"\n" )
+        file.close ()
+
+    def configureGood ( self ):
+        self.configureBad ()
+        cfg_file = self.platform ().config_file ()
+        self.platform ().set_environment ()
+        cfg_cmd = self.platform ().config_app() \
+                        + " --import"   \
+                        + self.platform ().ngc_file ()
+        if subprocess.call ( [ self.platform ().config_app(), "--import", self.platform ().ngc_file () ] ) != 0:
+            raise Exception ( "Failed to run command [" + cfg_cmd + "]" )
+    def configure ( self ):
+        self.configureGood ();
+
+## Here long bunch of methods which will create affordable 
+## configuration
+##
+    def removeTestEnvironment ( self ):
+        test_dir = self._platform.test_dir ()
+        if ( os.path.exists ( test_dir ) ):
+            print ( "# Removing old test directories at [" + test_dir + "]\n" )
+            shutil.rmtree ( test_dir )
+
+    def createTestEnvironment ( self ):
+        self.checkExecutables ()
+        self.checkInputs ()
+
+        test_dir = self._platform.test_dir ()
+        print ( "# Creating new test environment at [" + test_dir + "]\n" )
+        self.removeTestEnvironment ()
+        self.makeDirectories ()
+        self.configure ()
+
+## Here is simple mount check
+##
+    def simpleMountCheck ( self ):
+        mnt_pnt = self.platform ().mount_point ()
+        print ( "# Performing mount pont check [" + mnt_pnt + "]" )
+
+        targets = [ "cache", "kart-files", "karts", "workspace" ]
+        for value in targets:
+            self.checkDir ( mnt_pnt + self.platform ().separator () + value )
+
+    def simpleUmountCheck ( self ):
+        mnt_pnt = self.platform ().mount_point ()
+        print ( "# Performing umount pont check [" + mnt_pnt + "]" )
+        if self.platform ().create_mount_point ():
+            if os.listdir ( mnt_pnt ):
+                raise Exception ( "Mount point still in use [" + mnt_pnt + "]" )
+        else:
+            if os.path.exists ( mnt_pnt ):
+                raise Exception ( "Mount point still in use [" + mnt_pnt + "]" )
+
+
+## Pathetic methods ...
+##
+    def pathToPosix ( self, path ):
+        if str.isalpha ( path [ 0 ] ) and path [ 1 ] == ':':
+            retval = path [ 2 : ]
+            if retval [ 0 ] == '\\':
+                retval = "/" + path [ 0 ] + retval
+            else:
+                retval = "/" + path [ 0 ] + "/" + retval
+        else:
+            retval = path
+
+        return retval.replace ( "\\", "/" )
+
+    def bump ( self ):
+        print ( "===============================================================================" );
+        print ( "===============================================================================" );
+
+    def workspacePath ( self, path ):
+        return self.platform ().mount_point()   \
+                + self.platform ().separator () \
+                + "workspace"   \
+                + self.platform ().separator () \
+                + path
+
+
+    def tempPath ( self, path ):
+        return self.platform ().temp_dir()   \
+                + self.platform ().separator () \
+                + path
+
+
diff --git a/test/dbgap-mount/py/test/test.py b/test/dbgap-mount/py/test/test.py
new file mode 100644
index 0000000..9425e91
--- /dev/null
+++ b/test/dbgap-mount/py/test/test.py
@@ -0,0 +1,125 @@
+import os
+import sys
+import time
+import subprocess
+import gc
+
+import platform
+import base
+import utils
+
+class Test ( base.Base ):
+
+    def __init__ ( self, plt ):
+        super ( Test, self ).__init__( plt )
+
+    def startDetached ( self ):
+        super ( Test, self ).bump ()
+        print ( "Start detached process" )
+            ## Starting mount tool
+            ##
+        mnt_cmd =  super ( Test, self ).platform ().mount_app ()    \
+                + " -d "    \
+                + str ( super ( Test, self ).platform ().project () ) \
+                + " "   \
+                + super ( Test, self ).platform ().mount_point ()
+        print ( "SYS [%s]\n" %( mnt_cmd ) )
+        if subprocess.call (  [   \
+                super ( Test, self ).platform ().mount_app (),  \
+                "-d",   \
+                str ( super ( Test, self ).platform ().project () ),    \
+                super ( Test, self ).platform ().mount_point () \
+                ]   \
+                ) != 0:
+            raise Exception ( "Can not execute command [" + mnt_cmd + "]" )
+            ## Give one second to establish mount and checking mount
+            ##
+        time.sleep ( 1 )
+
+        super ( Test, self ).simpleMountCheck ()
+
+    def stopDetached ( self ):
+            ## For now we are stoppin' without handling any exceptions
+            ##
+        umnt_cmd =  super ( Test, self ).platform ().mount_app ()    \
+                + " -u "    \
+                + super ( Test, self ).platform ().mount_point ()
+        print ( "SYS [%s]\n" %( umnt_cmd ) )
+#        if subprocess.call ( [   \
+#                super ( Test, self ).platform ().mount_app (),  \
+#                "-u",   \
+#                super ( Test, self ).platform ().mount_point () \
+#                ]   \
+#                ) != 0:
+#            raise Exception ( "Can not execute command [" + mnt_cmd + "]" )
+        if subprocess.call ( [   \
+                "/usr/sbin/diskutil"    \
+                "unmountDisk"   \
+                "force" \
+                "/Users/iskhakov/DbGapMountTestMac/mount"
+                ]   \
+                ) != 0:
+            raise Exception ( "Can not execute command [" + mnt_cmd + "]" )
+        time.sleep ( 1 )
+
+        super ( Test, self ).simpleUmountCheck ()
+
+    def run ( self ):
+        print ( "Runnin' test\n" )
+
+            ## Configuring
+            ##
+        super ( Test, self ).createTestEnvironment ()
+
+        path_1 = super ( Test, self ).workspacePath ( "file_1.file" )
+        path_2 = super ( Test, self ).workspacePath ( "file_2.file" )
+        path_3 = super ( Test, self ).workspacePath ( "dir" )
+        path_4 = super ( Test, self ).workspacePath ( "dir/file_4.file" )
+        path_2t = super ( Test, self ).tempPath ( "file_2.file" )
+
+            ## First pass
+            ##
+        try:
+            self.startDetached ()
+                ## Creatin' 32K file and smaller files
+            utils.createFile ( path_1, 33 )
+            utils.createFile ( path_2, 32768 )
+
+            gc.collect ()
+            print ( "XXX: " + str ( gc.garbage ) )
+            time.sleep ( 1 )
+
+            utils.checkFileSize ( path_1, 33 )
+            utils.deleteFile ( path_1 )
+
+                ## Copyin' files
+            utils.checkFileSize ( path_2, 32768 )
+            utils.copyFile ( path_2, path_2t )
+
+                ## Directoryin' files
+            # utils.createDirectory ( path_3 )
+            # utils.copyFile ( path_2, path_4 )
+            # utils.listDirectory ( super ( Test, self ).workspacePath ( "." ) )
+            # time.sleep ( 1 )
+
+
+            print ( "XXX: " + str ( gc.garbage ) )
+            self.stopDetached ()
+        except:
+            print ( "XXX: " + str ( gc.garbage ) )
+            self.stopDetached ()
+            print ( "Error:" + str ( sys.exc_info () [ 0 ] ) )
+            raise
+            return
+
+            ## Second pass
+            ##
+        try:
+            self.startDetached ()
+
+            self.stopDetached ()
+        except:
+            self.stopDetached ()
+            print ( "Error:" + str ( sys.exc_info () [ 0 ] ) )
+            return
+
diff --git a/test/dbgap-mount/py/test/utils.py b/test/dbgap-mount/py/test/utils.py
new file mode 100644
index 0000000..9193b19
--- /dev/null
+++ b/test/dbgap-mount/py/test/utils.py
@@ -0,0 +1,79 @@
+import os
+import os.path
+import shutil
+import filecmp
+
+## Deleting file
+##
+def deleteFile ( path ):
+    print ( "# Deleting file [" + path + "]" )
+    if os.path.exists ( path ):
+        os.remove ( path )
+
+def deleteDir ( path ):
+    print ( "# Deleting directory [" + path + "]" )
+    if os.path.exists ( path ):
+        shutil.rmtree ( path )
+
+## Checks if file exists and it's file is correct
+## Checks if file exists and it's file is correct
+##
+def checkFileSize ( path, size ):
+    print ( "# Checking size (" + str ( size ) + ") for file [" + path + "]" );
+    if not os.path.exists ( path ):
+        raise Exception ( "File does not exists [" + path + "]" )
+
+    new_size = os.stat ( path ).st_size
+    if new_size != size:
+        raise Exception ( "Invalid file size " + str ( new_size ) + " for file [" + path + "] had to " + str ( size ) )
+
+## Creates file
+##
+def createFile ( path, size ):
+    print ( "# Writing " + str ( size ) + " bytes to file [" + path + "]" )
+    deleteFile ( path )
+    file = open ( path, "w" )
+    arr="0123456789abcef"
+    arr_size = len ( arr )
+    acc_size = 0
+    while ( acc_size < size ):
+        size_to_write = size - acc_size
+        if arr_size < size_to_write :
+            size_to_write = arr_size
+        file.write ( arr [ : size_to_write ] ) 
+        acc_size += size_to_write;
+    file.close ()
+
+## Copies file
+##
+def copyFile ( src, dst ):
+    print ( "# Copy file [" + src + "] to [" + dst + "]" )
+    deleteFile ( dst )
+    shutil.copyfile ( src, dst )
+
+## Compare files
+##
+def compareFiles ( file1, file2 ):
+    print ( "# Compareing file [" + file1 + "] and [" + file2 + "]" )
+    filecmp.cmp ( file1, file2 )
+
+## Creates directory
+##
+def createDirectory ( path ):
+    print ( "# Creating directory [" + path + "]" )
+    os.makedirs ( path )
+
+## Listing directory content
+##
+def listDirectory ( path, sep = "" ):
+    if not len ( sep ):
+        print ( "# Listing of directory [" + path + "]" )
+    if os.path.exists ( path ):
+        for name in os.listdir ( path ):
+            new_path = path + os.sep + name
+            if os.path.isdir ( new_path ):
+                print ( sep + "[" + name + "][/]")
+                listDirectory ( new_path, sep + "   " )
+            elif os.path.isfile ( new_path ):
+                print ( sep + "[" + name + "]")
+
diff --git a/test/general-loader/Makefile b/test/general-loader/Makefile
index 7098d66..61003e2 100644
--- a/test/general-loader/Makefile
+++ b/test/general-loader/Makefile
@@ -170,6 +170,8 @@ tool-tests: $(TEST_BINDIR)/makeinputs
 	@$(SRCDIR)/runtestcase.sh $(BINDIR) kdbmeta $(SRCDIR) 6packed 0 "-L=info -I=$(VDB_INCDIR)" SOFTWARE/formatter
 	@#    
 	@rm -rf input/*.gl actual/*
+	@#
+	@$(TOP)/$(MODULE)/VDB-3250/prepare_test_data.sh $(TOP) $(TEST_BINDIR)
 
 one-tool: $(TEST_BINDIR)/makeinputs
 	@mkdir -p input && $(TEST_BINDIR)/makeinputs && rm $(TEST_BINDIR)/makeinputs
diff --git a/test/sra-pileup/Makefile b/test/general-loader/VDB-3250/Makefile
similarity index 61%
copy from test/sra-pileup/Makefile
copy to test/general-loader/VDB-3250/Makefile
index 4ad3ec3..ec3cdca 100644
--- a/test/sra-pileup/Makefile
+++ b/test/general-loader/VDB-3250/Makefile
@@ -22,28 +22,63 @@
 #
 # ===========================================================================
 
-default: runtests
+default: prepare_test_data  \
+        check_test_result
 
-TOP ?= $(abspath ../..)
+TOP ?= $(abspath ../../..)
 
-MODULE = test/sra-pileup
+MODULE = test/general-loader/VDB-3250
 
-TEST_TOOLS = 
+TEST_TOOLS = \
+	prepare_test_data   \
+	check_test_result   \
+
+ALL_TOOLS = \
+	$(TEST_TOOLS) \
 
 include $(TOP)/build/Makefile.env
 
-$(TEST_TOOLS): makedirs
+INCDIRS += -I$(TOP)/tools/general-loader
+
+$(ALL_TOOLS): makedirs
 	@ $(MAKE_CMD) $(TEST_BINDIR)/$@
 
-runtests: check_exit_code
+.PHONY: $(TEST_TOOLS)
+
+clean: stdclean
 
 #-------------------------------------------------------------------------------
-# scripted tests
+# chuck
 #
 
-check_exit_code:
-	@ python $(TOP)/build/check-exit-code.py $(BINDIR)/sra-pileup
+PREPARE_DATA_SRC = \
+	prepare_test_data
+
+PREPARE_DATA_OBJ = \
+	$(addsuffix .$(OBJX),$(PREPARE_DATA_SRC))
+
+PREPARE_DATA_LIB =   \
+	-sgeneral-writer  \
+	-sncbi-vdb
+
+$(TEST_BINDIR)/prepare_test_data: $(PREPARE_DATA_OBJ)
+	$(LP) --exe -o $@ $^ $(PREPARE_DATA_LIB)
+
+
+#-------------------------------------------------------------------------------
+# chuck
+#
+
+CHECK_RESULT_SRC = \
+	check_test_result
+
+CHECK_RESULT_OBJ = \
+	$(addsuffix .$(OBJX),$(CHECK_RESULT_SRC))
+
+CHECK_RESULT_LIB =   \
+	-sncbi-vdb
+
+$(TEST_BINDIR)/check_test_result: $(CHECK_RESULT_OBJ)
+	$(LP) --exe -o $@ $^ $(CHECK_RESULT_LIB)
 
-.PHONY: $(TEST_TOOLS)
 
-clean: stdclean
diff --git a/test/general-loader/VDB-3250/check_test_result.cpp b/test/general-loader/VDB-3250/check_test_result.cpp
new file mode 100644
index 0000000..33e16f9
--- /dev/null
+++ b/test/general-loader/VDB-3250/check_test_result.cpp
@@ -0,0 +1,385 @@
+#include <iostream>
+#include <stdexcept>
+
+#include <kfs/mmap.h>
+#include <kfs/directory.h>
+#include <kfs/file.h>
+
+#include <vdb/manager.h>
+#include <vdb/schema.h>
+#include <vdb/table.h>
+#include <vdb/database.h>
+#include <vdb/cursor.h>
+
+#include <string.h>
+#include <stdlib.h>
+
+using namespace std;
+
+/************************************************
+ * Syntax: program -d data -s schema -o outfile *
+ ************************************************/
+string _PR = "check_test_result";
+string _DF = "test_data.bin";
+string _SF = "test_data.vschema";
+string _TF = "test";
+
+#define _DF_T    "-d"
+#define _DF_TH   "data_file"
+
+#define _SF_T    "-s"
+#define _SF_TH   "schema_file"
+
+#define _TF_T    "-T"
+#define _TF_TH   "target"
+
+void
+usage ()
+{
+    cerr << endl;
+    cerr << "USAGE:";
+    cerr << " " << _PR;
+    cerr << " [ " << _DF_T << " " << _DF_TH << " ]";
+    cerr << " [ " << _SF_T << " " << _SF_TH << " ]";
+    cerr << " [ " << _TF_T << " " << _TF_TH << " ]";
+    cerr << endl;
+    cerr << endl;
+}   /* usage () */
+
+bool
+parse_args ( int argc, char ** argv )
+{
+    if ( argc < 1 ) {
+        cerr << "ERROR: invalid usage of parse_args ()" << endl;
+        exit ( 1 );
+    }
+
+    char * Ch = strrchr ( * argv, '/' );
+    _PR = ( Ch == NULL ) ? ( * argv ) : ( Ch + 1 );
+
+    for ( int llp = 1; llp < argc; llp ++ ) {
+        if ( strcmp ( argv [ llp ], _DF_T ) == 0 ) {
+            if ( argc <= llp + 1 ) {
+                cerr << "ERROR: '" << _DF_T << "' requests parameter" << endl;
+                return false;
+            }
+            llp ++;
+            _DF = argv [ llp ];
+
+            continue;
+        }
+
+        if ( strcmp ( argv [ llp ], _SF_T ) == 0 ) {
+            if ( argc <= llp + 1 ) {
+                cerr << "ERROR: '" << _SF_T << "' requests parameter" << endl;
+                return false;
+            }
+            llp ++;
+            _SF = argv [ llp ];
+
+            continue;
+        }
+
+        if ( strcmp ( argv [ llp ], _TF_T ) == 0 ) {
+            if ( argc <= llp + 1 ) {
+                cerr << "ERROR: '" << _TF_T << "' requests parameter" << endl;
+                return false;
+            }
+            llp ++;
+            _TF = argv [ llp ];
+
+            continue;
+        }
+
+        cerr << "ERROR: invalid parameter '" << argv [ llp ] << "'" << endl;
+        return false;
+    }
+
+    cerr << "  DATA: " << _DF << endl;;
+    cerr << "SCHEMA: " << _SF << endl;;
+    cerr << "TARGET: " << _TF << endl;;
+
+    return true;
+}   /* parse_args () */
+
+int bobrabotka ();
+
+int
+main ( int argc, char ** argv )
+{
+    if ( ! parse_args ( argc, argv ) ) {
+        usage ();
+        return 1;
+    }
+
+    int rc = bobrabotka ();
+
+    if ( rc == 0 ) {
+        cout << "DONE (^_^)" << endl;
+    }
+    else {
+        cerr << "FAILED (o_O)" << endl;
+    }
+
+    return rc;
+}   /* main () */
+
+class LoA { /* LoA - LOaded uint64_t Array */
+public:
+    LoA ( const string & File );
+    ~LoA ();
+
+    inline const uint64_t * Data () const { return _data; };
+    inline size_t Qty () const { return _qty; };
+
+private:
+    KMMap * _map;
+
+    string _path;
+    uint64_t * _data;
+    size_t _qty;
+};
+
+LoA :: LoA ( const string & Nm )
+:   _map ( NULL )
+,   _path ( Nm )
+,   _data ( NULL )
+,   _qty ( 0 )
+{
+    cout << "#=======================" << endl;
+    cout << "Reading uint64_t array from " << _path << endl;
+
+    struct KDirectory * Nat = NULL;
+    if ( KDirectoryNativeDir ( & Nat ) != 0 ) {
+        throw runtime_error ( "Can not get NativeDir!" );
+    }
+
+    const struct KFile * File = NULL;
+    if ( KDirectoryOpenFileRead ( Nat, & File, Nm . c_str () ) != 0 ) {
+        throw runtime_error ( string ( "Can not open File [" ) + Nm + "]!" );
+    }
+
+    if ( KMMapMakeRead ( ( const KMMap ** ) & _map, File ) != 0 ) {
+        throw runtime_error ( string ( "Can not mmap File [" ) + Nm + "]!" );
+    }
+
+    const void * Addr = NULL;
+    if ( KMMapAddrRead ( _map, & Addr ) != 0 ) {
+        throw runtime_error ( string ( "Can not mmap -> addr File [" ) + Nm + "]!" );
+    }
+
+    size_t Size = 0;
+    if ( KMMapSize ( _map, & Size ) != 0 ) {
+        throw runtime_error ( string ( "Can not mmap -> size File [" ) + Nm + "]!" );
+    }
+
+    if ( Size % sizeof ( uint64_t ) != 0 ) {
+        throw runtime_error ( string ( "Invalid file size [" ) + Nm + "]!" );
+    }
+
+    _data = ( uint64_t * ) Addr;
+    _qty = Size / sizeof ( uint64_t );
+
+    KFileRelease ( File );
+    KDirectoryRelease ( Nat );
+
+    cout << "Read " << _qty << " uint64_t integers" << endl;
+    cout << "#=======================" << endl;
+}   /* LoA :: LoA () */
+
+LoA :: ~LoA ()
+{
+    if ( _map != NULL ) {
+        KMMapRelease ( _map );
+        _map = NULL;
+    }
+    _path . clear ();
+    _data = NULL;
+    _qty = 0;
+}   /* LoA :: ~LoA () */
+
+class DbR {
+public :
+    DbR ();
+    ~DbR ();
+
+    inline const uint64_t * Data () const { return _data; };
+    inline size_t Qty () const { return _qty; };
+
+private :
+    void open_db ();
+    void read_data ();
+
+    const struct VDBManager * _man;
+    struct VSchema * _schema;
+    const struct VDatabase * _database;
+    const struct VTable * _table;
+    const struct VCursor * _cursor;
+
+    uint64_t * _data;
+    size_t _qty;
+};
+
+DbR :: DbR ()
+:   _man ( NULL )
+,   _schema ( NULL )
+,   _database ( NULL )
+,   _table ( NULL )
+,   _cursor ( NULL )
+,   _data ( NULL )
+,   _qty ( 0 )
+{
+    cout << "#=======================" << endl;
+    cout << "Reading uint64_t array from database " << _TF << endl;
+    open_db ();
+    read_data ();
+    cout << "Read " << _qty << " uint64_t integers" << endl;
+    cout << "#=======================" << endl;
+}   /* DbR :: DbR () */
+
+DbR :: ~DbR ()
+{
+    if ( _data != NULL ) {
+        delete [] _data;
+        _data = NULL;
+    }
+    _qty = 0;
+
+    if ( _cursor != NULL ) {
+        VCursorRelease ( _cursor );
+        _cursor = NULL;
+    }
+    if ( _table != NULL ) {
+        VTableRelease ( _table );
+        _table = NULL;
+    }
+    if ( _database != NULL ) {
+        VDatabaseRelease ( _database );
+        _database = NULL;
+    }
+    if ( _schema != NULL ) {
+        VSchemaRelease ( _schema );
+        _schema = NULL;
+    }
+    if ( _man != NULL ) {
+        VDBManagerRelease ( _man );
+        _man = NULL;
+    }
+}   /* DbR :: ~DbR () */
+
+void
+DbR :: open_db ()
+{
+    struct KDirectory * Nat;
+    if ( KDirectoryNativeDir ( & Nat ) != 0 ) {
+        throw runtime_error ( "Can not get NativeDir!" );
+    }
+
+    if ( VDBManagerMakeRead ( & _man,  Nat ) != 0 ) {
+        throw runtime_error ( "Can not create VDB manager!" );
+    }
+
+    KDirectoryRelease ( Nat );
+
+    if ( VDBManagerMakeSchema ( _man, & _schema ) != 0 ) {
+        throw runtime_error ( "Can not create V-Schema!" );
+    }
+
+    if ( VSchemaParseFile ( _schema, _SF . c_str () ) != 0 ) {
+        throw runtime_error ( "Can not parse V-Schema!" );
+    }
+
+    if ( VDBManagerOpenDBRead ( _man, & _database, _schema, _TF . c_str () ) ) {
+        throw runtime_error ( "Can not open V-Database!" );
+    }
+
+    if ( VDatabaseOpenTableRead ( _database, & _table, "SEQUENCE" ) != 0 ) {
+        throw runtime_error ( "Can not open V-Table!" );
+    }
+
+    if ( VTableCreateCursorRead ( _table, & _cursor ) != 0 ) {
+        throw runtime_error ( "Can not create V-Cursor!" );
+    }
+}   /* DbR :: open_db () */
+
+void
+DbR :: read_data ()
+{
+    uint32_t ColumnId = 0;
+    if ( VCursorAddColumn ( _cursor, & ColumnId, "SIGNAL" ) != 0 ) { 
+        throw runtime_error ( "Can not add column to V-Cursor!" );
+    }
+
+    if ( VCursorOpen ( _cursor ) != 0 ) {
+        throw runtime_error ( "Can not open V-Cursor!" );
+    }
+
+    uint32_t EBits = 0;
+    uint32_t RLen = 0;
+
+    const void * Base = NULL;
+
+    if ( VCursorCellDataDirect (
+                            _cursor,
+                            1,
+                            ColumnId,
+                            & EBits,
+                            & Base,
+                            NULL,
+                            & RLen
+                            ) != 0 ) {
+        throw runtime_error ( "Can not read V-Cursor!" );
+    }
+
+    if ( EBits != ( sizeof ( uint64_t ) * 8 ) ) {
+        throw runtime_error ( "Invalid size of readed elements" );
+    }
+
+    cerr << "read [" << RLen << "] elems of size [" << EBits << "]" << endl;
+
+    _data = new uint64_t [ RLen ];
+    memmove ( _data, Base, sizeof ( uint64_t ) * RLen );
+    _qty = RLen;
+
+    VCursorRelease ( _cursor );
+    _cursor = NULL;
+
+}   /* DbR :: read_data () */
+
+int
+bobrabotka ()
+{
+    try {
+            /*  First we do need something extra cool
+             */
+        LoA Loa ( _DF );
+
+        DbR Dbr;
+
+        cout << "#=======================" << endl;
+        cout << "Comareing reuslts" << endl;
+
+        if ( Loa . Qty () != Dbr . Qty () ) {
+            throw runtime_error ( "Different size of readed arrays" );
+        }
+
+        for ( size_t llp = 0; llp < Loa . Qty (); llp ++ ) {
+            if ( Loa . Data () [ llp ] != Dbr . Data () [ llp ] ) {
+                throw runtime_error ( "Data is dirrer" );
+            }
+        }
+
+        cout << "Comarision was adequate #lol#" << endl;
+        cout << "#=======================" << endl;
+    }
+    catch ( exception & E ) {
+        cerr << "Exception handled : " << E . what () << endl;
+        return 1;
+    }
+    catch ( ... ) {
+        cerr << "Unknown exception handled" << endl;
+        return 1;
+    }
+
+    return 0;
+}
diff --git a/test/general-loader/VDB-3250/prepare_test_data.cpp b/test/general-loader/VDB-3250/prepare_test_data.cpp
new file mode 100644
index 0000000..4e0906d
--- /dev/null
+++ b/test/general-loader/VDB-3250/prepare_test_data.cpp
@@ -0,0 +1,257 @@
+#include <iostream>
+#include <stdexcept>
+
+#include <kfs/mmap.h>
+#include <kfs/directory.h>
+#include <kfs/file.h>
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "../../../tools/general-loader/general-writer.hpp"
+
+using namespace std;
+using namespace ncbi;
+
+/************************************************
+ * Syntax: program -d data -s schema -o outfile *
+ ************************************************/
+string _PR = "prepare_test_data";
+string _DF = "test_data.bin";
+string _SF = "test_data.vschema";
+string _OF = "test_data.gw";
+
+#define _DF_T    "-d"
+#define _DF_TH   "data_file"
+
+#define _SF_T    "-s"
+#define _SF_TH   "schema_file"
+
+#define _OF_T    "-o"
+#define _OF_TH   "output_file"
+
+void
+usage ()
+{
+    cerr << endl;
+    cerr << "USAGE:";
+    cerr << " " << _PR;
+    cerr << " [ " << _DF_T << " " << _DF_TH << " ]";
+    cerr << " [ " << _SF_T << " " << _SF_TH << " ]";
+    cerr << " [ " << _OF_T << " " << _OF_TH << " ]";
+    cerr << endl;
+    cerr << endl;
+}   /* usage () */
+
+bool
+parse_args ( int argc, char ** argv )
+{
+    if ( argc < 1 ) {
+        cerr << "ERROR: invalid usage of parse_args ()" << endl;
+        exit ( 1 );
+    }
+
+    char * Ch = strrchr ( * argv, '/' );
+    _PR = ( Ch == NULL ) ? ( * argv ) : ( Ch + 1 );
+
+    for ( int llp = 1; llp < argc; llp ++ ) {
+        if ( strcmp ( argv [ llp ], _DF_T ) == 0 ) {
+            if ( argc <= llp + 1 ) {
+                cerr << "ERROR: '" << _DF_T << "' requests parameter" << endl;
+                return false;
+            }
+            llp ++;
+            _DF = argv [ llp ];
+
+            continue;
+        }
+
+        if ( strcmp ( argv [ llp ], _SF_T ) == 0 ) {
+            if ( argc <= llp + 1 ) {
+                cerr << "ERROR: '" << _SF_T << "' requests parameter" << endl;
+                return false;
+            }
+            llp ++;
+            _SF = argv [ llp ];
+
+            continue;
+        }
+
+        if ( strcmp ( argv [ llp ], _OF_T ) == 0 ) {
+            if ( argc <= llp + 1 ) {
+                cerr << "ERROR: '" << _OF_T << "' requests parameter" << endl;
+                return false;
+            }
+            llp ++;
+            _OF = argv [ llp ];
+
+            continue;
+        }
+
+        cerr << "ERROR: invalid parameter '" << argv [ llp ] << "'" << endl;
+        return false;
+    }
+
+    cerr << "  DATA: " << _DF << endl;;
+    cerr << "SCHEMA: " << _SF << endl;;
+    cerr << "   OUT: " << _OF << endl;;
+
+    return true;
+}   /* parse_args () */
+
+int bobrabotka ();
+
+int
+main ( int argc, char ** argv )
+{
+    if ( ! parse_args ( argc, argv ) ) {
+        usage ();
+        return 1;
+    }
+
+    int rc = bobrabotka ();
+
+    if ( rc == 0 ) {
+        cout << "DONE (^_^)" << endl;
+    }
+    else {
+        cerr << "FAILED (o_O)" << endl;
+    }
+
+    return rc;
+}   /* main () */
+
+class LoA { /* LoA - LOaded uint64_t Array */
+public:
+    LoA ( const string & File );
+    ~LoA ();
+
+    inline const uint64_t * Data () const { return _data; };
+    inline size_t Qty () const { return _qty; };
+
+private:
+    KMMap * _map;
+
+    string _path;
+    uint64_t * _data;
+    size_t _qty;
+};
+
+LoA :: LoA ( const string & Nm )
+:   _map ( NULL )
+,   _path ( Nm )
+,   _data ( NULL )
+,   _qty ( 0 )
+{
+    cout << "#=======================" << endl;
+    cout << "Reading uint64_t array from " << _path << endl;
+
+    struct KDirectory * Nat = NULL;
+    if ( KDirectoryNativeDir ( & Nat ) != 0 ) {
+        throw runtime_error ( "Can not get NativeDir!" );
+    }
+
+    const struct KFile * File = NULL;
+    if ( KDirectoryOpenFileRead ( Nat, & File, Nm . c_str () ) != 0 ) {
+        throw runtime_error ( string ( "Can not open File [" ) + Nm + "]!" );
+    }
+
+    if ( KMMapMakeRead ( ( const KMMap ** ) & _map, File ) != 0 ) {
+        throw runtime_error ( string ( "Can not mmap File [" ) + Nm + "]!" );
+    }
+
+    const void * Addr = NULL;
+    if ( KMMapAddrRead ( _map, & Addr ) != 0 ) {
+        throw runtime_error ( string ( "Can not mmap -> addr File [" ) + Nm + "]!" );
+    }
+
+    size_t Size = 0;
+    if ( KMMapSize ( _map, & Size ) != 0 ) {
+        throw runtime_error ( string ( "Can not mmap -> size File [" ) + Nm + "]!" );
+    }
+
+    if ( Size % sizeof ( uint64_t ) != 0 ) {
+        throw runtime_error ( string ( "Invalid file size [" ) + Nm + "]!" );
+    }
+
+    _data = ( uint64_t * ) Addr;
+    _qty = Size / sizeof ( uint64_t );
+
+    KFileRelease ( File );
+    KDirectoryRelease ( Nat );
+
+    cout << "Read " << _qty << " uint64_t integers" << endl;
+    cout << "#=======================" << endl;
+}   /* LoA :: LoA () */
+
+LoA :: ~LoA ()
+{
+    if ( _map != NULL ) {
+        KMMapRelease ( _map );
+        _map = NULL;
+    }
+    _path . clear ();
+    _data = NULL;
+    _qty = 0;
+}   /* LoA :: ~LoA () */
+
+void
+write_data ( const LoA & Loa )
+{
+    cout << "#=======================" << endl;
+    cout << "Writing to file " << _OF << endl;
+
+    GeneralWriter GW ( _OF );
+
+        /*  Some formalities
+         */
+    GW . setSoftwareName ( "general-loader-test", "01.01.01" );
+    GW . setRemotePath ( "TEST" );
+    GW . useSchema ( _SF, "NCBI:sra:db:trace #1" );
+
+    size_t EBits = sizeof ( uint64_t ) * 8;
+
+        /*  Adding table and column
+         */
+    int TableId = GW . addTable ( "SEQUENCE" );
+    int ColumnId = GW . addIntegerColumn ( TableId, "SIGNAL", EBits );
+
+        /*  Opening writer and setting defaults
+         */
+    GW . open ();
+    GW . columnDefault ( ColumnId, EBits, "", 0 );
+
+        /*  Writing and flusing buffers
+         */
+    GW . write ( ColumnId, EBits, Loa . Data (), Loa . Qty () );
+    GW . nextRow ( TableId );
+
+        /*  Here writer should die by itself and close all streams :LOL:
+         */
+    cout << "Wrote " << Loa . Qty () << " 64-bit integers ( " << ( Loa . Qty () * sizeof ( uint64_t ) ) << " bytes ) to file " << _OF << endl;
+    cout << "#=======================" << endl;
+}   /* write_data () */
+
+int
+bobrabotka ()
+{
+    try {
+            /*  First we do need something extra cool
+             */
+        LoA Loa ( _DF );
+
+            /*  Second we do prepare writer
+             */
+        write_data ( Loa );
+    }
+    catch ( exception & E ) {
+        cerr << "Exception handled : " << E . what () << endl;
+        return 1;
+    }
+    catch ( ... ) {
+        cerr << "Unknown exception handled" << endl;
+        return 1;
+    }
+
+    return 0;
+}
diff --git a/test/general-loader/VDB-3250/prepare_test_data.sh b/test/general-loader/VDB-3250/prepare_test_data.sh
new file mode 100755
index 0000000..254a04c
--- /dev/null
+++ b/test/general-loader/VDB-3250/prepare_test_data.sh
@@ -0,0 +1,190 @@
+#!/bin/bash
+
+########################################################
+## That script will run tests for error VDB-3250
+#  which related to uint16_t and size of reading data 
+## bu GeneralLoader
+########################################################
+
+####
+### Usefuls
+#
+
+_S_NM=`basename $0`
+
+_msg ()
+{
+    echo "[$_S_NM]: $@"
+}
+
+_err ()
+{
+    echo "[$_S_NM] ERROR: $@"
+}
+
+_err_exit ()
+{
+    echo "[$_S_NM] ERROR: $@" >&2
+    exit 1
+}
+
+_exec ()
+{
+    CMD="$@"
+    echo "## $CMD"
+    eval $CMD
+    if [ $? -ne 0 ]
+    then
+        _err_exit FAILED: $CMD
+    fi
+}
+
+_exec_plain ()
+{
+    CMD="$@"
+    echo "## $CMD"
+    eval $CMD
+    if [ $? -ne 0 ]
+    then
+        _err FAILED: $CMD
+    fi
+}
+
+####
+### Args
+#
+
+syntax ()
+{
+    cat <<EOF >&2
+
+Syntax : $_S_NM top_dir bin_dir
+
+EOF
+}
+
+if [ $# -ne 2 ]
+then
+    echo "[$_S_NM] ERROR: invalid arguments" >&2
+
+    syntax
+
+    exit 1
+fi
+
+T_VAR=$1
+if [ ! -d "$T_VAR" ]
+then
+    _err_exit can not stat directory \'$T_VAR\'
+fi
+
+test_check_dir ()
+{
+    A=$2
+    V=$1
+
+    if [ ! -d "$A" ]
+    then
+        _err_exit directory \'$A\' does not exists
+    fi
+
+    eval $V=$A
+}
+
+test_check_dir TOP_DIR `cd $T_VAR; pwd`
+test_check_dir TEST_DIR $TOP_DIR/test/general-loader
+test_check_dir TEST_DATA_DIR $TEST_DIR/VDB-3250
+
+
+T_VAR=$2
+if [ ! -d "$T_VAR" ]
+then
+    _err_exit can not stat directory \'$T_VAR\'
+fi
+
+test_check_dir TBD `cd $T_VAR/..;pwd`
+test_check_dir BIN_DIR $TBD/bin
+test_check_dir TEST_BIN_DIR $TBD/test-bin
+
+####
+### Checking data to work on
+##
+#
+INPUT_TEST_DATA=$TEST_DATA_DIR/test_data.bin
+if [ ! -f "$INPUT_TEST_DATA" ]
+then
+    _err_exit can not stat file \'$INPUT_TEST_DATA\'
+fi
+
+TEST_SCHEMA=$TEST_DATA_DIR/test_data.vschema
+if [ ! -f "$TEST_SCHEMA" ]
+then
+    _err_exit can not stat file \'$TEST_SCHEMA\'
+fi
+
+OUTPUT_TEST_DATA=$TEST_DATA_DIR/test_data.gw
+if [ -f "$OUTPUT_TEST_DATA" ]
+then
+    _exec rm -f $OUTPUT_TEST_DATA
+fi
+
+TEST_DATABASE=$TEST_DATA_DIR/test
+if [ -d "$TEST_DATABASE" ]
+then
+    _exec rm -rf $TEST_DATABASE
+fi
+
+####
+### Checing if there are necessary binaries: general-writer and
+##  general-loader
+#
+
+test_check_exe ()
+{
+    A=$2
+    V=$1
+
+    if [ ! -x "$A" ]
+    then
+        _err_exit executable \'$A\' does not exists
+    fi
+
+    eval $V=$A
+}
+
+test_check_exe LOADER_EXE $BIN_DIR/general-loader
+
+####
+### Making test binaries
+##
+#
+cd $TEST_DATA_DIR
+
+_exec make
+
+test_check_exe PREPARER_EXE $TEST_BIN_DIR/prepare_test_data
+test_check_exe CHECKER_EXE $TEST_BIN_DIR/check_test_result
+
+####
+### Here test starts
+##
+#
+_exec $PREPARER_EXE -d $INPUT_TEST_DATA -s $TEST_SCHEMA -o $OUTPUT_TEST_DATA
+_exec "export VDB_CONFIG=.. ; $LOADER_EXE <$OUTPUT_TEST_DATA -T $TEST_DATABASE"
+_exec $CHECKER_EXE -d  $INPUT_TEST_DATA -s $TEST_SCHEMA -T $TEST_DATABASE
+
+####
+### Clearing unnecessary data
+##
+#
+if [ -f "$OUTPUT_TEST_DATA" ]
+then
+    _exec_plain rm -f $OUTPUT_TEST_DATA
+fi
+
+if [ -d "$TEST_DATABASE" ]
+then
+    _exec_plain rm -rf $TEST_DATABASE
+fi
+
+echo TEST PASSED
diff --git a/test/general-loader/VDB-3250/test_data.bin b/test/general-loader/VDB-3250/test_data.bin
new file mode 100644
index 0000000..9a96182
Binary files /dev/null and b/test/general-loader/VDB-3250/test_data.bin differ
diff --git a/test/general-loader/VDB-3250/test_data.vschema b/test/general-loader/VDB-3250/test_data.vschema
new file mode 100644
index 0000000..233287a
--- /dev/null
+++ b/test/general-loader/VDB-3250/test_data.vschema
@@ -0,0 +1,65 @@
+/*===========================================================================
+*
+*                            PUBLIC DOMAIN NOTICE
+*               National Center for Biotechnology Information
+*
+*  This software/database is a "United States Government Work" under the
+*  terms of the United States Copyright Act.  It was written as part of
+*  the author's official duties as a United States Government employee and
+*  thus cannot be copyrighted.  This software/database is freely available
+*  to the public for use. The National Library of Medicine and the U.S.
+*  Government have not placed any restriction on its use or reproduction.
+*
+*  Although all reasonable efforts have been taken to ensure the accuracy
+*  and reliability of the software and data, the NLM and the U.S.
+*  Government do not and cannot warrant the performance or results that
+*  may be obtained by using this software or data. The NLM and the U.S.
+*  Government disclaim all warranties, express or implied, including
+*  warranties of performance, merchantability or fitness for any particular
+*  purpose.
+*
+*  Please cite the author in any work or product based on this material.
+*
+* ===========================================================================
+*
+*/
+
+version 1;
+
+include 'vdb/vdb.vschema';
+include 'ncbi/sra.vschema';
+include 'ncbi/seq.vschema';
+include 'ncbi/stats.vschema';
+include 'insdc/insdc.vschema';
+include 'insdc/sra.vschema';
+include 'ncbi/clip.vschema';
+include 'sra/454.vschema';
+
+extern function NCBI:SRA:spot_name_token
+    NCBI:SRA:_454_:tokenize_spot_name #1 ( ascii name );
+
+
+table NCBI:sra:tbl:trace #1                     // declare the table
+    = NCBI:SRA:tbl:sra_nopos #2.1.3             // inherit interface AND implementation for (original) SRA model
+    , NCBI:tbl:base_space #2.0.3                // columns for storing and compressing READ as dna
+    , NCBI:SRA:tbl:stats #1.2.0                 // accumulate statistics upon writing
+{
+    /* PLATFORM
+     *  platform name is generically called "capillary"
+     */
+    ascii platform_name
+        = < ascii > echo < "CAPILLARY" > ();
+
+    // *
+    // signal - actual TRACE data
+    column NCBI:isamp4 SIGNAL = out_signal;
+    NCBI:isamp4 out_signal = .SIGNAL;
+    physical column NCBI:isamp4
+        .SIGNAL = SIGNAL;
+}
+
+database NCBI:sra:db:trace #1
+{
+    table NCBI:sra:tbl:trace #1 SEQUENCE;
+}
+
diff --git a/test/sra-pileup/Makefile b/test/sra-pileup/Makefile
index 4ad3ec3..f5ffc27 100644
--- a/test/sra-pileup/Makefile
+++ b/test/sra-pileup/Makefile
@@ -37,6 +37,8 @@ $(TEST_TOOLS): makedirs
 
 runtests: check_exit_code
 
+slowtests: fastq_dump_vs_sam_dump sam_dump_spotgroup_for_all
+
 #-------------------------------------------------------------------------------
 # scripted tests
 #
@@ -44,6 +46,22 @@ runtests: check_exit_code
 check_exit_code:
 	@ python $(TOP)/build/check-exit-code.py $(BINDIR)/sra-pileup
 
+
+ACC = SRR3332402
+
+#-------------------------------------------------------------------------------
+# testing if sam-dump and fastq-dump produce the same READ/QUALITY values
+#
+fastq_dump_vs_sam_dump :
+	@ python test_diff_fastq_dump_vs_sam_dump.py -a $(ACC) -f $(BINDIR)/fastq-dump -m $(BINDIR)/sam-dump
+
+#-------------------------------------------------------------------------------
+# testing if sam-dump and fastq-dump produce the same READ/QUALITY values
+#
+sam_dump_spotgroup_for_all :
+	@ python test_all_sam_dump_has_spotgroup.py -a $(ACC) -m $(BINDIR)/sam-dump
+
+    
 .PHONY: $(TEST_TOOLS)
 
 clean: stdclean
diff --git a/test/sra-pileup/test_all_sam_dump_has_spotgroup.py b/test/sra-pileup/test_all_sam_dump_has_spotgroup.py
new file mode 100755
index 0000000..a87528c
--- /dev/null
+++ b/test/sra-pileup/test_all_sam_dump_has_spotgroup.py
@@ -0,0 +1,92 @@
+#!/usr/bin/env python
+
+import sys, getopt, subprocess, multiprocessing
+
+
+def run( cmd, lines, q_out ) :
+    p = subprocess.Popen( cmd, stdout = subprocess.PIPE )
+    n = 0
+    bases = None
+    while True :
+        line = p.stdout.readline()
+        if line != '' :
+            n += 1
+            if not line.startswith( '@' ) :
+                q_out.put( line )
+            if lines != None :
+                if n > lines :
+                    p.kill()
+                    break
+        else :
+            break
+    q_out.put( None )
+
+
+def sam_dump_full( sam_dump, acc, spots, q_out ) :
+    run( [ sam_dump, '-u', '-g', acc ], spots, q_out )
+    print "sam-dump done"
+
+
+def count_lines( q_in, q_out ) :
+    total = 0
+    with_spotgrp = 0
+    while True :
+        line = q_in.get()
+        if line != None :
+            total += 1
+            sam = line.split( '\t' )
+            qname = sam[ 0 ]
+            name_parts = qname.split( '.' )
+            if len( name_parts ) > 1 :
+                with_spotgrp += 1
+        else :
+            break
+    res = ( total, with_spotgrp )
+    q_out.put( res )
+
+
+if __name__ == '__main__':
+    acc = 'SRR3332402'
+    spots = None
+    sam_dump = 'sam-dump'
+    
+    short_opts = "ha:s:m:"
+    long_opts = [ "acc=", "spots=", "sam_dump=" ]
+    try :
+        opts, args = getopt.getopt( sys.argv[ 1: ], short_opts, long_opts )
+    except getopt.GetoptError :
+        print sys.argv[ 0 ], ' -a <accession> -s <spots> -m <sam-dump-binary>'
+        sys.exit( 2 )
+    for opt, arg in opts :
+        if opt == '-h' :
+            print sys.argv[ 0 ], ' -a <accession> -s <spots> -m <sam-dump-binary>'
+            sys.exit()
+        elif opt in ( "-a", "--acc" ) :
+            acc = arg
+        elif opt in ( "-s", "--spots" ) :
+            spots = int( arg )
+        elif opt in ( "-m", "--sam_dump" ) :
+            sam_dump = arg
+
+    print 'accession = ', acc
+    if spots != None :
+        print 'spots = ', spots
+   
+    q1 = multiprocessing.Queue()
+    q2 = multiprocessing.Queue()
+    
+    p1 = multiprocessing.Process( target = sam_dump_full, args = ( sam_dump, acc, spots, q1 ), )
+    p2 = multiprocessing.Process( target = count_lines, args = ( q1, q2 ), )
+    
+    p1.start()
+    p2.start()
+    
+    p1.join()
+    p2.join()
+    
+    res = q2.get()
+    print "total        : ", res[ 0 ]
+    print "with_spotgrp : ", res[ 1 ]
+    if res[ 0 ] != res[ 1 ] :
+        print "not all sam-lines have a spotgroup in the QNAME-field!"
+        sys.exit( 3 )
diff --git a/test/sra-pileup/test_diff_fastq_dump_vs_sam_dump.py b/test/sra-pileup/test_diff_fastq_dump_vs_sam_dump.py
new file mode 100755
index 0000000..f716f89
--- /dev/null
+++ b/test/sra-pileup/test_diff_fastq_dump_vs_sam_dump.py
@@ -0,0 +1,245 @@
+#!/usr/bin/env python
+
+import sys, getopt, subprocess, multiprocessing
+
+
+def run( cmd, spots, q ) :
+    p = subprocess.Popen( cmd, stdout = subprocess.PIPE )
+    n = 0
+    l = 0
+    lines = None
+    if spots != None :
+        lines = spots * 4
+    bases = None
+    while True :
+        line = p.stdout.readline()
+        if line != '' :
+            if l == 1 :
+                bases = line.strip()
+            elif l == 3 :
+                q.put( ( bases, line.strip() ) )
+            n += 1
+            if lines != None :
+                if n > lines :
+                    p.kill()
+                    break
+            l += 1  
+            if l > 3 :
+                l = 0
+        else :
+            break
+    q.put( None )
+
+
+def fastq_dump_full( fastq_dump, acc, spots, q ) :
+    run( [ fastq_dump, '--split-3', '-Z', acc ], spots, q )
+    print "fastq-dump done"
+
+def sam_dump_full( sam_dump, acc, spots, q ) :
+    run( [ sam_dump, '-u', '--fastq', acc ], spots, q )
+    print "sam-dump done"
+
+def handle_q( d, q ) :
+    res = 0
+    t = q.get()
+    if t != None :
+        res = 1
+        ( bases, quality ) = t
+        try :
+            d[ bases ].append( quality )
+        except :
+            d[ bases ] = [ quality ]
+    return res
+
+
+def compare_lists( l1, l2 ) :
+    cmn = 0
+    rev = 0
+    nom = 0
+    for item in l1 :
+        if item in l2 :
+            cmn += 1
+        elif item[::-1] in l2 :
+            rev += 1
+        else :
+            nom += 1
+    return ( cmn, rev, nom )
+
+
+def reverse_compl( bases ) :
+    res = ""
+    for c in bases[::-1] :
+        if c == 'A' :
+            res += 'T'
+        elif c == 'C' :
+            res += 'G'
+        elif c == 'G' :
+            res += 'C'
+        elif c == 'T' :
+            res += 'A'
+        else :
+            res += c
+    return res
+
+
+class join_stats() :
+    def __init__( self ) :
+        self.n_matches = 0
+        self.nr_matches = 0
+        self.n_reversed = 0
+        self.nr_reversed = 0
+        self.n_no_match = 0
+        self.nr_no_match = 0
+        self.n_not_found = 0
+
+    def add_match_res( self, m, r, n ) :
+        self.n_matches  += m
+        self.n_reversed += r
+        self.n_no_match += n
+
+    def add_rmatch_res( self, m, r, n ) :
+        self.nr_matches  += m
+        self.nr_reversed += r
+        self.nr_no_match += n
+    
+    def __str__( self ) :
+        res  = "matches    : %d\n" % self.n_matches
+        res += "r-matches  : %d\n" % self.nr_matches
+        res += "reversed   : %d\n" % self.n_reversed
+        res += "r-reversed : %d\n" % self.nr_reversed
+        res += "no_match   : %d\n" % self.n_no_match
+        res += "r-no_match : %d\n" % self.nr_no_match
+        res += "not_found  : %d" % self.n_not_found
+        return res
+
+    def non_matches( self ) :
+        res = self.nr_matches
+        res += self.n_reversed
+        res += self.nr_reversed
+        res += self.n_no_match
+        res += self.nr_no_match
+        res += self.n_not_found
+        return res
+
+def extract_matches( d1, d2 ) :
+    res = 0
+    l = []
+    for bases in d1 :
+        if bases in d2 :
+            l.append( bases )
+    for bases in l :
+        l1 = d1[ bases ]
+        l2 = d2[ bases ]
+        if len( l1 ) == 1 and len( l2 ) == 1 :
+            if l1[ 0 ] == l2[ 0 ] :
+                res += 1
+                del d1[ bases ]
+                del d2[ bases ]
+    return res
+
+
+def join_2( q1, q2, q3 ) :
+    #the key is the bases
+    #the value is a ist of qualities
+    d1 = {}
+    d2 = {}
+    
+    n1 = 0
+    n2 = 0
+    r1 = 1
+    r2 = 1
+    loop = 0
+    
+    js = join_stats()
+    
+    while ( r1 + r2 ) > 0 :
+        loop += 1
+        if loop % 10000 == 0 :
+            js.n_matches += extract_matches( d1, d2 )
+            #sys.stdout.write( '.' )
+            #sys.stdout.flush()
+            
+        if r1 > 0 :
+            r1 = handle_q( d1, q1 )
+            n1 += r1
+        if r2 > 0:
+            r2 = handle_q( d2, q2 )
+            n2 += r2
+            
+    print "from fastq-dump : %d" % n1
+    print "from sam-dump   : %d" % n2
+    
+    for bases in d1 :
+        ql_1 = d1[ bases ]
+        ql_2 = d2.get( bases, None )
+        if ql_2 != None :
+            ( m, r, n ) = compare_lists( ql_1, ql_2 )
+            if n > 0 :
+                ql_2 = d2.get( reverse_compl( bases ), None )
+                if ql_2 != None :
+                    ( m1, r1, n1 ) = compare_lists( ql_1, ql_2 )
+                    js.add_rmatch_res( m1, r1, n1 )
+            else :
+                js.add_match_res( m, r, n )
+        else :
+            ql_2 = d2.get( reverse_compl( bases ), None )
+            if ql_2 != None :
+                ( m2, r2, n2 ) = compare_lists( ql_1, ql_2 )
+                js.add_rmatch_res( m2, r2, n2 )
+            else :
+                js.n_not_found += 1
+    
+    print js
+    q3.put( js.non_matches() )
+
+    
+if __name__ == '__main__':
+    acc = 'SRR3332402'
+    spots = None
+    fastq_dump = 'fastq-dump'
+    sam_dump = 'sam-dump'
+    
+    short_opts = "ha:s:f:m:"
+    long_opts = [ "acc=", "spots=", "fastq_dump=", "sam_dump=" ]
+    try :
+        opts, args = getopt.getopt( sys.argv[ 1: ], short_opts, long_opts )
+    except getopt.GetoptError :
+        print sys.argv[ 0 ], ' -a <accession> -s <spots> -f <fastq-dump-binary> -m <sam-dump-binary>'
+        sys.exit( 2 )
+    for opt, arg in opts :
+        if opt == '-h' :
+            print sys.argv[ 0 ], ' -a <accession> -s <spots> -f <fastq-dump-binary> -m <sam-dump-binary>'
+            sys.exit()
+        elif opt in ( "-a", "--acc" ) :
+            acc = arg
+        elif opt in ( "-s", "--spots" ) :
+            spots = int( arg )
+        elif opt in ( "-f", "--fastq_dump" ) :
+            fastq_dump = arg
+        elif opt in ( "-m", "--sam_dump" ) :
+            sam_dump = arg
+
+    print 'accession = ', acc
+    if spots != None :
+        print 'spots = ', spots
+   
+    q1 = multiprocessing.Queue()
+    q2 = multiprocessing.Queue()
+    q3 = multiprocessing.Queue()
+    
+    p1 = multiprocessing.Process( target = fastq_dump_full, args = ( fastq_dump, acc, spots, q1 ), )
+    p2 = multiprocessing.Process( target = sam_dump_full, args = ( sam_dump, acc, spots, q2 ), )
+    p3 = multiprocessing.Process( target = join_2, args = ( q1, q2, q3 ), )
+    
+    p1.start()
+    p2.start()
+    p3.start()
+    
+    p1.join()
+    p2.join()
+    p3.join()
+    
+    nm = q3.get()
+    print "non-matches : ", nm
+    if nm > 0 :
+        sys.exit( 3 )
diff --git a/build/Makefile.vers b/test/vdb-config/Makefile
similarity index 83%
copy from build/Makefile.vers
copy to test/vdb-config/Makefile
index 453b9a2..7813982 100644
--- a/build/Makefile.vers
+++ b/test/vdb-config/Makefile
@@ -22,5 +22,14 @@
 #
 # ===========================================================================
 
-# SRA-TOOLS and library version
-VERSION = 2.8.1
+default: runtests
+
+TOP ?= $(abspath ../..)
+include $(TOP)/build/Makefile.env # BINDIR
+
+runtests: test-vdb-config
+
+test-vdb-config:
+	@ printf "Testing exit code vdb-config of vdb-config... "
+	@ PATH=$(BINDIR):$(PATH) ; ./test-vdb-config.pl
+	@ echo OK
diff --git a/test/vdb-config/test-vdb-config.pl b/test/vdb-config/test-vdb-config.pl
new file mode 100755
index 0000000..542a5b0
--- /dev/null
+++ b/test/vdb-config/test-vdb-config.pl
@@ -0,0 +1,12 @@
+#!/usr/bin/perl -w
+
+use strict;
+
+use File::Temp   "tempdir";
+
+my $tmp = tempdir ( "phgvXXXX", CLEANUP => 1 );
+$ENV{VDB_CONFIG}=$tmp;
+$ENV{NCBI_SETTINGS}="$tmp/u.mkfg";
+
+`vdb-config -s foo=bar`;
+die "vdb-config exited with " . ( $? >> 8 ) if ( $? );
diff --git a/tools/bam-loader/bam.c b/tools/bam-loader/bam.c
index 559a0ff..e60fe38 100644
--- a/tools/bam-loader/bam.c
+++ b/tools/bam-loader/bam.c
@@ -2987,6 +2987,7 @@ unsigned ReferenceLengthFromCIGAR(const BAM_Alignment *self)
     return y;
 }
 
+#if 0
 static unsigned SequenceLengthFromCIGAR(const BAM_Alignment *self)
 {
     unsigned i;
@@ -3010,6 +3011,7 @@ static unsigned SequenceLengthFromCIGAR(const BAM_Alignment *self)
     }
     return y;
 }
+#endif
 
 rc_t BAM_AlignmentGetPosition2(const BAM_Alignment *cself, int64_t *rhs, uint32_t *length)
 {
diff --git a/tools/bam-loader/loader-imp.c b/tools/bam-loader/loader-imp.c
index 46b46d7..f81ea7c 100644
--- a/tools/bam-loader/loader-imp.c
+++ b/tools/bam-loader/loader-imp.c
@@ -177,6 +177,7 @@ typedef struct context_t {
     bool isColorSpace;
 } context_t;
 
+#if 0
 static char const *Print_ctx_value_t(ctx_value_t const *const self)
 {
     static char buffer[16384];
@@ -186,6 +187,7 @@ static char const *Print_ctx_value_t(ctx_value_t const *const self)
         return 0;
     return buffer;
 }
+#endif
 
 static rc_t MMArrayMake(MMArray **rslt, int fd, uint32_t elemSize)
 {
@@ -252,6 +254,7 @@ static rc_t MMArrayGet(MMArray *const self, void **const value, uint64_t const e
     return 0;
 }
 
+#if 0
 static rc_t MMArrayGetRead(MMArray *const self, void const **const value, uint64_t const element)
 {
     unsigned const bin_no = element >> 32;
@@ -279,6 +282,7 @@ static rc_t MMArrayGetRead(MMArray *const self, void const **const value, uint64
     *value = &next[(size_t)in_bin * self->elemSize];
     return 0;
 }
+#endif
 
 static void MMArrayLock(MMArray *const self)
 {
@@ -879,6 +883,7 @@ static uint8_t GetMapQ(BAM_Alignment const *rec)
     return mapQ;
 }
 
+#if 0
 static bool EditAlignedQualities(uint8_t qual[], bool const hasMismatch[], unsigned readlen)
 {
     unsigned i;
@@ -903,7 +908,9 @@ static bool EditAlignedQualities(uint8_t qual[], bool const hasMismatch[], unsig
     }
     return true;
 }
+#endif
 
+#if 0
 static bool EditUnalignedQualities(uint8_t qual[], bool const hasMismatch[], unsigned readlen)
 {
     unsigned i;
@@ -928,6 +935,7 @@ static bool EditUnalignedQualities(uint8_t qual[], bool const hasMismatch[], uns
     }
     return true;
 }
+#endif
 
 static bool platform_cmp(char const platform[], char const test[])
 {
@@ -1093,6 +1101,7 @@ static rc_t RecordLowMatchCounts(KMDataNode *const node)
     return ctx.rc;
 }
 
+#if 0
 static
 rc_t LogDupConflict(char const readName[])
 {
@@ -1113,6 +1122,7 @@ rc_t LogDupConflict(char const readName[])
                                  "name=%s", readName));
     return rc;
 }
+#endif
 
 static char const *const CHANGED[] = {
     "FLAG changed",
diff --git a/tools/bam-loader/sam.l b/tools/bam-loader/sam.l
new file mode 100644
index 0000000..62683fd
--- /dev/null
+++ b/tools/bam-loader/sam.l
@@ -0,0 +1,172 @@
+/*===========================================================================
+*
+*                            PUBLIC DOMAIN NOTICE
+*               National Center for Biotechnology Information
+*
+*  This software/database is a "United States Government Work" under the
+*  terms of the United States Copyright Act.  It was written as part of
+*  the author's official duties as a United States Government employee and
+*  thus cannot be copyrighted.  This software/database is freely available
+*  to the public for use. The National Library of Medicine and the U.S.
+*  Government have not placed any restriction on its use or reproduction.
+*
+*  Although all reasonable efforts have been taken to ensure the accuracy
+*  and reliability of the software and data, the NLM and the U.S.
+*  Government do not and cannot warrant the performance or results that
+*  may be obtained by using this software or data. The NLM and the U.S.
+*  Government disclaim all warranties, express or implied, including
+*  warranties of performance, merchantability or fitness for any particular
+*  purpose.
+*
+*  Please cite the author in any work or product based on this material.
+*
+* ===========================================================================
+*
+*/
+
+   /*
+      lex file is three sections:
+      definitions: name definition
+      %%
+      rules: pattern action
+      %%
+      user code
+   */
+
+  /*
+    @HD\tVN:1.4\tSO:coordinate
+    @SQ\tSN:1\t...
+    @SQ\tSN:16\t...
+    @RG\tID:PM89\tPL:Illumina\tLB...
+    HWI-...
+  */
+
+%top{
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include "sam.tab.h"
+
+//#define YYSTYPE char
+#define LEXDEBUG 0
+
+    // do { if (LEXDEBUG) fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, __LINE__, __func__, __VA_ARGS__); } while (0)
+#define lex_print(fmt, ...) \
+    do { if (LEXDEBUG) fprintf(stderr, fmt, ##__VA_ARGS__); } while (0)
+
+  }
+
+/* definitions */
+digits [[:digit:]]+
+integer [-+]?[0-9]+
+float  [-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?
+eol    (\r\n|\r|\n)
+controlchar [\x00-\x08\x0b-\x0c\x0e-\x1f]
+
+tag [A-Za-z][A-Za-z0-9]
+ /* validtag VN|SO|GO|SN|LN|AS|M5|SP|UR|ID|CN|DS|DT|FO|KS|LB|PG|PI|PL|PM|PU|SM|ID|PN|CL|PP|DS|VN */
+
+
+attv {tag}:A:[!-~]
+ittv {tag}:i:{integer}
+fttv {tag}:f:{float}
+zttv {tag}:Z:[[:print:]]*
+httv {tag}:H:([0-9A-F][0-9A-F])*
+bttv {tag}:B:[cCsSiIf](,{float})+
+ttv {attv}|{ittv}|{fttv}|{zttv}|{httv}|{bttv}
+
+/* No @ in first, to distinguish from headers */
+qname [!-?A-~][!-~]{0,253}
+
+/* stop after first EOF */
+%option noyywrap
+%option prefix="SAM"
+%option warn
+%option nodefault
+%option nodebug
+/* Not a TTY */
+%option never-interactive
+%option yylineno
+%option nounistd
+/* Allow multitheading */
+/* %option reentrant */
+/* yylex takes yylval */
+/* %option bison-bridge */
+%x INALIGNMENT
+%x AFTERCOLON
+
+%%
+ /* rules */
+ /* TODO: lots of strdups, when do we free()? */
+^@HD   { lex_print( "lex: Header\n"); return HEADER; }
+^@SQ   { lex_print( "lex: SQ\n"); return SEQUENCE; }
+^@RG   { lex_print( "lex: RG\n"); return READGROUP; }
+^@PG   { lex_print( "lex: PG\n"); return PROGRAM; }
+^@CO\t.*{eol} { lex_print( "lex: Comment\n"); return COMMENT; }
+<INITIAL,INALIGNMENT>^{qname} { BEGIN INALIGNMENT; SAMlval.strval=strdup(yytext); lex_print("\nlex: alignment qname, INALIGNMENT\n"); return QNAME; }
+<INITIAL,INALIGNMENT,AFTERCOLON>{controlchar} { lex_print("lex:CONTROLCHAR1\n"); return CONTROLCHAR; }
+<INITIAL,INALIGNMENT>\t { lex_print("lex: tab\n"); return TAB;}
+<AFTERCOLON>\t { BEGIN INITIAL; lex_print("lex: tab INITIAL\n"); return TAB;}
+
+<INITIAL,INALIGNMENT,AFTERCOLON>{eol} { BEGIN INITIAL; lex_print("lex: eol INITIAL\n"); return EOL;}
+ /* <INALIGNMENT>{ttv} { lex_print("lex: ttv\n"); return TTV; } */
+<INALIGNMENT>[ -~]+ { SAMlval.strval=strdup(yytext); lex_print("lex: alignvalue\n"); return ALIGNVALUE; }
+{tag}  { SAMlval.strval=strdup(yytext); lex_print("lex: Valid Tag:%s\n", yytext); return TAG; }
+<INITIAL,INALIGNMENT>: { BEGIN AFTERCOLON; lex_print("lex: colon AFTERCOLON\n"); return COLON;}
+<AFTERCOLON>[ -~]+ { SAMlval.strval=strdup(yytext); lex_print("lex: Value:%s\n", yytext); return VALUE; }
+
+ /* \t[!-~]+ { lex_print("lex: alignment field\n"); return ALIGNMENT; }
+ \t{ttv} { lex_print("lex: optional alignment\n"); return ALIGNMENT; }
+ */
+ /*
+    \t{flag} { lex_print("lex: alignment flag\n"); return ALIGNMENT; }
+    \t{mapq} { lex_print("lex: alignment mapq\n"); return ALIGNMENT; }
+    \t{cigar} { lex_print("lex: alignment cigar\n"); return ALIGNMENT; }
+    \t{rnext} { lex_print("lex: alignment rnext\n"); return ALIGNMENT; }
+    \t{pnext} { lex_print("lex: alignment pnext\n"); return ALIGNMENT; }
+    \t{tlen} { lex_print("lex: alignment tlen\n"); return ALIGNMENT; }
+    \t{seq} { lex_print("lex: alignment seq\n"); return ALIGNMENT; }
+    \t{qual} { lex_print("lex: alignment qual\n"); return ALIGNMENT; }
+    \t{ttv} { lex_print("lex: alignment ttv\n"); return ALIGNMENT; }
+    \t{rname} { lex_print("lex: alignment rname\n"); return ALIGNMENT; }
+    \t{pos} { lex_print("lex: alignment pos\n"); return ALIGNMENT; }
+ */
+
+
+
+    /*
+    ^@VN\t{version}\n printf("lex: Version\n");
+    ^{hdrtag}(\t[[:alpha:]][[:alnum:]]:[[:print:]]+)+\n  printf("lex: Allowed Header %d %s", yyleng, yytext);
+    ^@[[:upper:]]{2}(\t[[:alpha:]][[:alnum:]]:[[:print:]]+)+\n  printf("lex: Header %d %s", yyleng, yytext);
+    ^@[[:upper:]]{2}(\t[[:alpha:]][[:alnum:]]+:[[:print:]]+)+\n  printf("lex: Header long %d %s", yyleng, yytext);
+    ^{qname}\t{flag}\t{rname}\t{pos}\t{mapq}\t{cigar}\t{rnext}\t{pnext}\t{tlen}\t{seq}\t{qual}\n printf("lex: Alignment\n");
+    ^{qname}\t{flag}\t{rname}\t{pos}\t{mapq}\t{cigar}\t{rnext}\t{pnext}\t{tlen}\t{seq}\t{qual}({ttv})+\n {
+        char * s1=strdup(yytext);
+        printf("lex: Alignment with optional: %s\n", s1);
+        char * s2=s1;
+        char * tok;
+        while ((tok=strsep(&s2,"\t")))
+        {
+            printf("  Token:%s\n", tok);
+        }
+
+
+        free(s1);
+    }
+
+
+    ^@[[:lower:]]{2}\t.*\n    printf("Optional, lowercase tag\n");
+    ^@HD.*\n    printf("Empty HD: %s %d", yytext, yyleng);
+    ^[^@].*\n printf("not at:                     %s", yytext);
+ */
+.|\n       lex_print("DEFAULT '%c' ", *yytext);
+
+%%
+ /* user code */
+/*
+int main(int argc, char * argv[])
+{
+    SAMlex();
+//    SAMparse();
+}
+*/
diff --git a/tools/bam-loader/sam.y b/tools/bam-loader/sam.y
new file mode 100644
index 0000000..3e22848
--- /dev/null
+++ b/tools/bam-loader/sam.y
@@ -0,0 +1,396 @@
+/*===========================================================================
+*
+*                            PUBLIC DOMAIN NOTICE
+*               National Center for Biotechnology Information
+*
+*  This software/database is a "United States Government Work" under the
+*  terms of the United States Copyright Act.  It was written as part of
+*  the author's official duties as a United States Government employee and
+*  thus cannot be copyrighted.  This software/database is freely available
+*  to the public for use. The National Library of Medicine and the U.S.
+*  Government have not placed any restriction on its use or reproduction.
+*
+*  Although all reasonable efforts have been taken to ensure the accuracy
+*  and reliability of the software and data, the NLM and the U.S.
+*  Government do not and cannot warrant the performance or results that
+*  may be obtained by using this software or data. The NLM and the U.S.
+*  Government disclaim all warranties, express or implied, including
+*  warranties of performance, merchantability or fitness for any particular
+*  purpose.
+*
+*  Please cite the author in any work or product based on this material.
+*
+* ===========================================================================
+*
+*/
+
+/* %{
+   Prologue
+   %}
+   Declarations
+   %%
+   Grammar rules
+   %%
+   Epilogue
+   */
+
+%{
+    #include <stdio.h>
+    #include <ctype.h>
+    #include <stdlib.h>
+    #include <string.h>
+    #include <sys/types.h>
+    #include <regex.h>
+    #include <stdint.h>
+    #include "sam.tab.h"
+
+    #define YYDEBUG 1
+
+/*    int yylex(void); */
+    int SAMlex(void);
+/*    void yyerror(const char * s) { fprintf(stderr,"%s\n", s); } */
+    void SAMerror(const char * s) { fprintf(stderr,"ERR: %s\n", s); }
+
+    /* Pair of TAG, regexp: "/..." TODO: or integer range "1-12345" */
+    const char * validations[] =
+    {
+        "VN", "/.*", // @PG also has "/[0-9]+\\.[0-9]+",
+        "SO", "/unknown|unsorted|queryname|coordinate",
+        "GO", "/none|query|reference",
+        "SN", "/[!-)+-<>-~][!-~]*",
+        "LN", "/[0]*[1-9][0-9]{0,10}", // TODO: range check 1..2**31-1
+        "AS", "/.*",
+        "M5", "/[0-9A-Z\\*]{32}",
+        "SP", "/.*",
+        "UR", "/.*:/.*",
+        "ID", "/.*",
+        "CN", "/.*",
+        "DS", "/.*",
+        "DT", "/.*",
+        "FO", "/\\*|[ACMGRSVTWYHKDBN]+",
+        "KS", "/.*",
+        "LB", "/.*",
+        "PG", "/.*",
+        "PI", "/.*",
+        "PL", "/.*",
+        "PM", "/.*",
+        "PU", "/.*",
+        "SM", "/.*",
+        "PN", "/.*",
+        "CL", "/.*",
+        "PP", "/.*",
+        "DS", "/.*",
+        "\0", "\0"
+    };
+
+    // Returns 1 if match found
+    int regexcheck(const char *regex, const char * value)
+    {
+        regex_t preg;
+
+//        fprintf(stderr,"Compiling %s\n", regex);
+        int result=regcomp(&preg, regex, REG_EXTENDED);
+        if (result)
+        {
+            size_t s=regerror(result, &preg, NULL, 0);
+            char *errmsg=malloc(s);
+            regerror(result, &preg, errmsg, s);
+            fprintf(stderr,"regcomp error on '%s': %s\n", regex, errmsg);
+            free(errmsg);
+            regfree(&preg);
+            return 0;
+        }
+
+        regmatch_t matches[1];
+        if (regexec(&preg, value, 1, matches, 0))
+        {
+            fprintf(stderr,"Value: '%s' doesn't match regex '%s'\n", value, regex);
+            regfree(&preg);
+            return 0;
+        }
+        //fprintf(stderr,"match\n");
+        regfree(&preg);
+        return 1;
+    }
+
+    // Returns 1 if OK
+    int validate(const char * tag, const char * value)
+    {
+        int ok=0;
+
+        for (size_t i=0;;++i)
+        {
+            const char *valtag=validations[i*2];
+            const char *valval=validations[i*2+1];
+            if (*valtag=='\0')
+            {
+                fprintf(stderr,"No validation for tag %s\n", tag);
+                ok=1;
+                break;
+            }
+            if (!strcmp(tag, valtag))
+            {
+//                fprintf(stderr,"Checking %s\n", valtag);
+                if (valval[0]=='/')
+                {
+                    ok=regexcheck(valval+1, value);
+                    break;
+                } else
+                {
+                // Parse integer range
+                    fprintf(stderr,"range not implemented\n");
+                    ok=1;
+                }
+            }
+        }
+
+        return ok;
+    }
+
+    size_t alignfields=2; // 1 based, QNAME is #1
+    // TODO, make these dynamic
+    char *tags=NULL; // Space delimited tags seen in current line
+    char *seqnames=NULL;
+    char *ids=NULL;
+
+    void check_required_tag(const char * tag)
+    {
+        if (!strstr(tags,tag))
+        {
+            fprintf(stderr,"%s tag not seen in header\n", tag);
+        }
+    }
+
+%}
+
+/* Declarations */
+%union {
+ int intval;
+ char * strval;
+ double floatval;
+}
+
+%token <strval> HEADER
+%token <strval> SEQUENCE
+%token <strval> READGROUP
+%token <strval> PROGRAM
+%token <strval> COMMENT
+%token <strval> TAG
+%token <strval> VALUE
+%token <strval> ALIGNVALUE
+/* %token DIGITS */
+%token <strval> QNAME
+/*
+%token RNAME
+%token CIGAR
+%token RNEXT
+%token SEQ
+%token QUAL
+%token TTV
+*/
+%token COLON
+%token TAB
+%token CONTROLCHAR
+%token EOL
+%token END 0 "end of file"
+%error-verbose
+%name-prefix="SAM"
+%require "2.5"
+
+
+%%
+ /* Grammar rules */
+sam: /* beginning of input */
+   /* empty %empty */
+   | sam line
+   ;
+
+line:
+   EOL /* Spec is unclear about empty lines, accept for now */
+   | CONTROLCHAR { fprintf(stderr,"error: CONTROLCHAR\n"); }
+   | comment { fprintf(stderr,"comment\n"); }
+   | header EOL { fprintf(stderr,"header\n\n"); }
+   | sequence {fprintf(stderr,"sequence\n\n"); }
+   | program {fprintf(stderr,"program\n\n"); }
+   | readgroup {fprintf(stderr,"readgroup\n\n"); }
+   | alignment { fprintf(stderr,"alignment\n\n"); }
+
+comment:
+    COMMENT { }
+
+header:
+    HEADER tagvaluelist
+    {
+        fprintf(stderr,"header tagvaluelist %s\n", SAMlval.strval);
+        check_required_tag("VN");
+        if (!strcmp(tags,"SO ") && !strcmp(tags,"GO "))
+           fprintf(stderr,"warn: Both SO and GO tags present\n");
+        if (!(strcmp(tags,"SO ") || strcmp(tags,"GO ")))
+           fprintf(stderr,"warn: neither SO or GO tags present\n");
+        *tags='\0';
+    }
+
+sequence:
+    SEQUENCE tagvaluelist
+    {
+        fprintf(stderr, "sequence\n");
+        fprintf(stderr," sequences were: %s\n", seqnames);
+        check_required_tag("SN");
+        check_required_tag("LN");
+        *tags='\0';
+        }
+
+program:
+     PROGRAM tagvaluelist
+     {
+        fprintf(stderr,"ids were: %s\n", ids);
+        fprintf(stderr, "program\n");
+        check_required_tag("ID");
+        *tags='\0';
+     }
+
+
+readgroup:
+     READGROUP tagvaluelist
+     {
+        fprintf(stderr, "readgroup\n");
+        fprintf(stderr,"ids were: %s\n", ids);
+        check_required_tag("ID");
+        *tags='\0';
+     }
+
+tagvaluelist: tagvalue { fprintf(stderr, " one tagvaluelist:%s\n", SAMlval.strval); }
+  | tagvaluelist tagvalue { fprintf(stderr, " many tagvaluelist:%s\n", SAMlval.strval); }
+  ;
+
+tagvalue: TAB TAG COLON VALUE {
+        fprintf(stderr,"tagvalue:%s=%s\n", $2, $4);
+        const char * tag=$2;
+        const char * value=$4;
+
+        if (strlen(tag)!=2)
+        {
+            fprintf(stderr,"tag '%s' must be 2 characters\n", tag);
+        }
+
+        if (islower(tag[0] && islower(tag[1])))
+        {
+            fprintf(stderr,"optional tag\n");
+        } else
+        {
+            validate(tag, value);
+            strcat(tags,tag); strcat(tags," ");
+            if (!strcmp(tag,"SN"))
+            {
+                if (strstr(seqnames,value))
+                {
+                    fprintf(stderr,"error: duplicate sequence %s\n", value);
+                }
+                strcat(seqnames,value); strcat(seqnames," ");
+            }
+            if (!strcmp(tag,"ID"))
+            {
+                if (strstr(ids,value))
+                {
+                    fprintf(stderr,"error: duplicate id %s\n", value);
+                }
+                strcat(ids,value); strcat(ids, " ");
+            }
+        }
+        };
+  | TAB TAB TAG COLON VALUE { fprintf(stderr,"two tabs\n"); }
+  | TAB TAB EOL { fprintf(stderr,"empty tags\n"); }
+  | TAB EOL { fprintf(stderr,"empty tags\n"); }
+
+  ;
+
+alignment:
+    QNAME avlist
+    {
+        fprintf(stderr," avlist qname:%s fields=%zu\n", $1, alignfields);
+        alignfields=2;
+    }
+
+avlist:
+      av { fprintf(stderr," one av\n"); }
+ |    avlist av { fprintf(stderr,":bison: many avlist\n"); }
+
+av:
+    TAB ALIGNVALUE
+    {
+        const char * value=$2;
+        const char * opt="(required)";
+        if (alignfields>=12) opt="(optional)";
+        fprintf(stderr,"alignvalue #%zu%s: %s\n", alignfields, opt, value);
+        switch (alignfields)
+        {
+            case 2: // FLAG
+            {
+                int flag;
+                if (sscanf(value, "%d", &flag)!=1 || flag < 0 || flag > UINT16_MAX)
+                {
+                    fprintf(stderr,"error parsing FLAG: %s\n", value);
+                }
+                fprintf(stderr,"flag is %d\n",flag);
+                break;
+            }
+            case 4: // POS
+            {
+                int pos;
+                if (sscanf(value, "%d", &pos)!=1 || pos <= 0 || pos > INT32_MAX)
+                {
+                    fprintf(stderr,"error parsing POS: %s\n", value);
+                }
+                fprintf(stderr,"pos is %d\n",pos);
+                break;
+            }
+            case 5: // MAPQ
+            {
+                int mapq;
+                if (sscanf(value, "%d", &mapq)!=1 || mapq < 0 || mapq > UINT8_MAX)
+                {
+                    fprintf(stderr,"error parsing MAPQ: %s\n", value);
+                }
+                fprintf(stderr,"mapq is %d\n", mapq);
+                break;
+            }
+            case 8: // PNEXT
+            {
+                int pnext;
+                if (sscanf(value, "%d", &pnext)!=1 || pnext < 0 || pnext > INT32_MAX)
+                {
+                    fprintf(stderr,"error parsing PNEXT: %s\n", value);
+                }
+                fprintf(stderr,"pnext is %d\n",pnext);
+                break;
+            }
+            case 9: // TLEN
+            {
+                int tlen;
+                if (sscanf(value, "%d", &tlen)!=1 || tlen < INT32_MIN || tlen > INT32_MAX)
+                {
+                    fprintf(stderr,"error parsing TLEN: %s\n", value);
+                }
+                fprintf(stderr,"tlen is %d\n", tlen);
+                break;
+            }
+
+
+        }
+        ++alignfields;
+    }
+
+%%
+
+
+ /* Epilogue */
+
+int main(int argc, char * argv[])
+{
+    tags=calloc(255,1); // TODO, make dynamic
+    seqnames=calloc(10000,1); // TODO, ""
+    ids=calloc(10000,1); // TODO, ""
+
+    return SAMparse();
+}
+
diff --git a/tools/bam-loader/samview.c b/tools/bam-loader/samview.c
index 44fed67..eaa0f06 100644
--- a/tools/bam-loader/samview.c
+++ b/tools/bam-loader/samview.c
@@ -22,6 +22,7 @@
  *
  * ===========================================================================
  *
+ * Primarily, this exists to drive our BAM/SAM parsing code
  */
 
 #include <kapp/args.h>
diff --git a/tools/general-loader/general-loader.hpp b/tools/general-loader/general-loader.hpp
index 314e782..c700052 100644
--- a/tools/general-loader/general-loader.hpp
+++ b/tools/general-loader/general-loader.hpp
@@ -215,7 +215,7 @@ private:
     private:
         // read p_dataSize bytes and use one of the decoder functions in utf8-like-int-codec.h to unpack a sequence of integer values, 
         // stored in m_unpackingBuf as a collection of bytes
-        template < typename T_uintXX > rc_t UncompressInt ( Reader& p_reader, uint16_t p_dataSize, int ( * p_decode ) ( uint8_t const* buf_start, uint8_t const* buf_xend, T_uintXX* ret_decoded ) );
+        template < typename T_uintXX > rc_t UncompressInt ( Reader& p_reader, uint32_t p_dataSize, int ( * p_decode ) ( uint8_t const* buf_start, uint8_t const* buf_xend, T_uintXX* ret_decoded ) );
         
         rc_t ParseData ( Reader& p_reader, DatabaseLoader& p_dbLoader, uint32_t p_columnId, uint32_t p_dataSize );
         
diff --git a/tools/general-loader/protocol-parser.cpp b/tools/general-loader/protocol-parser.cpp
index 398e3a9..c47d88c 100644
--- a/tools/general-loader/protocol-parser.cpp
+++ b/tools/general-loader/protocol-parser.cpp
@@ -460,7 +460,7 @@ GeneralLoader :: UnpackedProtocolParser :: ParseEvents ( Reader& p_reader, Datab
 
 template < typename T_uintXX > 
 rc_t 
-GeneralLoader :: PackedProtocolParser :: UncompressInt (  Reader& p_reader, uint16_t p_dataSize, int (*p_decode) ( uint8_t const* buf_start, uint8_t const* buf_xend, T_uintXX* ret_decoded )  )
+GeneralLoader :: PackedProtocolParser :: UncompressInt (  Reader& p_reader, uint32_t p_dataSize, int (*p_decode) ( uint8_t const* buf_start, uint8_t const* buf_xend, T_uintXX* ret_decoded )  )
 {
     m_unpackingBuf . clear();
     // reserve enough for the best-packed case, when each element is represented with 1 byte
diff --git a/tools/prefetch/prefetch.c b/tools/prefetch/prefetch.c
index 98045f3..bdef754 100644
--- a/tools/prefetch/prefetch.c
+++ b/tools/prefetch/prefetch.c
@@ -565,8 +565,10 @@ static rc_t _VResolverRemote(VResolver *self, VRemoteProtocols protocols,
         if (vcache == NULL) {
             rc = RC(rcExe, rcResolver, rcResolving, rcPath, rcNotFound);
             PLOGERR(klogInt, (klogInt, rc, "cannot get cache location "
-                "for $(acc).", /* Try to cd out of protected repository.", */
-                "acc=%s" , name));
+             "for $(acc). "
+             "Hint: run \"vdb-config --interactive\" and make sure Workspace Location Path is set. "
+             "See https://github.com/ncbi/sra-tools/wiki/Toolkit-Configuration", 
+             "acc=%s" , name));
         }
 
         if (rc == 0) {
@@ -2180,6 +2182,7 @@ static rc_t ItemResetRemoteToVdbcacheIfVdbcacheRemoteExists(
             char *query = string_chr(remotePath, len, '?');
             if (query != NULL) {
                 *query = '\0';
+                len = query - remotePath;
             }
             STSMSG(STS_DBG, ("'%s' exists", remotePath));
             STSMSG(STS_TOP, ("'%s' has remote vdbcache", resolved->name));
@@ -2297,7 +2300,7 @@ static bool MainNeedDownload(const Main *self, const String *local,
         }
         {
             const KFile *f = NULL;
-            rc = KDirectoryOpenFileRead(self->dir, &f, "%S", local);
+            rc = KDirectoryOpenFileRead(self->dir, &f, "%s", local->addr);
             if (rc != 0) {
                 DISP_RC2(rc, "KDirectoryOpenFileRead", local->addr);
                 return true;
@@ -2443,6 +2446,8 @@ static rc_t ItemDownloadVdbcache(Item *item) {
     if (localExists) {
         download = MainNeedDownload(item->main, local ? local : cache,
             remotePath, resolved->file, &resolved->remoteSz);
+        if ( ! download )
+            STSMSG(STS_TOP, (" vdbcache is found locally"));
     }
     RELEASE(String, local);
     RELEASE(String, resolved->cache);
@@ -2452,8 +2457,10 @@ static rc_t ItemDownloadVdbcache(Item *item) {
      /* ignore fasp transport request while ascp vdbcache address is unknown */
         item->main->noHttp = false;
 
+        STSMSG(STS_TOP, (" Downloading vdbcache..."));
         rc = MainDownload(&item->resolved, item->main, item->isDependency);
         if (rc == 0) {
+            STSMSG(STS_TOP, (" vdbcache was downloaded successfully"));
             if (local && StringCompare(local, cache) != 0) {
                 STSMSG(STS_DBG, ("Removing '%S'", local));
                 /* TODO rm local vdbcache file
@@ -2461,7 +2468,8 @@ static rc_t ItemDownloadVdbcache(Item *item) {
                 rc = KDirectoryRemove(item->main->dir, false, "%S", local);
                     */
             }
-        }
+        } else
+            STSMSG(STS_TOP, (" failed to download vdbcache"));
     }
     return rc;
 }
diff --git a/tools/sra-dump/fastq.c b/tools/sra-dump/fastq.c
index 7f37f4b..868443f 100644
--- a/tools/sra-dump/fastq.c
+++ b/tools/sra-dump/fastq.c
@@ -3740,13 +3740,13 @@ rc_t SRADumper_Init( SRADumperFmt* fmt )
                             "Name can either be accession.version (ex: NC_000001.10) or",
                             "file specific name (ex: \"chr1\" or \"1\").",
                             "\"from\" and \"to\" are 1-based coordinates", NULL}},
-            {NULL, "matepair-distance", "from-to|unknown", {"Filter by distance beiween matepairs.", /* H_matepair-distance = 19 */
+            {NULL, "matepair-distance", "from-to|unknown", {"Filter by distance between matepairs.", /* H_matepair-distance = 19 */
                             "Use \"unknown\" to find matepairs split between the references.",
                             "Use from-to to limit matepair distance on the same reference", NULL}},
 
             {NULL, "qual-filter-1", NULL, {"Filter used in current 1000 Genomes data", NULL}}, /* H_qual_filter_1 = 20 */
 
-            {NULL, "suppress-qual-for-cskey", NULL, {"supress quality-value for cskey", NULL}}, /* H_SuppressQualForCSKey = 21 */
+            {NULL, "suppress-qual-for-cskey", NULL, {"suppress quality-value for cskey", NULL}}, /* H_SuppressQualForCSKey = 21 */
 
             {NULL, NULL, NULL, {NULL}}
         };
diff --git a/tools/sra-pileup/sam-aligned.c b/tools/sra-pileup/sam-aligned.c
index 1ed9b75..694f48a 100644
--- a/tools/sra-pileup/sam-aligned.c
+++ b/tools/sra-pileup/sam-aligned.c
@@ -1964,7 +1964,7 @@ static rc_t print_alignment_fastx( const samdump_opts * const opts,
             if ( rc == 0 )
             {
                 if ( quality_size > 0 )
-                    rc = dump_quality_33( opts, quality, quality_size, false );
+                    rc = dump_quality_33( opts, quality, quality_size, orientation );  /* sam-dump-opts.c */
                 else
                     rc = KOutMsg( "*" );
             }
diff --git a/tools/sra-pileup/sam-unaligned.c b/tools/sra-pileup/sam-unaligned.c
index 9d0d72a..6384728 100644
--- a/tools/sra-pileup/sam-unaligned.c
+++ b/tools/sra-pileup/sam-unaligned.c
@@ -653,8 +653,26 @@ static rc_t dump_seq_row_sam_filtered( const samdump_opts * const opts,
 
                             /* SAM-FIELD: QNAME     SRA-column: SPOT_ID ( int64 ) */
                             if ( rc == 0 )
-                                rc = KOutMsg( "%ld\t", seq_spot_id );
-
+                            {
+                                bool print_just_seq_spot_id = true;
+                                
+                                if ( opts->print_spot_group_in_name )
+                                {
+                                    const char * spot_group;
+                                    uint32_t spot_group_len;
+                                    rc = read_char_ptr( row_id, stx->cursor, stx->spot_group_idx, &spot_group, &spot_group_len, "SPOT_GROUP" );
+                                    if ( rc == 0 && spot_group_len > 0 )
+                                    {
+                                        rc = KOutMsg( "%ld.%.*s\t", seq_spot_id, spot_group_len, spot_group );
+                                        print_just_seq_spot_id = false;
+                                    }
+                                }
+                                if ( print_just_seq_spot_id )
+                                {
+                                    rc = KOutMsg( "%ld\t", seq_spot_id );
+                                }
+                            }
+                            
                             if ( rc == 0 && read_type == NULL )
                                 rc = read_read_type( stx, row_id, &read_type, nreads );
 
@@ -787,8 +805,26 @@ static rc_t dump_seq_prim_row_sam( const samdump_opts * const opts,
 
             /* SAM-FIELD: QNAME     SRA-column: SPOT_ID ( int64 ) */
             if ( rc == 0 )
-                rc = KOutMsg( "%ld\t", row_id );
-
+            {
+                bool print_just_seq_spot_id = true;
+                
+                if ( opts->print_spot_group_in_name )
+                {
+                    const char * spot_group;
+                    uint32_t spot_group_len;
+                    rc = read_char_ptr( row_id, stx->cursor, stx->spot_group_idx, &spot_group, &spot_group_len, "SPOT_GROUP" );
+                    if ( rc == 0 && spot_group_len > 0 )
+                    {
+                        rc = KOutMsg( "%ld.%.*s\t", row_id, spot_group_len, spot_group );
+                        print_just_seq_spot_id = false;
+                    }
+                }
+                if ( print_just_seq_spot_id )
+                {
+                    rc = KOutMsg( "%ld\t", row_id );
+                }
+            }
+            
             /* SAM-FIELD: FLAG      SRA-column: calculated from READ_TYPE, READ_FILTER etc. */
             if ( rc == 0 )
             {
@@ -939,10 +975,30 @@ static rc_t dump_seq_row_sam( const samdump_opts * const opts,
             /* SAM-FIELD: QNAME     SRA-column: SPOT_ID ( int64 ) */
             if ( rc == 0 )
             {
-                if ( name != NULL && name_len > 0 )
-                    rc = KOutMsg( "%.*s\t", name_len, name );
-                else
-                    rc = KOutMsg( "%lu\t", row_id );
+                bool print_just_seq_spot_id = true;
+                
+                if ( opts->print_spot_group_in_name )
+                {
+                    const char * spot_group;
+                    uint32_t spot_group_len;
+                    rc = read_char_ptr( row_id, stx->cursor, stx->spot_group_idx, &spot_group, &spot_group_len, "SPOT_GROUP" );
+                    if ( rc == 0 && spot_group_len > 0 )
+                    {
+                        if ( name != NULL && name_len > 0 )
+                            rc = KOutMsg( "%.*s.%.*s\t", name_len, name, spot_group_len, spot_group );
+                        else
+                            rc = KOutMsg( "%ld.%.*s\t", row_id, spot_group_len, spot_group );
+                        print_just_seq_spot_id = false;
+                    }
+                }
+
+                if ( print_just_seq_spot_id )
+                {
+                    if ( name != NULL && name_len > 0 )
+                        rc = KOutMsg( "%.*s\t", name_len, name );
+                    else
+                        rc = KOutMsg( "%lu\t", row_id );
+                }
             }
 
             /* SAM-FIELD: FLAG      SRA-column: calculated from READ_TYPE, READ_FILTER etc. */
@@ -1040,7 +1096,7 @@ static rc_t dump_seq_row_fastx_filtered( const samdump_opts * const opts,
                 rc = matecache_lookup_unaligned( mc, ids->db_idx, align_id, &mate_ref_pos, &ref_idx, &seq_spot_id );
                 if ( rc == 0 )
                 {
-                    bool reverse;
+                    /* bool reverse; */
 
                     /* the NAME */
                     if ( opts->output_format == of_fastq )
@@ -1064,14 +1120,16 @@ static rc_t dump_seq_row_fastx_filtered( const samdump_opts * const opts,
                         rc = read_quality( stx, row_id, &quality, rd_len );
                     if ( rc == 0 && read_type == NULL )
                         rc = read_read_type( stx, row_id, &read_type, nreads );
+                    /*
                     if ( rc == 0 )
                         reverse = ( ( read_type[ read_idx ] & READ_TYPE_REVERSE ) == READ_TYPE_REVERSE );
+                    */
                     if ( rc == 0 && read_start == NULL )
                         rc = read_read_start( stx, row_id, &read_start, nreads );
 
                     /* the READ */
                     if ( rc == 0 )
-                        rc = print_sliced_read( read, read_idx, reverse, read_start, read_len );
+                        rc = print_sliced_read( read, read_idx, /* reverse */ false, read_start, read_len );
                     if ( rc == 0 )
                         rc = KOutMsg( "\n" );
 
@@ -1080,7 +1138,7 @@ static rc_t dump_seq_row_fastx_filtered( const samdump_opts * const opts,
                     {
                         rc = KOutMsg( "+\n" );
                         if ( rc == 0 )
-                            rc = print_sliced_quality( opts, quality, read_idx, reverse, read_start, read_len );
+                            rc = print_sliced_quality( opts, quality, read_idx, /* reverse */ false, read_start, read_len );
                         if ( rc == 0 )
                             rc = KOutMsg( "\n" );
                     }
@@ -1121,7 +1179,7 @@ static rc_t dump_seq_row_fastx( const samdump_opts * const opts,
         if ( prim_align_ids[ read_idx ] == 0 &&    /* read is NOT aligned! */
              read_len[ read_idx ] > 0 )            /* and has a length! */
         {
-            bool reverse;
+            /* bool reverse; */
 
             /* the NAME */
             if ( opts->output_format == of_fastq )
@@ -1144,14 +1202,16 @@ static rc_t dump_seq_row_fastx( const samdump_opts * const opts,
                 rc = read_quality( stx, row_id, &quality, rd_len );
             if ( rc == 0 && read_type == NULL )
                 rc = read_read_type( stx, row_id, &read_type, nreads );
+            /*
             if ( rc == 0 )
                 reverse = ( ( read_type[ read_idx ] & READ_TYPE_REVERSE ) == READ_TYPE_REVERSE );
+            */
             if ( rc == 0 && read_start == NULL )
                 rc = read_read_start( stx, row_id, &read_start, nreads );
 
             /* the READ */
             if ( rc == 0 )
-                rc = print_sliced_read( read, read_idx, reverse, read_start, read_len );
+                rc = print_sliced_read( read, read_idx, /*reverse*/ false, read_start, read_len );
             if ( rc == 0 )
                 rc = KOutMsg( "\n" );
 
@@ -1160,7 +1220,7 @@ static rc_t dump_seq_row_fastx( const samdump_opts * const opts,
             {
                 rc = KOutMsg( "+\n" );
                 if ( rc == 0 )
-                    rc = print_sliced_quality( opts, quality, read_idx, reverse, read_start, read_len );
+                    rc = print_sliced_quality( opts, quality, read_idx, /*reverse*/ false, read_start, read_len );
                 if ( rc == 0 )
                     rc = KOutMsg( "\n" );
             }
@@ -1195,7 +1255,7 @@ static rc_t dump_seq_tab_row_fastx( const samdump_opts * const opts,
         if ( ( read_len[ read_idx ] > 0 ) &&            /* has a length! */
              ( ( read_type[ read_idx ] & READ_TYPE_BIOLOGICAL ) == READ_TYPE_BIOLOGICAL ) )
         {
-            bool reverse;
+            /* bool reverse; */
 
             /* the NAME */
             if ( opts->output_format == of_fastq )
@@ -1218,14 +1278,16 @@ static rc_t dump_seq_tab_row_fastx( const samdump_opts * const opts,
                 rc = read_INSDC_dna_text_ptr( row_id, stx->cursor, stx->read_idx, &read, &rd_len, "READ" );
             if ( rc == 0 && quality == NULL )
                 rc = read_quality( stx, row_id, &quality, rd_len );
+            /*
             if ( rc == 0 )
                 reverse = ( ( read_type[ read_idx ] & READ_TYPE_REVERSE ) == READ_TYPE_REVERSE );
+            */
             if ( rc == 0 && read_start == NULL )
                 rc = read_read_start( stx, row_id, &read_start, nreads );
 
             /* the READ */
             if ( rc == 0 )
-                rc = print_sliced_read( read, read_idx, reverse, read_start, read_len );
+                rc = print_sliced_read( read, read_idx, /* reverse */ false, read_start, read_len );
             if ( rc == 0 )
                 rc = KOutMsg( "\n" );
 
@@ -1237,7 +1299,7 @@ static rc_t dump_seq_tab_row_fastx( const samdump_opts * const opts,
                 if ( rc == 0 )
                     rc = KOutMsg( "+\n" );
                 if ( rc == 0 )
-                    rc = print_sliced_quality( opts, quality, read_idx, reverse, read_start, read_len );
+                    rc = print_sliced_quality( opts, quality, read_idx, /* reverse */ false, read_start, read_len );
                 if ( rc == 0 )
                     rc = KOutMsg( "\n" );
             }
diff --git a/tools/sra-stat/sra-stat.c b/tools/sra-stat/sra-stat.c
index 5ff70d6..754e88c 100644
--- a/tools/sra-stat/sra-stat.c
+++ b/tools/sra-stat/sra-stat.c
@@ -89,7 +89,7 @@
 #define RELEASE(type, obj) do { rc_t rc2 = type##Release(obj); \
     if (rc2 && !rc) { rc = rc2; } obj = NULL; } while (false)
 
-#define MAX_NREADS 2*1024
+#define MAX_NREADS ( 4 * 1024 )
 
 #define DEFAULT_CURSOR_CAPACITY (1024*1024*1024UL)
 
@@ -2094,6 +2094,45 @@ rc_t get_stats_meta(const KMetadata* meta,
     return rc;
 }
 
+static bool needEscaping ( const char * c ) {
+    return string_chr ( c, string_measure ( c, NULL), '"' ) != NULL
+        || string_chr ( c, string_measure ( c, NULL), '\'' ) != NULL
+        || string_chr ( c, string_measure ( c, NULL), '&' ) != NULL
+        || string_chr ( c, string_measure ( c, NULL), '<' ) != NULL
+        || string_chr ( c, string_measure ( c, NULL), '>' ) != NULL;
+}
+
+static rc_t printXmlEscaped ( const char * c ) {
+    rc_t rc = 0;
+    rc_t r2 = 0;
+    while ( * c ) {
+        switch  ( * c ) {
+            case '"':
+                r2 = OUTMSG ( ( """ ) );
+                break;
+            case '\'':
+                r2 = OUTMSG ( ( "'" ) );
+                break;
+            case '&':
+                r2 = OUTMSG ( ( "&" ) );
+                break;
+            case '<':
+                r2 = OUTMSG ( ( "<" ) );
+                break;
+            case '>':
+                r2 = OUTMSG ( ( ">" ) );
+                break;
+            default:
+                r2 = OUTMSG ( ( "%c", *c ) );
+                break;
+        }
+        if ( rc == 0 )
+            rc = r2;
+        ++ c;;
+    }
+    return rc;
+}
+
 static
 void srastatmeta_print(const MetaDataStats* meta, srastat_parms *pb)
 {
@@ -2117,7 +2156,14 @@ void srastatmeta_print(const MetaDataStats* meta, srastat_parms *pb)
                 }
                 if (pb->xml) {
                     if (pb->hasSPOT_GROUP) {
-                       OUTMSG(("  <Member member_name=\"%s\"", ss->spot_group));
+                       if (needEscaping(ss->spot_group)) {
+                           OUTMSG(("  <Member member_name=\""));
+                           printXmlEscaped(                 ss->spot_group);
+                           OUTMSG((                                      "\""));
+                       }
+                       else
+                            OUTMSG(("  <Member member_name=\"%s\"",
+                                    ss->spot_group));
                        OUTMSG((" spot_count=\"%ld\" base_count=\"%ld\"",
                             ss->spot_count, ss->BASE_COUNT));
                        OUTMSG((" base_count_bio=\"%ld\"", ss->BIO_BASE_COUNT));
@@ -2909,17 +2955,6 @@ static rc_t sra_stat(srastat_parms* pb, BSTree* tr,
                                         }
                                     }
                                 }
-/*                              if (cCMP_READ) {
-      rc = SRAColumnRead(cCMP_READ, spotid, &base, &boff, &row_bits);
-      DISP_RC_Read(rc, CMP_READ, spotid, "while calling SRAColumnRead");
-      if (boff & 7)
-      {   rc = RC(rcExe, rcColumn, rcReading, rcOffset, rcInvalid); }
-      if (row_bits & 7)
-      {   rc = RC(rcExe, rcColumn, rcReading, rcSize, rcInvalid); }
-      DISP_RC_Read(rc, CMP_READ, spotid, "after calling calling SRAColumnRead");
-      if (rc == 0)
-      {   assert(cmp_len == row_bits >> 3); }
-                                               } */
 
                                 ss = (SraStats*)BSTreeFind
                                     (tr, dSPOT_GROUP, srastats_cmp);
@@ -2951,6 +2986,11 @@ static rc_t sra_stat(srastat_parms* pb, BSTree* tr,
                                         = filt_cnt = 0;
                                     (i < nreads) && (rc == 0); i++)
                                 {
+                                    if ( i >= MAX_NREADS ) {
+                                        rc = RC ( rcExe, rcData, rcProcessing,
+                                                  rcBuffer, rcInsufficient );
+                                        break;
+                                    }
                                     if (dREAD_LEN[i] > 0) {
                                         g_totalREAD_LEN[i] += dREAD_LEN[i];
                                         ++g_nonZeroLenReads[i];
@@ -3105,6 +3145,9 @@ static rc_t sra_stat(srastat_parms* pb, BSTree* tr,
                     idx, &base, &boff, &row_bits);
                 DISP_RC_Read(rc, READ_LEN, spotid,
                     "while calling VCursorColumnRead");
+                if ( ( row_bits >> 3 ) > sizeof dREAD_LEN )
+                    rc = RC ( rcExe, rcColumn, rcReading,
+                              rcBuffer, rcInsufficient);
             }
             if (rc == 0) {
                 memmove(dREAD_LEN, ((const char*)base) + (boff>>3), row_bits>>3);
diff --git a/tools/util/pseudo-aligner.cpp b/tools/util/pseudo-aligner.cpp
index 3548e37..c050046 100644
--- a/tools/util/pseudo-aligner.cpp
+++ b/tools/util/pseudo-aligner.cpp
@@ -125,7 +125,11 @@ class Quality {
             return value + 33;
         }
         static Phred random() {
-            return Phred(max(3, min(40, int(33 + normalRandom().first * 5))));
+            for (;;) {
+                auto const value = int(33 + normalRandom().first * 5);
+                if (3 <= value && value <= 40)
+                    return Phred(value);
+            }
         }
     };
     typedef vector<Phred> vector_t;
@@ -148,9 +152,8 @@ public:
     }
     static Quality random() {
         auto rslt = vector_t(settings->readLength);
-        
-        for (auto i : rslt) {
-            i = Phred::random();
+        for (auto i = 0; i < settings->readLength; ++i) {
+            rslt[i] = Phred::random();
         }
         return Quality(rslt);
     }
@@ -169,7 +172,7 @@ struct Base {
         return Base(value == 0 ? 0 : (5 - value));
     }
     static Base random() {
-        auto const GC = frand() > 0.2; // GC or AT
+        auto const GC = frand() > 0.2; // GC or AT; is biased, target GC content is 40%
         auto const AC = frand() > 0.0; // A or C
         return Base(GC ? (AC ? 2 : 3) : (AC ? 1 : 4));
     }
@@ -356,25 +359,17 @@ static uint64_t scramble(uint64_t const serialNo)
     static uint8_t const *mixer = NULL;
     
     if (mixer == NULL) {
-        for (int i = 0; i < 256; ++i)
-            scramble[i] = i;
-        for (int k = 0; k < 256; ++k) {
-            for (int i = 0; i < 256; ++i) {
-                auto const j = random() % 256;
-                auto const xi = scramble[i];
-                auto const xj = scramble[j];
-                
-                scramble[i] = xj;
-                scramble[j] = xi;
-            }
+        for (int i = 0; i < 256; ++i) {
+            auto const j = random() % (i + 1);
+            scramble[i] = scramble[j];
+            scramble[j] = i;
         }
         mixer = scramble;
     }
-    uint64_t rslt = 0;
+    auto rslt = serialNo;
     auto carry = 0x55;
     for (auto i = 0; i < 8; ++i) {
-        auto const j = serialNo >> (8 * i);
-        auto const k = mixer[(uint8_t)(j ^ carry)];
+        auto const k = mixer[uint8_t(rslt ^ carry)];
         rslt = (uint64_t(k) << 56) | (rslt >> 8);
         carry = k;
     }
@@ -422,7 +417,7 @@ static void run(void)
     auto ref = RefSequence();
     uint64_t serialNo = 0;
     
-    for (double coverage = 0.0; coverage/double(ref.size()) > settings->coverageTarget; ) {
+    for (double coverage = 0.0; coverage/double(ref.size()) < settings->coverageTarget; ) {
         auto const ipd = make_ipd_pair();
         auto const pos = make_read_pair(ipd.first);
         auto const rev = pos.first > pos.second;
diff --git a/tools/util/test-sra.c b/tools/util/test-sra.c
index e00a73c..c61ea62 100644
--- a/tools/util/test-sra.c
+++ b/tools/util/test-sra.c
@@ -3422,32 +3422,163 @@ static rc_t PrintLib ( const char * path, bool xml ) {
     return rc;
 }
 
-rc_t CC KMain(int argc, char *argv[]) {
-    rc_t rc = 0;
-    uint32_t pcount = 0;
-    uint32_t i = 0;
-    Args *args = NULL;
-    rc_t rc3 = 0;
-    int argi = 0;
-    uint32_t params = 0;
-    const char * eol = "\n";
+/******************************************************************************/
+static rc_t MainFreeSpace ( const Main * self, const KDirectory * dir ) {
+    uint64_t free_bytes_available = 0;
+    uint64_t total_number_of_bytes = 0;
+    rc_t rc = KDirectoryGetDiskFreeSpace ( dir, & free_bytes_available,
+                                           & total_number_of_bytes );
+    if ( rc != 0 ) 
+        return rc;
 
-    Main prms;
-    char **argv2 = MainInit(&prms, argc, argv, &argi);
+    assert ( self );
 
-    if ( rc == 0 && prms . xml ) {
-        eol = "<br/>\n";
-    }
+    free_bytes_available /= 1024;
+    total_number_of_bytes /= 1024;
 
-    if (rc == 0) {
-        rc = ArgsMakeAndHandle(&args, argi, argv2, 1,
-            Options, sizeof Options / sizeof Options[0]);
-    }
+    if ( self -> xml )
+        OUTMSG ( (
+            "      <Space free=\"%d\" total=\"%d\" units=\"KBytes\"/>\n",
+            free_bytes_available, total_number_of_bytes ) );
+    else
+        OUTMSG ( (
+            "    Space free=\"%d\" total=\"%d\" units=\"KBytes\"\n",
+            free_bytes_available, total_number_of_bytes ) );
+
+    return rc;
+}
+
+static rc_t MainRepository ( const Main * self, const KRepository * repo ) {
+    const char tag [] = "User";
+    char buffer [ PATH_MAX ] = "";
+    size_t size = 0;
+    rc_t rc = KRepositoryName ( repo, buffer, sizeof buffer, & size );
+
+    assert ( self );
 
     if ( rc == 0 ) {
-        rc = ArgsParamCount ( args, & params );
+        if ( self -> xml )
+            OUTMSG ( ( "    <%s name=\"%s\"/>\n", tag, buffer ) );
+        else
+            OUTMSG (( "  %s name=\"%s\"\n", tag, buffer ));
+
+        rc = KRepositoryRoot ( repo, buffer, sizeof buffer, & size );
+        if ( rc == 0 ) {
+            bool found = true;
+            const KDirectory * dir = NULL;
+            rc_t rc = KDirectoryOpenDirRead ( self -> dir, & dir, false,
+                                              buffer );
+            if ( rc == SILENT_RC
+                ( rcFS, rcDirectory, rcOpening, rcPath, rcNotFound ) )
+            {
+                found = false;
+                rc = 0;
+            }
+    
+            if ( rc == 0 ) {
+                char b1 [ PATH_MAX ] = "";
+                char b2 [ PATH_MAX ] = "";
+                char * current = b1;
+                char * resolved = b2;
+                int i = 0;
+                string_copy ( b1, sizeof b1, buffer, size );
+                if ( self -> xml )
+                    OUTMSG ( ( "      <Root found=\"%s\">%s</Root>\n",
+                               found ? "true" : "false", current ) );
+                else
+                    OUTMSG ( ( "    Root=\"%s\" found=\"%s\"\n",
+                               current, found ? "true" : "false" ) );
+                for ( i = 0; i < 9 && ! found; ++ i ) {
+                    rc = KDirectoryResolvePath ( self -> dir, true, resolved,
+                                                 sizeof b1, "%s/..", current );
+                    if ( rc == 0 ) {
+                        rc = KDirectoryOpenDirRead ( self -> dir, & dir, false,
+                                                     resolved );
+                        if ( rc == 0 ) {
+                            found = true;
+                            current = resolved;
+                            if ( self -> xml )
+                                OUTMSG ( ( "      <Found>%s</Found>\n",
+                                           current ) );
+                            else
+                                OUTMSG ( ( "    Found=\"%s\"\n", current ) );
+                        }
+                        else if ( rc == SILENT_RC ( rcFS, rcDirectory,
+                                               rcOpening, rcPath, rcNotFound ) )
+                        {
+                            char * t = current;
+                            current = resolved;
+                            resolved = t;
+                        }
+                        else
+                            break;
+                    }
+                }
+                if ( found )
+                    MainFreeSpace ( self, dir );
+                RELEASE ( KDirectory, dir );
+            }
+            else {
+                if ( self -> xml )
+                    OUTMSG ( (
+                        "      <Root KDirectoryOpenDirRead=\"%R\">%s<Root>\n",
+                        rc, buffer ) );
+                else
+                    OUTMSG ( ( "  Root=\"%s\" KDirectoryOpenDirRead=\"%R\"\n",
+                               buffer, rc ));
+            }
+        }
+    }
+
+    if ( rc == 0 && self -> xml )
+        OUTMSG ( ( "    </%s>\n", tag ) );
+
+    return rc;
+}
+
+static rc_t MainRepositories ( const Main * self, const char * bol ) {
+    rc_t rc = 0;
+
+    const char tag [] = "Repositories";
+
+    KRepositoryVector user_repositories;
+    memset ( & user_repositories, 0, sizeof user_repositories );
+
+    assert ( self );
+
+    if ( self -> xml )
+        OUTMSG (( "%s<%s>\n", bol, tag ));
+    else
+        OUTMSG ( ( "\n%s\n", tag ));
+
+    rc = KRepositoryMgrUserRepositories ( self -> repoMgr,
+                                          & user_repositories );
+
+    if ( rc == 0) {
+        uint32_t len = VectorLength ( & user_repositories );
+        uint32_t i = 0;
+        for ( i = 0; i < len; ++ i ) {
+            const KRepository * repo = VectorGet ( & user_repositories, i );
+            if ( repo != NULL )
+                MainRepository ( self, repo );
+        }
     }
 
+    KRepositoryVectorWhack ( & user_repositories );
+
+    if ( self -> xml )
+        OUTMSG (( "%s</%s>\n", bol, tag ));
+
+    return rc;
+}
+/******************************************************************************/
+
+static rc_t MainFromArgs ( Main * self, const Args * args ) {
+    rc_t rc = 0;
+    uint32_t pcount = 0;
+
+    assert ( self );
+
     if (rc == 0) {
         rc = ArgsOptionCount(args, OPTION_CACHE, &pcount);
         if (rc) {
@@ -3455,7 +3586,7 @@ rc_t CC KMain(int argc, char *argv[]) {
         }
         else {
             if (pcount > 0) {
-                prms.allowCaching = true;
+                self -> allowCaching = true;
             }
         }
     }
@@ -3475,13 +3606,13 @@ rc_t CC KMain(int argc, char *argv[]) {
                         "Failure to get '" OPTION_PRJ "' argument");
                 }
                 else {
-                    prms.projectId = AsciiToU32(dummy, NULL, NULL);
+                    self->projectId = AsciiToU32(dummy, NULL, NULL);
                 }
             }
         }
     }
 
-    prms.full = true;
+    self->full = true;
 
     if (rc == 0) {
         rc = ArgsOptionCount(args, OPTION_QUICK, &pcount);
@@ -3490,7 +3621,7 @@ rc_t CC KMain(int argc, char *argv[]) {
         }
         else {
             if (pcount > 0) {
-                prms.full = false;
+                self->full = false;
             }
         }
     }
@@ -3502,13 +3633,13 @@ rc_t CC KMain(int argc, char *argv[]) {
         }
         else {
             if (pcount > 0) {
-                prms.full = true;
+                self->full = true;
             }
         }
     }
 
     if (rc == 0) {
-        prms.bytes = 256;
+        self->bytes = 256;
         rc = ArgsOptionCount(args, OPTION_BYTES, &pcount);
         if (rc) {
             LOGERR(klogErr, rc, "Failure to get '" OPTION_BYTES "' argument");
@@ -3521,9 +3652,9 @@ rc_t CC KMain(int argc, char *argv[]) {
                 if (rc == 0) {
                     int bytes = atoi(val);
                     if (bytes > 0) {
-                        prms.bytes = bytes;
-                        MainAddTest(&prms, ePrintFile);
-                        MainAddTest(&prms, eResolve);
+                        self->bytes = bytes;
+                        MainAddTest(self, ePrintFile);
+                        MainAddTest(self, eResolve);
                     }
                 } else {
                     LOGERR(klogErr, rc,
@@ -3533,27 +3664,90 @@ rc_t CC KMain(int argc, char *argv[]) {
         }
     }
 
-    if (!prms.full) {
-        MainMakeQuick(&prms);
+    if (rc == 0) {
+        rc = ArgsOptionCount(args, OPTION_NO_RFS, &pcount);
+        if (rc) {
+            LOGERR(klogErr, rc,
+                "Failure to get '" OPTION_NO_RFS "' argument");
+        }
+        else {
+            if (pcount > 0) {
+                self->noRfs = true;
+            }
+        }
     }
 
     if (rc == 0) {
-        rc = MainInitObjects(&prms);
+        rc = ArgsOptionCount(args, OPTION_NO_VDB, &pcount);
+        if (rc) {
+            LOGERR(klogErr, rc,
+                "Failure to get '" OPTION_NO_VDB "' argument");
+        }
+        else {
+            if (pcount > 0) {
+                self->noVDBManagerPathType = true;
+            }
+        }
     }
 
     if (rc == 0) {
+        rc = ArgsOptionCount(args, OPTION_REC, &pcount);
+        if (rc) {
+            LOGERR(klogErr, rc, "Failure to get '" OPTION_REC "' argument");
+        }
+        else {
+            if (pcount > 0) {
+                self->recursive = true;
+            }
+        }
+    }
+
+    return rc;
+}
+
+rc_t CC KMain(int argc, char *argv[]) {
+    rc_t rc = 0;
+    uint32_t pcount = 0;
+    uint32_t i = 0;
+    Args *args = NULL;
+    rc_t rc3 = 0;
+    int argi = 0;
+    uint32_t params = 0;
+    const char * eol = "\n";
+
+    Main prms;
+    char **argv2 = MainInit(&prms, argc, argv, &argi);
+
+    if ( rc == 0 && prms . xml )
+        eol = "<br/>\n";
+
+    if (rc == 0)
+        rc = ArgsMakeAndHandle(&args, argi, argv2, 1,
+            Options, sizeof Options / sizeof Options[0]);
+
+    if ( rc == 0 )
+        rc = ArgsParamCount ( args, & params );
+
+    if ( rc == 0 )
+        rc = MainFromArgs ( & prms, args );
+
+    if (!prms.full)
+        MainMakeQuick(&prms);
+
+    if (rc == 0)
+        rc = MainInitObjects(&prms);
+
+    if (rc == 0) {
         rc = ArgsOptionCount(args, OPTION_LIB, &pcount);
-        if (rc == 0 && pcount > 0 && ! prms.xml) {
+        if (rc == 0 && pcount > 0 && ! prms.xml)
             prms . tests = 0;
-        }
     }
 
     if (rc == 0) {
         const char root[] = "Test-sra";
         rc = ArgsOptionCount(args, OPTION_OUT, &pcount);
-        if (rc) {
+        if (rc)
             LOGERR(klogErr, rc, "Failure to get '" OPTION_OUT "' argument");
-        }
         else {
             if (pcount > 0) {
                 const char *dummy = NULL;
@@ -3563,12 +3757,10 @@ rc_t CC KMain(int argc, char *argv[]) {
                     LOGERR(klogErr, rc,
                         "Failure to get '" OPTION_OUT "' argument");
                 }
-                else if (strcmp(dummy, "x") == 0 || strcmp(dummy, "X") == 0) {
+                else if (strcmp(dummy, "x") == 0 || strcmp(dummy, "X") == 0)
                     prms.xml = true;
-                }
-                else {
+                else
                     prms.xml = false;
-                }
             }
             else {
                 prms.xml = MainHasTest(&prms, eCfg)
@@ -3576,130 +3768,80 @@ rc_t CC KMain(int argc, char *argv[]) {
             }
         }
 
-        if (prms.xml) {
+        if (prms.xml)
             OUTMSG(("<%s>\n", root));
-        }
 
-        if (MainHasTest(&prms, eNgs)) {
+        if (MainHasTest(&prms, eNgs))
             _MainPrintNgsInfo(&prms);
-        }
 
         MainPrintVersion(&prms);
 
         if (MainHasTest(&prms, eCfg)) {
             rc_t rc2 = MainPrintConfig(&prms);
-            if (rc == 0 && rc2 != 0) {
+            if (rc == 0 && rc2 != 0)
                 rc = rc2;
-            }
         }
 
-        if (MainHasTest(&prms, eOS)) {
+        if (MainHasTest(&prms, eOS))
             PrintOS(prms.xml);
-        }
 
-        if (MainHasTest(&prms, eAscp)) {
+        if (MainHasTest(&prms, eAscp))
             MainPrintAscp(&prms);
-        }
 
-        if (MainHasTest(&prms, eNetwork)) {
+        if (MainHasTest(&prms, eNetwork))
             MainNetwotk(&prms, NULL, prms.xml ? "  " : "", eol);
-        }
 
         if (!prms.full) {
             rc_t rc2 = MainQuickCheck(&prms);
-            if (rc == 0 && rc2 != 0) {
+            if (rc == 0 && rc2 != 0)
                 rc = rc2;
-            }
-        }
-
-        if (rc == 0) {
-            rc = ArgsOptionCount(args, OPTION_NO_RFS, &pcount);
-            if (rc) {
-                LOGERR(klogErr, rc,
-                    "Failure to get '" OPTION_NO_RFS "' argument");
-            }
-            else {
-                if (pcount > 0) {
-                    prms.noRfs = true;
-                }
-            }
-        }
-
-        if (rc == 0) {
-            rc = ArgsOptionCount(args, OPTION_NO_VDB, &pcount);
-            if (rc) {
-                LOGERR(klogErr, rc,
-                    "Failure to get '" OPTION_NO_VDB "' argument");
-            }
-            else {
-                if (pcount > 0) {
-                    prms.noVDBManagerPathType = true;
-                }
-            }
-        }
-
-        if (rc == 0) {
-            rc = ArgsOptionCount(args, OPTION_REC, &pcount);
-            if (rc) {
-                LOGERR(klogErr, rc, "Failure to get '" OPTION_REC "' argument");
-            }
-            else {
-                if (pcount > 0) {
-                    prms.recursive = true;
-                }
-            }
         }
 
         if (rc == 0) {
             rc = ArgsOptionCount(args, OPTION_LIB, &pcount);
-            if (rc != 0) {
+            if (rc != 0)
                 LOGERR(klogErr, rc, "Failure to get '" OPTION_LIB "' argument");
-            }
             else {
                 int i = 0;
                 for (i = 0; i < pcount; ++i) {
                     const char * lib = NULL;
                     rc = ArgsOptionValue
                         ( args, OPTION_LIB, i, ( const void ** ) & lib );
-                    if ( rc != 0 ) {
+                    if ( rc != 0 )
                         LOGERR(klogErr, rc,
                             "Failure to get '" OPTION_LIB "' argument");
-                    }
-                    else {
+                    else
                         PrintLib ( lib, prms.xml );
-                    }
                 }
             }
         }
 
-        if ( params == 0 && MainHasTest ( & prms, eNetwork ) ) {
+        if ( params == 0 && MainHasTest ( & prms, eNetwork ) )
             MainNetwotk ( & prms, "SRR000001", prms . xml ? "  " : "", eol );
-        }
+
+        MainRepositories ( & prms, "  " );
+
         for (i = 0; i < params; ++i) {
             const char *name = NULL;
             rc3 = ArgsParamValue(args, i, (const void **)&name);
             if (rc3 == 0) {
                 rc_t rc2 = Quitting();
                 if (rc2 != 0) {
-                    if (rc == 0 && rc2 != 0) {
+                    if (rc == 0 && rc2 != 0)
                         rc = rc2;
-                    }
                     break;
                 }
                 ReportResetObject(name);
                 rc2 = MainExec(&prms, NULL, name);
-                if (rc == 0 && rc2 != 0) {
+                if (rc == 0 && rc2 != 0)
                     rc = rc2;
-                }
             }
         }
-        if (rc == 0 && rc3 != 0) {
+        if (rc == 0 && rc3 != 0)
             rc = rc3;
-        }
 
-        if (MainHasTest(&prms, eNcbiReport)) {
+        if (MainHasTest(&prms, eNcbiReport))
             ReportForceFinalize();
-        }
 
         if (!prms.full) {
             OUTMSG(("\nAdd -F option to try all the tests."));
diff --git a/tools/vdb-config/configure.cpp b/tools/vdb-config/configure.cpp
index 0d2438b..68a0a1a 100644
--- a/tools/vdb-config/configure.cpp
+++ b/tools/vdb-config/configure.cpp
@@ -83,15 +83,20 @@ class CConfigurator : CNoncopyable {
                     m_Cfg.UpdateNode(name.c_str(), "$(HOME)/ncbi");
                 }
             }
+            else {
+                const string canonical
+                    ( m_Dir . Canonical ( node . GetCString () ) );
+                if ( ! canonical . empty () )
+                    m_Cfg.UpdateNode ( name, canonical );
+            }
         }
         rc_t rc = 0;
         if (fix) {
             const string name("/repository/site/disabled");
             if (m_Cfg.NodeExists(name)) {
                 rc_t r2 = m_Cfg.UpdateNode(name.c_str(), "false");
-                if (r2 != 0 && rc == 0) {
+                if (r2 != 0 && rc == 0)
                     rc = r2;
-                }
             }
         }
         const KRepositoryMgr *mgr = NULL;
@@ -100,18 +105,16 @@ class CConfigurator : CNoncopyable {
         memset(&repositories, 0, sizeof repositories);
         if (rc == 0) {
             rc = KRepositoryMgrRemoteRepositories(mgr, &repositories);
-            if (rc == 0) {
+            if (rc == 0)
                 KRepositoryVectorWhack(&repositories);
-            }
             else if
                 (rc == SILENT_RC(rcKFG, rcNode, rcOpening, rcPath, rcNotFound))
             {
                 rc = m_Cfg.CreateRemoteRepositories();
             }
         }
-        if ( rc == 0 && fix ) {
+        if ( rc == 0 && fix )
             rc = m_Cfg.CreateRemoteRepositories(fix);
-        }
         if (rc == 0) {
 
             m_Cfg . FixResolverCgiNodes ( );
@@ -120,34 +123,45 @@ class CConfigurator : CNoncopyable {
             rc = KRepositoryMgrUserRepositories(mgr, &repositories);
             if (rc == 0) {
                 uint32_t len = 0;
-                if (rc == 0) {
+                if (rc == 0)
                     len = VectorLength(&repositories);
-                }
-                if (len == 0) {
+                if (len == 0)
                     noUser = true;
-                }
                 else {
                     uint32_t i = 0;
                     noUser = true;
                     for (i = 0; i < len; ++i) {
-                        const KRepository *repo
-                            = static_cast<const KRepository*>
-                                (VectorGet(&repositories, i));
+                        KRepository *repo = static_cast<KRepository*>
+                            (VectorGet(&repositories, i));
                         if (repo != NULL) {
-                            char buffer[PATH_MAX] = "";
+                            char name[PATH_MAX] = "";
                             size_t size = 0;
                             rc = KRepositoryName(repo,
-                                buffer, sizeof buffer, &size);
+                                name, sizeof name, &size);
                             if (rc == 0) {
                                 const char p[] = "public";
-                                if (strcase_cmp(p, sizeof p - 1, buffer,
-                                    size, sizeof buffer) == 0)
+                                if (strcase_cmp(p, sizeof p - 1, name,
+                                    size, sizeof name) == 0)
                                 {
                                     noUser = false;
                                 }
                                 if (fix) {
-                                    rc = m_Cfg.CreateUserRepository
-                                        (buffer, fix);
+                                    rc = m_Cfg.CreateUserRepository (name, fix);
+                                }
+                            }
+
+                            char root[PATH_MAX] = "";
+                            rc = KRepositoryRoot ( repo,
+                                                   root, sizeof root, &size);
+                            if (rc == 0) {
+                                const string canonical
+                                    ( m_Dir . Canonical ( root ) );
+                                if ( ! canonical . empty () ) {
+                                    rc = KRepositorySetRoot ( repo,
+                                        canonical . c_str (),
+                                        canonical . size () );
+                                    if ( rc == 0 )
+                                        m_Cfg . Updated ();
                                 }
                             }
                         }
diff --git a/tools/vdb-config/util.cpp b/tools/vdb-config/util.cpp
index f01b63a..fdbbb33 100644
--- a/tools/vdb-config/util.cpp
+++ b/tools/vdb-config/util.cpp
@@ -326,67 +326,88 @@ rc_t CKConfig::CreateRemoteRepositories(bool fix) {
 }
 
 rc_t CKConfig::CreateUserRepository(string repoName, bool fix) {
-    if (repoName.size() == 0) {
+    if (repoName.size() == 0)
         repoName = "public";
-    }
+
     CString cRoot(ReadString("/repository/user/default-path"));
+
     string root;
-    if (cRoot.Empty()) {
+    if (cRoot.Empty())
         root = "$(HOME)/ncbi";
-    }
-    else {
+    else
         root = cRoot.GetString();
-    }
 
     std::ostringstream s;
     s << "/repository/user/" << (repoName == "public" ? "main" : "protected")
         << "/" << repoName;
     string repoNode(s.str());
     string name(repoNode + "/root");
+
     bool toFix = true;
-    if (fix) {
+    if (fix)
         toFix = !NodeExists(name);
-    }
+
     rc_t rc = 0;
-    if (toFix) {
+    if (toFix)
         rc = UpdateNode(name, (root + "/public").c_str());
-    }
 
-    rc_t r2 = UpdateNode(repoNode + "/apps/file/volumes/flat", "files");
-    if (r2 != 0 && rc == 0) {
-        rc = r2;
+    {
+        string name ( repoNode + "/apps/file/volumes/flat" );
+        if ( ! NodeExists ( name ) ) {
+            rc_t r2 = UpdateNode ( name, "files" );
+            if ( r2 != 0 && rc == 0 )
+                rc = r2;
+        }
     }
-
-    r2 = UpdateNode(repoNode + "/apps/sra/volumes/sraFlat", "sra");
-    if (r2 != 0 && rc == 0) {
-        rc = r2;
+    {
+        string name ( repoNode + "/apps/sra/volumes/sraFlat" );
+        if ( ! NodeExists ( name ) ) {
+            rc_t r2 = UpdateNode ( name, "sra" );
+            if ( r2 != 0 && rc == 0 )
+                rc = r2;
+        }
     }
 
-    if (repoName == "public") {
-        r2 = UpdateNode(repoNode + "/apps/nakmer/volumes/nakmerFlat", "nannot");
-        if (r2 != 0 && rc == 0) {
+    {
+        rc_t r2 = UpdateNode ( repoNode + "/cache-enabled", "true" );
+        if ( r2 != 0 && rc == 0 )
             rc = r2;
-        }
+    }
 
-        r2 = UpdateNode(repoNode + "/apps/nannot/volumes/nannotFlat", "nannot");
-        if (r2 != 0 && rc == 0) {
-            rc = r2;
-        }
+    if ( repoName != "public" )
+        return rc;
 
-        r2 = UpdateNode(repoNode + "/apps/refseq/volumes/refseq", "refseq");
-        if (r2 != 0 && rc == 0) {
-            rc = r2;
+    {
+        string name ( repoNode + "/apps/nakmer/volumes/nakmerFlat" );
+        if ( ! NodeExists ( name ) ) {
+            rc_t r2 = UpdateNode ( name, "nannot" );
+            if ( r2 != 0 && rc == 0 )
+                rc = r2;
         }
-
-        r2 = UpdateNode(repoNode + "/apps/wgs/volumes/wgsFlat", "wgs");
-        if (r2 != 0 && rc == 0) {
-            rc = r2;
+    }
+    {
+        string name ( repoNode + "/apps/nannot/volumes/nannotFlat" );
+        if ( ! NodeExists ( name ) ) {
+            rc_t r2 = UpdateNode ( name, "nannot" );
+            if ( r2 != 0 && rc == 0 )
+                rc = r2;
         }
     }
-
-    r2 = UpdateNode(repoNode + "/cache-enabled", "true");
-    if (r2 != 0 && rc == 0) {
-        rc = r2;
+    {
+        string name ( repoNode + "/apps/refseq/volumes/refseq" );
+        if ( ! NodeExists ( name ) ) {
+            rc_t r2 = UpdateNode ( name, "refseq" );
+            if ( r2 != 0 && rc == 0 )
+                rc = r2;
+        }
+    }
+    {
+        string name ( repoNode + "/apps/wgs/volumes/wgsFlat" );
+        if ( ! NodeExists ( name ) ) {
+            rc_t r2 = UpdateNode ( name, "wgs" );
+            if ( r2 != 0 && rc == 0 )
+                rc = r2;
+        }
     }
 
     return rc;
@@ -626,6 +647,20 @@ rc_t CKDirectory::CheckPublicAccess(const CString &path, bool verbose) const {
     return CheckAccess(path, updated, false, verbose);
 }
 
+std::string CKDirectory::Canonical ( const char * path ) const {
+    char resolved [ PATH_MAX ] = "";
+    rc_t rc =
+        KDirectoryResolvePath ( m_Self, true, resolved, sizeof resolved, path );
+    if ( rc != 0 )
+        return "";
+    size_t size  = string_measure ( path, NULL );
+    if ( string_cmp
+        ( path, size, resolved, string_measure ( resolved, NULL ), size ) == 0 )
+        return "";
+    return resolved;
+}
+
+
 rc_t CKConfig::UpdateNode(bool verbose,
     const char *value, const char *name, ...)
 {
@@ -657,6 +692,7 @@ rc_t CKConfig::FixResolverCgiNodes ( void ) {
     return rc;
 }
 
+
 CApp::CApp(const CKDirectory &dir, const CKConfigNode &rep,
         const string &root, const string &name)
     : m_HasVolume(false)
diff --git a/tools/vdb-config/util.hpp b/tools/vdb-config/util.hpp
index e657df9..2a65856 100644
--- a/tools/vdb-config/util.hpp
+++ b/tools/vdb-config/util.hpp
@@ -174,6 +174,7 @@ public:
         return IsDirectory(path.c_str());
     }
     bool IsDirectory(const char *path, ...) const;
+    std::string Canonical ( const char * path ) const;
 private:
     bool Exists(const char *path) const
     {   return KDirectoryPathType(m_Self, path) != kptNotFound; }
@@ -264,6 +265,7 @@ public:
     { KConfigRelease(m_Self); }
     KConfig* Get(void) const { return m_Self; }
     void Reload(bool verbose = false);
+    void Updated ( void ) { m_Updated = true; }
     rc_t Commit(void) const;
     const KConfigNode* OpenNodeRead(const char *path, ...) const;
     bool IsRemoteRepositoryDisabled(void) const;
@@ -286,6 +288,9 @@ public:
     rc_t UpdateNode(const std::string &path, const char *buffer) {
         return UpdateNode(path.c_str(), buffer);
     }
+    rc_t UpdateNode(const std::string &path, const std::string &buffer) {
+        return UpdateNode(path.c_str(), buffer.c_str());
+    }
     rc_t CreateRemoteRepositories(bool fix = false);
     rc_t CreateUserRepository(std::string name = "", bool fix = false);
     const String* ReadString(const char *path) const;
diff --git a/tools/vdb-config/vdb-config-model.cpp b/tools/vdb-config/vdb-config-model.cpp
index 3b5815a..184ff2b 100644
--- a/tools/vdb-config/vdb-config-model.cpp
+++ b/tools/vdb-config/vdb-config-model.cpp
@@ -24,13 +24,15 @@
 *
 */
 
-#include "vdb-config-model.hpp" // vdbconf_model
-
+#include <klib/text.h> /* string_cmp */
 #include <klib/vector.h> /* Vector */
 
 #include <cstring> // memset
 
 #include <climits> /* PATH_MAX */
+
+#include "vdb-config-model.hpp" // vdbconf_model
+
 #ifndef PATH_MAX
 #define PATH_MAX 4096
 #endif
@@ -44,6 +46,7 @@ const int32_t vdbconf_model::kInvalidRepoId = -2;
 std::string vdbconf_model::native_to_internal( const std::string &s ) const
 {
     std::string res = "";
+
     VPath * temp_v_path;
     rc_t rc = VFSManagerMakeSysPath ( _vfs_mgr, &temp_v_path, s.c_str() );
     if ( rc == 0 )
@@ -51,10 +54,24 @@ std::string vdbconf_model::native_to_internal( const std::string &s ) const
         size_t written;
         char buffer[ PATH_MAX ];
         rc = VPathReadPath ( temp_v_path, buffer, sizeof buffer, &written );
-        if ( rc == 0 )
-            res.assign( buffer, written );
+        if ( rc == 0 ) {
+            char resolved [ PATH_MAX ] = "";
+            rc_t rc = KDirectoryResolvePath
+                ( _dir, true, resolved, sizeof resolved, buffer );
+            if ( rc == 0 ) {
+                if ( string_cmp ( buffer, written, resolved,
+                            string_measure ( resolved, NULL ), PATH_MAX ) != 0 )
+                {   // make sure the path is canonic
+                    res = resolved;
+                }
+                else {
+                    res.assign( buffer, written );
+                }
+            }
+        }
         VPathRelease ( temp_v_path );
     }
+
     return res;
 }
 
diff --git a/tools/vdb-config/vdb-config.c b/tools/vdb-config/vdb-config.c
index 2b0a917..cec49c0 100644
--- a/tools/vdb-config/vdb-config.c
+++ b/tools/vdb-config/vdb-config.c
@@ -1385,9 +1385,8 @@ static rc_t ShowFiles(const KConfig* cfg, const Params* prm) {
 
         for (i = 0; i < count && rc == 0; ++i) {
             const char* name = NULL;
-            if (rc == 0) {
+            if (rc == 0)
                 rc = KNamelistGet(names, i, &name);
-            }
             if (rc == 0) {
                 OUTMSG(("%s\n", name));
                 hasAny = true;
@@ -1619,64 +1618,95 @@ rc_t CC KMain(int argc, char* argv[]) {
 
     Params prm;
     KConfig* cfg = NULL;
+    bool configured = false;
 
-    if (rc == 0) {
+    if (rc == 0)
         rc = ParamsConstruct(argc, argv, &prm);
+
+    if (rc == 0 && prm.showMultiple && prm.xml)
+        OUTMSG(("<VdbConfig>\n"));
+
+    if (rc == 0) {
+        if (prm.modeConfigure) {
+            rc = configure(prm.configureMode);
+            configured = true;
+        }
     }
 
     if (rc == 0) {
         const KDirectory *d = NULL;
+        KDirectory * n = NULL;
+        rc = KDirectoryNativeDir ( & n );
         if (prm.cfg_dir != NULL) {
-            KDirectory *n = NULL;
-            rc = KDirectoryNativeDir(&n);
             if (rc == 0) {
                 rc = KDirectoryOpenDirRead(n, &d, false, prm.cfg_dir);
                 DISP_RC2(rc, "while opening", prm.cfg_dir);
             }
-            RELEASE(KDirectory, n);
         }
         if (rc == 0) {
             rc = KConfigMake(&cfg, d);
             DISP_RC(rc, "while calling KConfigMake");
         }
-        RELEASE(KDirectory, d);
-    }
 
-    if (rc == 0 && prm.showMultiple && prm.xml) {
-        OUTMSG(("<VdbConfig>\n"));
-    }
-
-    if (rc == 0) {
-        if (prm.modeConfigure) {
-            rc = configure(prm.configureMode);
-        }
-        else if (prm.ngc) {
-            rc = ImportNgc(cfg, &prm);
+        if ( rc == 0 && ! configured ) {
+            char home [ PATH_MAX ] = "";
+            size_t written = 0;
+            rc = KConfig_Get_Default_User_Path ( cfg, home, sizeof home,
+                & written );
+            if ( rc == 0 ) {
+                char resolved [ PATH_MAX ] = "";
+                rc_t r2 = KDirectoryResolvePath ( n, true, resolved,
+                    sizeof resolved, home );
+                if ( r2 == 0 ) {
+                    size_t size  = string_measure ( home, NULL );
+                    if ( string_cmp ( home, size, resolved,
+                        string_measure ( resolved, NULL ), size ) != 0 )
+                    {
+                        r2 = KConfig_Set_Default_User_Path ( cfg, resolved );
+                        if ( r2 == 0 ) {
+                            KConfigCommit ( cfg );
+                            KConfigRelease ( cfg );
+                            rc = KConfigMake ( &cfg, d );
+                            DISP_RC ( rc, "while re-calling KConfigMake" );
+                        }
+                    }
+                }
+            }
+            else
+                rc = 0;
         }
-        else if (prm.modeSetNode) {
-            rc_t rc3 = SetNode(cfg, &prm);
-            if (rc3 != 0 && rc == 0) {
-                rc = rc3;
+
+        RELEASE ( KDirectory, d );
+        RELEASE ( KDirectory, n );
+
+        if ( ! configured ) {
+            if (prm.ngc)
+                rc = ImportNgc(cfg, &prm);
+            else if (prm.modeSetNode) {
+                rc_t rc3 = SetNode(cfg, &prm);
+                if (rc3 != 0 && rc == 0)
+                    rc = rc3;
             }
         }
+
         if (prm.proxy != NULL || prm.proxyDisabled != eUndefined) {
             rc_t rc3 = SetProxy(cfg, &prm);
-            if (rc3 != 0 && rc == 0) {
+            if (rc3 != 0 && rc == 0)
                 rc = rc3;
-            }
         }
+
         if (prm.modeShowCfg) {
             rc_t rc3 = ShowConfig(cfg, &prm);
-            if (rc3 != 0 && rc == 0) {
+            if (rc3 != 0 && rc == 0)
                 rc = rc3;
-            }
         }
+
         if (prm.modeShowFiles) {
             rc_t rc3 = ShowFiles(cfg, &prm);
-            if (rc3 != 0 && rc == 0) {
+            if (rc3 != 0 && rc == 0)
                 rc = rc3;
-            }
         }
+
         if (prm.modeShowLoadPath) {
             const char* path = NULL;
             rc_t rc3 = KConfigGetLoadPath(cfg, &path);

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/sra-sdk.git



More information about the debian-med-commit mailing list