source: trunk/test/unit/nl/tno/metagenomics/integration/TrashServiceTests.groovy @ 4

Last change on this file since 4 was 4, checked in by robert@…, 9 years ago

Implemented trash in order to prevent deletion of data

File size: 17.4 KB
Line 
1package nl.tno.metagenomics.integration
2
3import grails.test.*
4import nl.tno.metagenomics.*
5
6class TrashServiceTests extends GrailsUnitTestCase {
7        def trashService
8    Study trash
9       
10        protected void setUp() {
11        super.setUp()
12                mockDomain( Study );
13                mockDomain( Sample );
14                mockDomain( Assay );
15                mockDomain( AssaySample );
16                mockDomain( Run );
17                mockDomain( SequenceData );
18               
19                mockLogging( TrashService.class, true );
20               
21                trashService = new TrashService();
22
23                setupStudy();
24    }
25
26    protected void tearDown() {
27        super.tearDown()
28    }
29
30        protected void setupStudy() {
31                // Create a study trashcan
32                trash = new Study( name: "Trashcan", studyToken: "trashcan", trashcan: true );
33                trash.save(flush:true);
34               
35                // Setup a study with two assays, 4 samples
36                Study s = new Study( name: "Study 1", studyToken: "study1" );
37
38                s.save(flush:true);
39               
40                // Create two assays
41                Assay a1 = new Assay( id: 1, name: "Assay 1", assayToken: "assay1", study: s );
42                Assay a2 = new Assay( id: 2, name: "Assay 2", assayToken: "assay2", study: s );
43                Assay a3 = new Assay( id: 3, name: "Assay 3", assayToken: "assay3", study: s );
44                def assays = [a1, a2, a3];
45
46                assays.each { s.addToAssays( it ); it.save( flush: true ); }
47               
48                // Create four samples
49                Sample sa1 = new Sample( id: 1, name: "Sample 1a", sampleToken: "sample1a", study: s );
50                Sample sa2 = new Sample( id: 2, name: "Sample 1b", sampleToken: "sample1b", study: s );
51                Sample sa3 = new Sample( id: 3, name: "Sample 2a", sampleToken: "sample2a", study: s );
52                Sample sa4 = new Sample( id: 4, name: "Sample 2b", sampleToken: "sample2b", study: s );
53                Sample sa5 = new Sample( id: 5, name: "Sample 3a", sampleToken: "sample3a", study: s );
54                def samples = [sa1, sa2, sa3, sa4, sa5]
55               
56                samples.each { s.addToSamples( it ); it.save(flush:true); }
57               
58                s.save(flush:true);
59               
60                // Create desired combinations of samples and assays
61                // Such that: assay1 has 2 samples with data, assay2 has 1 sample with data and assay3 has no samples with data
62           AssaySample as1a = new AssaySample( oligoNumber: "123", tagSequence: "abc", sample: sa1, assay: a1 );
63           AssaySample as1b = new AssaySample( oligoNumber: "200", tagSequence: "def", sample: sa2, assay: a1 );
64           AssaySample as2a = new AssaySample( oligoNumber: "300", tagSequence: "ghi", sample: sa3, assay: a2 );
65           AssaySample as2b = new AssaySample( id: 12, sample: sa4, assay: a2);
66           AssaySample as3a = new AssaySample( sample: sa5, assay: a3);
67           def assaySamples= [as1a, as1b, as2a, as2b, as3a]
68
69           a1.addToAssaySamples( as1a ); sa1.addToAssaySamples( as1a );
70           as1a.save(flush:true);
71           
72           a1.addToAssaySamples( as1b ); sa2.addToAssaySamples( as1b );
73           as1b.save(flush:true);
74
75           a2.addToAssaySamples( as2a ); sa3.addToAssaySamples( as2a );
76           as2a.save(flush:true);
77
78           a2.addToAssaySamples( as2b ); sa4.addToAssaySamples( as2b );
79           as2b.save(flush:true);
80
81           a3.addToAssaySamples( as3a ); sa5.addToAssaySamples( as3a );
82           as3a.save(flush:true);
83           
84           assert as1a.sample.name == "Sample 1a"
85           
86           // Save samples and assays again
87           assays.each { it.save(flush:true); }
88           samples.each { it.save(flush:true); }
89           
90           // Create a single run
91           Run run = new Run( name: "abc" );
92           run.save(flush:true);
93
94           // Add sequencedata objects to as1a and as1b
95           SequenceData sd1 = new SequenceData( run: run, assaySample: as1a, sequenceFile: "fasta1", qualityFile: "qual1", numSequences: 100, averageQuality: 10.0 );
96           SequenceData sd2 = new SequenceData( run: run, assaySample: as1a, sequenceFile: "fasta2", qualityFile: "qual2", numSequences: 30, averageQuality: 14.0 );
97           SequenceData sd3 = new SequenceData( run: run, assaySample: as1b, sequenceFile: "fasta3", qualityFile: "qual3", numSequences: 2000, averageQuality: 17.0 );
98           def sequenceData = [sd1, sd2, sd3];
99           
100           run.addToSequenceData( sd1 );
101           run.addToSequenceData( sd2 );
102           run.addToSequenceData( sd3 );
103           
104           as1a.addToSequenceData( sd1 );
105           as1a.addToSequenceData( sd2 );
106           as1b.addToSequenceData( sd3 );
107           
108           run.save(flush:true); as1a.save(flush:true); as1b.save(flush:true);
109           sequenceData.each { it.save(flush:true); }
110        }
111       
112        protected void setupTrash() {
113                // Create a study trashcan
114                trash = Study.findByStudyToken( "trashcan" );
115               
116                // Create a trash assay
117                Assay a1 = new Assay( id: 100, name: "Trash Assay 1", assayToken: "trash_assay1", study: trash );
118                def assays = [a1];
119
120                assays.each { trash.addToAssays( it ); it.save( flush: true ); }
121               
122                // Create three samples, two originally also present in assay 1, the other one isn't
123                Sample sa1 = new Sample( id: 101, name: "Sample 1a", sampleToken: "tsample1a", study: trash );
124                Sample sa2 = new Sample( id: 102, name: "Sample 1b", sampleToken: "tsample1b", study: trash );
125                Sample sa3 = new Sample( id: 103, name: "Sample 2a", sampleToken: "tsample2a", study: trash );
126                def samples = [sa1, sa2, sa3]
127               
128                samples.each { trash.addToSamples( it ); it.save(flush:true); }
129               
130                trash.save(flush:true);
131               
132                // Create desired combinations of samples and assays
133                // Such that: assay1 has 2 samples with data, assay2 has 1 sample with data and assay3 has no samples with data
134           AssaySample as1a = new AssaySample( id: 102, oligoNumber: "fromtrash: 1", tagSequence: "fromtrash: abc", sample: sa1, assay: a1 );
135           AssaySample as1b = new AssaySample( oligoNumber: "fromtrash: 2", tagSequence: "fromtrash: def", sample: sa2, assay: a1 );
136           AssaySample as2a = new AssaySample( oligoNumber: "fromtrash: 3", tagSequence: "fromtrash: ghi", sample: sa3, assay: a1 );
137           def assaySamples= [as1a, as1b, as2a]
138
139           a1.addToAssaySamples( as1a ); sa1.addToAssaySamples( as1a );
140           as1a.save(flush:true);
141           
142           a1.addToAssaySamples( as1b ); sa2.addToAssaySamples( as1b );
143           as1b.save(flush:true);
144
145           a1.addToAssaySamples( as2a ); sa3.addToAssaySamples( as2a );
146           as2a.save(flush:true);
147
148           // Save samples and assays again
149           assays.each { it.save(flush:true); }
150           samples.each { it.save(flush:true); }
151           
152           // Create a single run in order to be able to save sequencedata
153           Run run = new Run( name: "trashrun" );
154           run.save(flush:true);
155
156           // Add sequencedata objects to as1a and as1b
157           SequenceData sd1 = new SequenceData( run: run, assaySample: as1a, sequenceFile: "fromtrash: fasta1", qualityFile: "fromtrash: qual1", numSequences: 80, averageQuality: 11.0 );
158           SequenceData sd2 = new SequenceData( run: run, assaySample: as1a, sequenceFile: "fromtrash: fasta2", qualityFile: "fromtrash: qual2", numSequences: 520, averageQuality: 14.0 );
159           SequenceData sd3 = new SequenceData( run: run, assaySample: as1b, sequenceFile: "fromtrash: fasta3", qualityFile: "fromtrash: qual3", numSequences: 2000, averageQuality: 17.0 );
160           def sequenceData = [sd1, sd2, sd3];
161           
162           run.addToSequenceData( sd1 );
163           run.addToSequenceData( sd2 );
164           run.addToSequenceData( sd3 );
165           
166           as1a.addToSequenceData( sd1 );
167           as1a.addToSequenceData( sd2 );
168           as1b.addToSequenceData( sd3 );
169           
170           run.save(flush:true); as1a.save(flush:true); as1b.save(flush:true);
171           sequenceData.each { it.save(flush:true); }
172        }
173       
174    void testStudyTrash() {
175                def study = Study.findByStudyToken( "study1" );
176               
177                // Check whether the starting condition is correct
178                assert trash instanceof Study
179                assert study instanceof Study
180                assert study.assays?.size() == 3;
181                assert ( !trash.assays || trash.assays.size() == 0 );
182               
183                // Move data to trash and delete study
184                trashService.moveToTrash( study );
185               
186                // Check whether the study is really removed
187                assert null == Study.findByStudyToken( "study1" );
188               
189                // Check whether only the assays were kept that contain data
190                assert trash.assays.size() == 2;
191               
192                // Check whether only the assaysamples were kept that contain data
193                def assaySamples = trash.assays*.assaySamples.flatten().unique();
194                assert assaySamples.size() == 3;
195               
196                def assaySample = assaySamples.find { it.sample?.name == "Sample 1a"; }
197                assert assaySample
198                assert assaySample.oligoNumber == "123"
199                assert assaySample.tagSequence == "abc"
200                assert assaySample.sequenceData.size() == 2
201
202                assaySample = assaySamples.find { it.sample?.name == "Sample 1b"; }
203                assert assaySample
204                assert assaySample.oligoNumber == "200"
205                assert assaySample.tagSequence == "def"
206                assert assaySample.sequenceData.size() == 1
207
208                assaySample = assaySamples.find { it.sample?.name == "Sample 2a"; }
209                assert assaySample
210                assert assaySample.oligoNumber == "300"
211                assert assaySample.tagSequence == "ghi"
212                assert !assaySample.sequenceData || assaySample.sequenceData.size() == 0
213
214                // Check whether the assay samples contain the right sequence data
215                def sequenceData = trash.assays*.assaySamples*.sequenceData.flatten().unique();
216               
217                // Filter null values
218                sequenceData = sequenceData.findAll { it != null };
219                assert sequenceData.size() == 3;
220               
221                def sd = sequenceData.find { it.sequenceFile == "fasta1"; }
222                assert sd
223                assert sd.qualityFile == "qual1" 
224                assert sd.numSequences == 100 
225                assert sd.averageQuality == 10.0
226                assert sd.sample.assay.name == "Assay 1"
227                assert sd.sample.sample.name == "Sample 1a"
228               
229                sd = sequenceData.find { it.sequenceFile == "fasta2"; }
230                assert sd
231                assert sd.qualityFile == "qual2"
232                assert sd.numSequences == 30
233                assert sd.averageQuality == 14.0
234                assert sd.sample.assay.name == "Assay 1"
235                assert sd.sample.sample.name == "Sample 1a"
236               
237                sd = sequenceData.find { it.sequenceFile == "fasta3"; }
238                assert sd
239                assert sd.qualityFile == "qual3"
240                assert sd.numSequences == 2000
241                assert sd.averageQuality == 17.0
242                assert sd.sample.assay.name == "Assay 1"
243                assert sd.sample.sample.name == "Sample 1b"
244    }
245       
246        void testAssayTrash() {
247                def study = Study.findByStudyToken( "study1" );
248                def assay = study.assays.find { it.assayToken == "assay1" };
249               
250                // Check whether the starting condition is correct
251                assert trash instanceof Study
252                assert assay instanceof Assay
253                assert assay.assaySamples.size() == 2;
254                assert ( !trash.assays || trash.assays.size() == 0 );
255               
256                // Move data to trash and delete study
257                trashService.moveToTrash( assay );
258               
259                // Check whether the study itself still exists
260                study = Study.findByStudyToken( "study1" )
261                assert study
262                assay = study.assays.find { it.assayToken == "assay1" };
263               
264                study.assays.each { 
265                        println it.name + ", " + it.assaySamples?.size()
266                }
267                assert !assay
268                assert study.assays.size() == 2
269               
270                // Check whether the assay is really removed
271                assay = Assay.findByAssayToken( "assay1" );
272                assert !assay
273               
274                // Check whether the assay samples also have been removed
275                // assert AssaySample.list().findAll { it.assay?.study?.studyToken == "study1" && it.assay?.assayToken == "assay1" }.size() == 0
276               
277                // Check whether only the assays were kept that contain data
278                assert trash.assays.size() == 1;
279                assert trash.samples.size() == 2;
280               
281                // Check whether only the assaysamples were kept that contain data
282                def assaySamples = trash.assays*.assaySamples.flatten().unique();
283                assert assaySamples.size() == 2;
284               
285                def assaySample = assaySamples.find { it.sample?.name == "Sample 1a"; }
286                assert assaySample
287                assert assaySample.oligoNumber == "123"
288                assert assaySample.tagSequence == "abc"
289                assert assaySample.sequenceData.size() == 2
290
291                assaySample = assaySamples.find { it.sample?.name == "Sample 1b"; }
292                assert assaySample
293                assert assaySample.oligoNumber == "200"
294                assert assaySample.tagSequence == "def"
295                assert assaySample.sequenceData.size() == 1
296
297                // Check whether the assay samples contain the right sequence data
298                def sequenceData = trash.assays*.assaySamples*.sequenceData.flatten().unique();
299               
300                // Filter null values
301                sequenceData = sequenceData.findAll { it != null };
302                assert sequenceData.size() == 3;
303               
304                def sd = sequenceData.find { it.sequenceFile == "fasta1"; }
305                assert sd
306                assert sd.qualityFile == "qual1"
307                assert sd.numSequences == 100
308                assert sd.averageQuality == 10.0
309                assert sd.sample.assay.name == "Assay 1"
310                assert sd.sample.sample.name == "Sample 1a"
311               
312                sd = sequenceData.find { it.sequenceFile == "fasta2"; }
313                assert sd
314                assert sd.qualityFile == "qual2"
315                assert sd.numSequences == 30
316                assert sd.averageQuality == 14.0
317                assert sd.sample.assay.name == "Assay 1"
318                assert sd.sample.sample.name == "Sample 1a"
319               
320                sd = sequenceData.find { it.sequenceFile == "fasta3"; }
321                assert sd
322                assert sd.qualityFile == "qual3"
323                assert sd.numSequences == 2000
324                assert sd.averageQuality == 17.0
325                assert sd.sample.assay.name == "Assay 1"
326                assert sd.sample.sample.name == "Sample 1b"
327        }
328       
329        void testSampleTrash() {
330                def study = Study.findByStudyToken( "study1" );
331                def sample = study.samples.find { it.sampleToken == "sample1a" };
332                def assay
333               
334                // Check whether the starting condition is correct
335                assert trash instanceof Study
336                assert sample instanceof Sample
337                assert sample.assaySamples.size() == 1;
338                assert ( !trash.assays || trash.assays.size() == 0 );
339               
340                // Move data to trash and delete study
341                trashService.moveToTrash( sample );
342               
343                // Check whether the study and the assay itself still exists
344                study = Study.findByStudyToken( "study1" )
345                assert study
346                assay = study.assays.find { it.assayToken == "assay1" };
347                assert assay
348                assert study.assays.size() == 3
349               
350                // Check whether the sample is really removed
351                sample = Sample.findBySampleToken( "sample1a" );
352                assert !sample
353                sample = study.samples.find { it.sampleToken == "sample1a" }
354                assert !sample
355
356                // Check whether the assay samples also have been removed
357                //assert AssaySample.list().findAll { it.sample?.study?.studyToken == "study1" && it.sample?.sampleToken == "assay1" }.size() == 0
358                               
359                // Check whether only the assays were kept that contain data
360                assert trash.assays.size() == 1;
361                assert trash.samples.size() == 1;
362               
363                // Check whether only the assaysamples were kept that contain data and belong to sample 1
364                def assaySamples = trash.assays*.assaySamples.flatten().unique();
365                assert assaySamples.size() == 1;
366               
367                def assaySample = assaySamples.find { it.sample?.name == "Sample 1a"; }
368                assert assaySample
369                assert assaySample.assay?.name == "Assay 1"
370                assert assaySample.oligoNumber == "123"
371                assert assaySample.tagSequence == "abc"
372                assert assaySample.sequenceData.size() == 2
373
374                // Check whether the assay samples contain the right sequence data
375                def sequenceData = trash.assays*.assaySamples*.sequenceData.flatten().unique();
376               
377                // Filter null values
378                sequenceData = sequenceData.findAll { it != null };
379               
380                assert sequenceData.size() == 2;
381
382                // Filter null values
383                sequenceData = sequenceData.findAll { it != null };
384                assert sequenceData.size() == 2;
385               
386                def sd = sequenceData.find { it.sequenceFile == "fasta1"; }
387                assert sd
388                assert sd.qualityFile == "qual1"
389                assert sd.numSequences == 100
390                assert sd.averageQuality == 10.0
391                assert sd.sample.assay.name == "Assay 1"
392                assert sd.sample.sample.name == "Sample 1a"
393               
394                sd = sequenceData.find { it.sequenceFile == "fasta2"; }
395                assert sd
396                assert sd.qualityFile == "qual2"
397                assert sd.numSequences == 30
398                assert sd.averageQuality == 14.0
399                assert sd.sample.assay.name == "Assay 1"
400                assert sd.sample.sample.name == "Sample 1a"
401        }
402       
403        void testRestoreAssay() {
404                setupTrash();
405               
406                def study = Study.findByStudyToken( "study1" );
407               
408                def trashAssay = trash.assays.find { it.assayToken == "trash_assay1" };
409                def restoreTo = study.assays.find { it.assayToken == "assay1" };
410               
411                assert trashAssay
412                assert restoreTo
413               
414                assert restoreTo.assaySamples?.size() == 2
415               
416                trashService.restoreAssay( trashAssay, restoreTo );
417               
418                // Check whether the sample data is moved to the other assay
419                def restoredTo = study.assays.find { it.assayToken == "assay1" };
420                assert restoredTo.assaySamples?.size() == 2
421               
422                // Check for the copying of oligoNumber and tagSequence
423                def s = restoredTo.assaySamples.find { it.sample.sampleToken == "sample1a" }
424                assert s
425                assert s.oligoNumber == "fromtrash: 1";
426                assert s.tagSequence == "fromtrash: abc";
427                assert s.sequenceData?.size() == 4
428               
429                assert s.numSequences() == 730
430                def sequenceFiles = s.sequenceData.sequenceFile;
431                assert sequenceFiles.contains( "fromtrash: fasta1" )
432                assert sequenceFiles.contains( "fromtrash: fasta2" )
433               
434                // Also check the second assay sample
435                s = restoredTo.assaySamples.find { it.sample.sampleToken == "sample1b" }
436                assert s
437                assert s.oligoNumber == "fromtrash: 2";
438                assert s.tagSequence == "fromtrash: def";
439                assert s.sequenceData?.size() == 2
440               
441                assert s.numSequences() == 4000
442                sequenceFiles = s.sequenceData.sequenceFile;
443                assert sequenceFiles.contains( "fromtrash: fasta3" )
444        }
445       
446        void testRestoreSample() {
447                setupTrash();
448               
449                def study = Study.findByStudyToken( "study1" );
450
451                def trashAssay = trash.assays.find { it.assayToken == "trash_assay1" };
452                def restoreToAssay = study.assays.find { it.assayToken == "assay2" };
453
454                assert trashAssay
455                assert restoreToAssay
456
457                def trashSample = trashAssay.assaySamples.find { it.id == 102 };
458                def restoreTo = restoreToAssay.assaySamples.find { it.id == 12 };
459
460                assert trashSample
461                assert restoreTo
462               
463                assert restoreTo.sequenceData == null || restoreTo.sequenceData.size() == 0;
464               
465                trashService.restoreSample( trashSample, restoreTo );
466               
467                // Check whether the sample data is moved to the other assay
468                def restoredTo = restoreToAssay.assaySamples.find { it.id == 12 };
469                assert restoredTo
470               
471                // Check for the copying of oligoNumber and tagSequence
472                assert restoredTo.oligoNumber == "fromtrash: 1";
473                assert restoredTo.tagSequence == "fromtrash: abc";
474                assert restoredTo.sequenceData?.size() == 2
475               
476                assert restoredTo.numSequences() == 600
477                def sequenceFiles = restoredTo.sequenceData.sequenceFile;
478                assert sequenceFiles.contains( "fromtrash: fasta1" )
479                assert sequenceFiles.contains( "fromtrash: fasta2" )
480
481        }
482}
Note: See TracBrowser for help on using the repository browser.