1#!/usr/local/bin/perl
2
3# Test that programs accept and reject argument of '-' (for reading
4# data from stdin, rather than from files) as they're supposed to.
5#
6# Usage:   ./i17-stdin.pl <builddir> <srcdir> <tmpfile prefix>
7# Example: ./i17-stdin.pl ..         ..       tmpfoo
8#
9# SRE, Wed Oct 27 13:05:10 2010 [Janelia]
10
11
12BEGIN {
13    $builddir  = shift;
14    $srcdir    = shift;
15    $tmppfx    = shift;
16}
17
18$verbose = 0;
19
20# The test makes use of the following files:
21#
22# $model1.hmm           <hmmfile>  Single RRM_1 model
23# $model2.hmm           <hmmfile>  Single Caudal_act model
24# $nmodel1.hmm          <hmmfile>  Single 3box model (DNA)
25# $nmodel2.hmm          <hmmfile>  Single PSE model (DNA)
26# $model1.sto           <msafile>  Single RRM_1 alignment
27# $model2.sto           <msafile>  Single Caudal_act alignment
28
29# It creates the following files:
30# $tmppfx.hmm           <hmmdb>    2 models, RRM_1 + Caudal_act
31# $tmppfx.nhmm          <hmmdb>    2 DNA models, 3box and PSE
32# $tmppfx.sto           <msadb>    2 MSAs, RRM_1 + Caudal_act
33# $tmppfx.hmm.h3{mifp}             hmmpress auxfiles for .hmm file
34# $tmppfx.fa1           <seqfile>  1 consensus seq  from RRM_1 model
35# $tmppfx.fa2           <seqfile>  2 consensus seqs, one from RRM_1 and one from Caudal_act
36# $tmppfx.fa10          <seqfile> 10 seqs from RRM_1 model
37# $tmppfx.db            <seqdb>   10 RRM_1 + 10 Caudal_act + 100 random seqs
38# $tmppfx.ndb           <seqdb>   2 PSE + 2 3box + 6 random seqs
39# $tmppfx.key           <keyfile>  "Caudal_act" in a file, to test hmmfetch -f
40#
41
42# All models assumed to be in testsuite subdirectory.
43$model1   = "RRM_1";
44$model2   = "Caudal_act";
45$nmodel1  = "3box";
46$nmodel2  = "PSE";
47
48@h3progs =  ("hmmalign", "hmmbuild", "hmmconvert", "hmmemit", "hmmfetch", "hmmpress", "hmmscan", "hmmsearch", "hmmstat", "jackhmmer", "nhmmer", "phmmer");
49@eslprogs = ("esl-shuffle");
50
51# Verify that we have all the executables and datafiles we need for the test.
52foreach $h3prog  (@h3progs) { if (! -x "$builddir/src/$h3prog")             { die "FAIL: didn't find $h3prog executable in $builddir/src\n";              } }
53foreach $eslprog (@eslrogs) { if (! -x "$builddir/easel/miniapps/$eslprog") { die "FAIL: didn't find $eslprog executable in $builddir/easel/miniapps\n";  } }
54
55if (! -r "$srcdir/testsuite/$model1.hmm")  { die "FAIL: can't read profile $model1.hmm in $srcdir/testsuite\n"; }
56if (! -r "$srcdir/testsuite/$model2.hmm")  { die "FAIL: can't read profile $model2.hmm in $srcdir/testsuite\n"; }
57if (! -r "$srcdir/testsuite/$nmodel1.hmm") { die "FAIL: can't read profile $nmodel1.hmm in $srcdir/testsuite\n"; }
58if (! -r "$srcdir/testsuite/$nmodel2.hmm") { die "FAIL: can't read profile $nmodel2.hmm in $srcdir/testsuite\n"; }
59
60if (! -r "$srcdir/testsuite/$model1.sto")  { die "FAIL: can't read msa $model1.sto in $srcdir/testsuite\n"; }
61if (! -r "$srcdir/testsuite/$model2.sto")  { die "FAIL: can't read msa $model2.sto in $srcdir/testsuite\n"; }
62if (! -r "$srcdir/testsuite/$nmodel1.sto") { die "FAIL: can't read msa $nmodel1.sto in $srcdir/testsuite\n"; }
63if (! -r "$srcdir/testsuite/$nmodel2.sto") { die "FAIL: can't read msa $nmodel2.sto in $srcdir/testsuite\n"; }
64
65
66`cat $srcdir/testsuite/$model1.hmm  $srcdir/testsuite/$model2.hmm  > $tmppfx.hmm`;  if ($?) { die "FAIL: cat\n"; }
67`cat $srcdir/testsuite/$nmodel1.hmm $srcdir/testsuite/$nmodel2.hmm > $tmppfx.nhmm`; if ($?) { die "FAIL: cat\n"; }
68`$builddir/src/hmmpress $tmppfx.hmm`;                                               if ($?) { die "FAIL: hmmpress\n"; }
69
70`cat $srcdir/testsuite/$model1.sto $srcdir/testsuite/$model2.sto > $tmppfx.sto`;    if ($?) { die "FAIL: cat\n"; }
71
72`$builddir/src/hmmemit -c $srcdir/testsuite/$model1.hmm > $tmppfx.fa1`;             if ($?) { die "FAIL: hmmemit -c\n"; }
73`cat $tmppfx.fa1 > $tmppfx.fa2`;                                                    if ($?) { die "FAIL: cat\n"; }
74`$builddir/src/hmmemit -c $srcdir/testsuite/$model2.hmm >> $tmppfx.fa2`;            if ($?) { die "FAIL: hmmemit -c\n"; }
75
76`$builddir/src/hmmemit -N10 $srcdir/testsuite/$model1.hmm > $tmppfx.fa10`;          if ($?) { die "FAIL: hmmemit\n"; }
77
78`$builddir/src/hmmemit -p -N10 $srcdir/testsuite/$model1.hmm > $tmppfx.db`;         if ($?) { die "FAIL: hmmemit\n"; }
79`$builddir/src/hmmemit -p -N10 $srcdir/testsuite/$model2.hmm >> $tmppfx.db`;        if ($?) { die "FAIL: hmmemit\n"; }
80`$builddir/easel/miniapps/esl-shuffle -G -N100 -L 400 --amino >> $tmppfx.db`;       if ($?) { die "FAIL: esl-shuffle\n"; }
81
82`$builddir/src/hmmemit -p -N2 -L2000 --glocal $srcdir/testsuite/$nmodel1.hmm >  $tmppfx.ndb`; if ($?) { die "FAIL: hmmemit\n"; }
83`$builddir/src/hmmemit -p -N2 -L2000 --glocal $srcdir/testsuite/$nmodel2.hmm >> $tmppfx.ndb`; if ($?) { die "FAIL: hmmemit\n"; }
84`$builddir/easel/miniapps/esl-shuffle -G -N6 -L 2000 --dna                   >> $tmppfx.ndb`; if ($?) { die "FAIL: esl-shuffle\n"; }
85
86`echo $model1    > $tmppfx.key`;                                                    if ($?) { die "FAIL: cat\n"; }
87`echo $model2   >> $tmppfx.key`;                                                    if ($?) { die "FAIL: cat\n"; }
88
89
90################################################################
91# hmmalign
92#   reject - - case
93################################################################
94
95$tag  = "hmmalign";    $prog = "$builddir/src/$tag";
96$tag1 = "<hmmfile>";   $arg1 = "$srcdir/testsuite/$model1.hmm";
97$tag2 = "<seqfile>";   $arg2 = "$tmppfx.fa10";
98if ($verbose) { print "$tag...\n"; }
99
100`$prog $arg1 $arg2         > $tmppfx.out1`;   if ($?) { die "FAIL: $tag $tag1 $tag2\n"; }
101`cat $arg1 | $prog - $arg2 > $tmppfx.out2`;   if ($?) { die "FAIL: $tag - $tag2\n"; }
102`cat $arg2 | $prog $arg1 - > $tmppfx.out3`;   if ($?) { die "FAIL: $tag $tag1 -\n"; }
103
104`diff -b $tmppfx.out1 $tmppfx.out2 2>&1 > /dev/null`; if ($?) { die "FAIL: $tag results differ if $tag1 comes through stdin\n"; }
105`diff -b $tmppfx.out1 $tmppfx.out3 2>&1 > /dev/null`; if ($?) { die "FAIL: $tag results differ if $tag2 comes through stdin\n"; }
106
107$output = `cat $arg1 $arg2 | $prog - - 2>&1`;
108if (!$?) { die "FAIL: $tag should fail on double - -\n"; }
109if ($output !~ /^\nERROR: Either <hmmfile> or <seqfile>/) { die "FAIL: $tag didn't give expected error message for the - - case.\n"; }
110
111
112################################################################
113# hmmbuild
114#    don't diff HMM files, they may fail because of DATE field
115#    reject - for <hmmfile>: can't send it to stdout.
116################################################################
117
118$tag  = "hmmbuild";       $prog = "$builddir/src/$tag";
119$tag1 = "<msafile>";      $arg1 = "$tmppfx.sto";
120if ($verbose) { print "$tag...\n"; }
121
122`$prog $tmppfx.hmm.out1 $arg1                              | grep -v "^#" > $tmppfx.out1`;   if ($?) { die "FAIL: $tag <hmmfile> $tag1 \n"; }
123`cat $arg1 | $prog --informat stockholm $tmppfx.hmm.out2 - | grep -v "^#" > $tmppfx.out2`;   if ($?) { die "FAIL: $tag <hmmfile> -\n"; }
124`diff -b $tmppfx.out1     $tmppfx.out2     2>&1 > /dev/null`; if ($?) { die "FAIL: $tag results differ if $tag1 comes through stdin\n"; }
125
126$output = `$prog - $arg1`;
127if (!$?) { die "FAIL: $tag should reject - for <hmmfile_out>\n"; }
128
129################################################################
130# hmmconvert
131################################################################
132
133$tag  = "hmmconvert";     $prog = "$builddir/src/$tag";
134$tag1 = "<hmmfile>";      $arg1 = "$tmppfx.hmm";
135if ($verbose) { print "$tag...\n"; }
136
137`$prog $arg1         > $tmppfx.out1`;   if ($?) { die "FAIL: $tag $tag1\n"; }
138`cat $arg1 | $prog - > $tmppfx.out2`;   if ($?) { die "FAIL: $tag -\n"; }
139
140`diff -b $tmppfx.out1 $tmppfx.out2 2>&1 > /dev/null`;
141if ($?) { die "FAIL: $tag results differ if $tag1 comes through stdin\n"; }
142
143################################################################
144# hmmemit
145#    need to pass fixed RNG seed to be able to diff outputs
146################################################################
147
148$tag  = "hmmemit";      $prog = "$builddir/src/$tag";
149$tag1 = "<hmmfile>";    $arg1 = "$tmppfx.hmm";
150if ($verbose) { print "$tag...\n"; }
151
152`$prog --seed 42 $arg1         > $tmppfx.out1`;   if ($?) { die "FAIL: $tag $tag1\n"; }
153`cat $arg1 | $prog --seed 42 - > $tmppfx.out2`;   if ($?) { die "FAIL: $tag -\n"; }
154
155`diff -b $tmppfx.out1 $tmppfx.out2 2>&1 > /dev/null`;
156if ($?) { die "FAIL: $tag results differ if $tag1 comes through stdin\n"; }
157
158
159################################################################
160# hmmfetch
161#    need to check all three use modes, including -f and --index
162#    --index rejects -
163#    w/ -f, only one of <hmmfile>, <keyfile> can be -
164#    -f fetches in different orders depending on whether file is
165#      indexed or not, so <keyfile> must be constructed to give
166#      same fetch order either way.
167################################################################
168
169$tag  = "hmmfetch";    $prog = "$builddir/src/$tag";
170$tag1 = "<hmmfile>";   $arg1 = "$tmppfx.hmm";
171$tag2 = "<keyfile>";   $arg2 = "$tmppfx.key";
172if ($verbose) { print "$tag...\n"; }
173
174`$prog $arg1 Caudal_act         > $tmppfx.out1`;          if ($?) { die "FAIL: $tag $tag1\n"; }
175`cat $arg1 | $prog - Caudal_act > $tmppfx.out2`;          if ($?) { die "FAIL: $tag -\n"; }
176`diff -b $tmppfx.out1 $tmppfx.out2 2>&1 > /dev/null`;  if ($?) { die "FAIL: $tag results differ if $tag1 comes through stdin\n"; }
177
178`$prog -f $arg1 $arg2           > $tmppfx.out1`;          if ($?) { die "FAIL: $tag -f $tag1 $tag2\n"; }
179`cat $arg1 | $prog -f - $arg2   > $tmppfx.out2`;          if ($?) { die "FAIL: $tag -f - $tag2\n"; }
180`cat $arg2 | $prog -f $arg1 -   > $tmppfx.out3`;          if ($?) { die "FAIL: $tag -f $tag1 -\n"; }
181`diff -b $tmppfx.out1 $tmppfx.out2 2>&1 > /dev/null`;  if ($?) { die "FAIL: $tag -f results differ if $tag1 comes through stdin\n"; }
182`diff -b $tmppfx.out1 $tmppfx.out3 2>&1 > /dev/null`;  if ($?) { die "FAIL: $tag -f results differ if $tag2 comes through stdin\n"; }
183
184$output = `cat $arg1 $arg2 | $prog -f - - 2>&1`;
185if (! $?) { die "FAIL: $tag should have failed on double - -\n"; }
186if ($output !~ /^Either <hmmfile> or <keyfile>/) { die "FAIL: $tag didn't give expected error message for the - - case.\n"; }
187
188`$prog --index $arg1            > $tmppfx.out1`;   if ($?)   { die "FAIL: $tag --index $tag1\n"; }
189$output = `cat $arg1 | $prog --index - 2>&1`;      if (! $?) { die "FAIL: $tag should reject - for <hmmfile> when using --index\n"; }
190if ($output !~ /^Can't use - with --index/) { die "FAIL: $tag didn't give expected error message for the - - case.\n"; }
191
192################################################################
193# hmmpress
194#    rejects - argument.
195################################################################
196
197$tag  = "hmmpress";         $prog = "$builddir/src/$tag";
198$tag1 = "<hmmfile>";        $arg1 = "$tmppfx.hmm";
199if ($verbose) { print "$tag...\n"; }
200
201$output = `cat $arg1 | $prog - 2>&1`;        if (! $?) { die "FAIL: $tag should reject - for <hmmfile>\n"; }
202if ($output !~ /^\nError: Can't use - for <hmmfile>/) { die "FAIL: $tag didn't give expected error message.\n"; }
203
204#################################################################
205# hmmscan.
206#     rejects - for <hmmfile>, because it must be hmmpress'ed.
207#################################################################
208
209$tag  = "hmmscan";         $prog = "$builddir/src/$tag";
210$tag1 = "<hmmdb>";         $arg1 = "$tmppfx.hmm";
211$tag2 = "<seqfile>";       $arg2 = "$tmppfx.fa2";
212if ($verbose) { print "$tag...\n"; }
213
214`$prog $arg1 $arg2         | grep -v "^#" > $tmppfx.out1`;   if ($?) { die "FAIL: $tag $tag1 $tag2\n"; }
215`cat $arg2 | $prog $arg1 - | grep -v "^#" > $tmppfx.out2`;   if ($?) { die "FAIL: $tag $tag1 -\n"; }
216
217`diff -b $tmppfx.out1 $tmppfx.out2 2>&1 > /dev/null`;
218if ($?) { die "FAIL: $tag results differ if $arg2 comes from stdin\n"; }
219
220$output = `cat $arg1 | $prog - $arg2 2>&1`;
221if (! $?) { die "FAIL: $tag should reject - for $tag1\n"; }
222if ($output !~ /^hmmscan cannot read/) { die "FAIL: hmmscan didn't give expected error message\n"; }
223
224
225#################################################################
226# hmmsearch
227#      reject - - case
228#      reject <seqdb> as - on multiquery
229#################################################################
230# note that the grep -v "^#" removes lines that would make diffs fail,
231# like query name and cpu time.
232
233$tag  = "hmmsearch";         $prog = "$builddir/src/$tag";
234$tag1 = "<hmmfile>";         $arg1 = "$srcdir/testsuite/$model1.hmm";   $arg1b = "$tmppfx.hmm";
235$tag2 = "<seqdb>";           $arg2 = "$tmppfx.db";
236if ($verbose) { print "$tag...\n"; }
237
238`$prog $arg1 $arg2          | grep -v "^#" > $tmppfx.out1`;  if ($?) { die "FAIL: $tag $tag1 $tag2\n"; }
239`cat $arg1 | $prog - $arg2  | grep -v "^#" > $tmppfx.out2`;  if ($?) { die "FAIL: $tag - $tag2\n"; }
240`cat $arg2 | $prog $arg1 -  | grep -v "^#" > $tmppfx.out3`;  if ($?) { die "FAIL: $tag $tag1 -\n"; }
241
242`diff -b $tmppfx.out1 $tmppfx.out2 2>&1 > /dev/null`;  if ($?) { die "FAIL: $prog results differ if $tag1 comes through stdin\n"; }
243`diff -b $tmppfx.out1 $tmppfx.out3 2>&1 > /dev/null`;  if ($?) { die "FAIL: $prog results differ if $tag2 comes through stdin\n"; }
244
245$output = `cat $arg1 $arg2 | $prog - - 2>&1`;    if (! $?) { die "FAIL: $prog should have failed on double - -\n"; }
246if ($output !~ /^Either <hmmfile> or <seqdb>/) { die "FAIL: $prog didn't give expected error message for the - - case.\n"; }
247
248$output = `cat $arg2 | $prog $arg1b - 2>&1`;     if (! $?) { die "FAIL: $prog should fail on multiquery $tag1, stdin $tag2.\n"; }
249
250
251################################################################
252# hmmstat
253################################################################
254
255$tag  = "hmmstat";        $prog = "$builddir/src/$tag";
256$tag1 = "<hmmfile>";      $arg1 = "$tmppfx.hmm";
257if ($verbose) { print "$tag...\n"; }
258
259`$prog $arg1         > $tmppfx.out1`;                     if ($?) { die "FAIL: $tag $tag1\n"; }
260`cat $arg1 | $prog - > $tmppfx.out2`;                     if ($?) { die "FAIL: $tag -\n"; }
261
262`diff -b $tmppfx.out1 $tmppfx.out2 2>&1 > /dev/null`;  if ($?) { die "FAIL: $tag results differ if $tag1 comes through stdin\n"; }
263
264
265################################################################
266# jackhmmer
267#    <seqdb> can't be -, always needs to be rewindable
268################################################################
269
270$tag  = "jackhmmer";         $prog = "$builddir/src/$tag --enone -N2";
271$tag1 = "<seqfile>";         $arg1 = "$tmppfx.fa1";
272$tag2 = "<seqdb>";           $arg2 = "$tmppfx.db";
273if ($verbose) { print "$tag...\n"; }
274
275`$prog $arg1 $arg2          | grep -v "^#" > $tmppfx.out1`;  if ($?) { die "FAIL: $tag $tag1 $tag2\n"; }
276`cat $arg1 | $prog - $arg2  | grep -v "^#" > $tmppfx.out2`;  if ($?) { die "FAIL: $tag - $tag2\n"; }
277
278`diff -b $tmppfx.out1 $tmppfx.out2 2>&1 > /dev/null`;  if ($?) { die "FAIL: $prog results differ if $tag1 comes through stdin\n"; }
279
280$output = `cat $arg2 | $prog $arg1 - 2>&1`;           if (! $?) { die "FAIL: $prog should fail if <seqdb> is -\n"; }
281if ($output !~ /^jackhmmer cannot read <seqdb> from/) { die "FAIL: $prog didn't give expected error message\n"; }
282
283################################################################
284# nhmmer
285#    (like hmmsearch, but with DNA models)
286#      reject - - case
287#      reject <seqdb> as - on multiquery
288#################################################################
289
290$tag  = "nhmmer";            $prog = "$builddir/src/$tag";
291$tag1 = "<hmmfile>";         $arg1 = "$srcdir/testsuite/$nmodel1.hmm";   $arg1b = "$tmppfx.nhmm";
292$tag2 = "<seqdb>";           $arg2 = "$tmppfx.ndb";
293if ($verbose) { print "$tag...\n"; }
294
295`$prog $arg1 $arg2          | grep -v "^#" > $tmppfx.out1`;  if ($?) { die "FAIL: $tag $tag1 $tag2\n"; }
296`cat $arg1 | $prog - $arg2  | grep -v "^#" > $tmppfx.out2`;  if ($?) { die "FAIL: $tag - $tag2\n"; }
297`cat $arg2 | $prog $arg1 -  | grep -v "^#" > $tmppfx.out3`;  if ($?) { die "FAIL: $tag $tag1 -\n"; }
298
299`diff -b $tmppfx.out1 $tmppfx.out2 2>&1 > /dev/null`;  if ($?) { die "FAIL: $prog results differ if $tag1 comes through stdin\n"; }
300`diff -b $tmppfx.out1 $tmppfx.out3 2>&1 > /dev/null`;  if ($?) { die "FAIL: $prog results differ if $tag2 comes through stdin\n"; }
301
302$output = `cat $arg1 $arg2 | $prog - - 2>&1`;    if (! $?) { die "FAIL: $prog should have failed on double - -\n"; }
303if ($output !~ /^Either <query hmmfile|alignfile> or <seqdb>/) { die "FAIL: $prog didn't give expected error message for the - - case.\n"; }
304
305$output = `cat $arg2 | $prog $arg1b - 2>&1`;     if (! $?) { die "FAIL: $prog should fail on multiquery $tag1, stdin $tag2.\n"; }
306
307################################################################
308# phmmer: just like testing hmmsearch, but with query sequences instead of profiles
309# first: single query.
310################################################################
311
312$tag  = "phmmer";            $prog = "$builddir/src/$tag";
313$tag1 = "<seqfile>";         $arg1 = "$tmppfx.fa1";         $arg1b = "$tmppfx.fa2";
314$tag2 = "<seqdb>";           $arg2 = "$tmppfx.db";
315if ($verbose) { print "$tag...\n"; }
316
317`$prog $arg1 $arg2          | grep -v "^#" > $tmppfx.out1`;  if ($?) { die "FAIL: $tag $tag1 $tag2\n"; }
318`cat $arg1 | $prog - $arg2  | grep -v "^#" > $tmppfx.out2`;  if ($?) { die "FAIL: $tag - $tag2\n"; }
319`cat $arg2 | $prog $arg1 -  | grep -v "^#" > $tmppfx.out3`;  if ($?) { die "FAIL: $tag $tag1 -\n"; }
320
321`diff -b $tmppfx.out1 $tmppfx.out2 2>&1 > /dev/null`;  if ($?) { die "FAIL: $prog results differ if $tag1 comes through stdin\n"; }
322`diff -b $tmppfx.out1 $tmppfx.out3 2>&1 > /dev/null`;  if ($?) { die "FAIL: $prog results differ if $tag2 comes through stdin\n"; }
323
324$output = `cat $arg1 $arg2 | $prog - - 2>&1`;    if (! $?) { die "FAIL: $prog should have failed on double - -\n"; }
325if ($output !~ /^Either <seqfile> or <seqdb>/)   { die "FAIL: $prog didn't give expected error message for the - - case.\n"; }
326
327$output = `cat $arg2 | $prog $arg1b - 2>&1`;     if (! $?) { die "FAIL: $prog should fail on multiquery $tag1, stdin $tag2.\n"; }
328
329
330unlink <$tmppfx.out*>;
331unlink <$tmppfx.hmm*>;
332unlink "$tmppfx.nhmm";
333unlink "$tmppfx.sto";
334unlink "$tmppfx.fa1";
335unlink "$tmppfx.fa2";
336unlink "$tmppfx.fa10";
337unlink "$tmppfx.db";
338unlink "$tmppfx.ndb";
339unlink "$tmppfx.key";
340
341print "ok\n";
342exit 0;
343