1 /*=========================================================================
2 
3   Library:   CTK
4 
5   Copyright (c) Kitware Inc.
6 
7   Licensed under the Apache License, Version 2.0 (the "License");
8   you may not use this file except in compliance with the License.
9   You may obtain a copy of the License at
10 
11       http://www.apache.org/licenses/LICENSE-2.0.txt
12 
13   Unless required by applicable law or agreed to in writing, software
14   distributed under the License is distributed on an "AS IS" BASIS,
15   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   See the License for the specific language governing permissions and
17   limitations under the License.
18 
19 =========================================================================*/
20 
21 // Qt includes
22 #include <QCoreApplication>
23 #include <QDir>
24 #include <QTimer>
25 
26 // ctkDICOMCore includes
27 #include "ctkDICOMDatabase.h"
28 
29 // STD includes
30 #include <iostream>
31 #include <cstdlib>
32 
33 
ctkDICOMDatabaseTest2(int argc,char * argv[])34 int ctkDICOMDatabaseTest2( int argc, char * argv [] )
35 {
36   QCoreApplication app(argc, argv);
37 
38   if (argc < 2)
39     {
40     std::cerr << "ctkDICOMDatabaseTest2: missing dicom filePath argument";
41     std::cerr << std::endl;
42     return EXIT_FAILURE;
43     }
44 
45   QString dicomFilePath(argv[1]);
46 
47   ctkDICOMDatabase database;
48   QDir databaseDirectory = QDir::temp();
49   databaseDirectory.remove("ctkDICOMDatabase.sql");
50   databaseDirectory.remove("ctkDICOMTagCache.sql");
51 
52   QFileInfo databaseFile(databaseDirectory, QString("database.test"));
53   database.openDatabase(databaseFile.absoluteFilePath());
54 
55   if (!database.lastError().isEmpty())
56     {
57     std::cerr << "ctkDICOMDatabase::openDatabase() failed: "
58               << qPrintable(database.lastError()) << std::endl;
59     return EXIT_FAILURE;
60     }
61 
62   if (!database.database().isValid())
63     {
64     std::cerr << "ctkDICOMDatabase::openDatabase() failed: "
65               << "invalid sql database" << std::endl;
66     return EXIT_FAILURE;
67     }
68 
69   if (database.isInMemory())
70     {
71     std::cerr << "ctkDICOMDatabase::openDatabase() failed: "
72               << "database should not be in memory" << std::endl;
73     return EXIT_FAILURE;
74     }
75 
76   bool res = database.initializeDatabase();
77 
78   if (!res)
79     {
80     std::cerr << "ctkDICOMDatabase::initializeDatabase() failed." << std::endl;
81     return EXIT_FAILURE;
82     }
83 
84   //
85   // Test that the tag interface works to parse ascii
86   //
87   QString tag("0008,103e");
88   unsigned short group, element;
89   if ( !database.tagToGroupElement(tag, group, element) )
90     {
91     std::cerr << "ctkDICOMDatabase: could not parse tag" << std::endl;
92     return EXIT_FAILURE;
93     }
94 
95   if ( group != 0x8 || element != 0x103e )
96     {
97     std::cerr << "ctkDICOMDatabase: expected: " << "0008,103e" << std::endl;
98     std::cerr << "ctkDICOMDatabase: got: " << group << " " << element << std::endl;
99     std::cerr << "ctkDICOMDatabase: parsed tag does not match group/element" << std::endl;
100     return EXIT_FAILURE;
101     }
102 
103   if ( database.groupElementToTag(group, element) != tag )
104     {
105     std::cerr << "ctkDICOMDatabase: could not convert a uints to tag string" << std::endl;
106     return EXIT_FAILURE;
107     }
108 
109 
110   //
111   // Basic test:
112   // - insert the file specified on the command line
113   // - ask for tag values and compare to known results
114   //
115   database.insert(dicomFilePath, false, false);
116   QString instanceUID("1.2.840.113619.2.135.3596.6358736.4843.1115808177.83");
117 
118   QString foundFile = database.fileForInstance(instanceUID);
119 
120   if (foundFile != dicomFilePath)
121     {
122     std::cerr << "ctkDICOMDatabase: didn't get back the original file path" << std::endl;
123     return EXIT_FAILURE;
124     }
125 
126   QString foundInstance = database.instanceForFile(dicomFilePath);
127 
128   if (foundInstance != instanceUID)
129     {
130     std::cerr << "ctkDICOMDatabase: didn't get back the original instance uid" << std::endl;
131     return EXIT_FAILURE;
132     }
133 
134 
135   //
136   // Test the tag cache
137   //
138 
139   if (!database.tagCacheExists())
140     {
141     std::cerr << "ctkDICOMDatabase: tag cache should be configured when database opens" << std::endl;
142     return EXIT_FAILURE;
143     }
144 
145   if (!database.initializeTagCache())
146     {
147     std::cerr << "ctkDICOMDatabase: could not initialize tag cache" << std::endl;
148     return EXIT_FAILURE;
149     }
150 
151   if (!database.tagCacheExists())
152     {
153     std::cerr << "ctkDICOMDatabase: tag cache should exist but is not detected" << std::endl;
154     return EXIT_FAILURE;
155     }
156 
157 
158   if (database.cachedTag(instanceUID, tag) != QString(""))
159     {
160     std::cerr << "ctkDICOMDatabase: tag cache should return empty string for unknown instance tag" << std::endl;
161     return EXIT_FAILURE;
162     }
163 
164   QString knownSeriesDescription("3D Cor T1 FAST IR-prepped GRE");
165 
166   if (!database.cacheTag(instanceUID, tag, knownSeriesDescription))
167     {
168     std::cerr << "ctkDICOMDatabase: could not insert instance tag" << std::endl;
169     return EXIT_FAILURE;
170     }
171 
172   if (database.cachedTag(instanceUID, tag) != knownSeriesDescription)
173     {
174     std::cerr << "ctkDICOMDatabase: could not retrieve cached tag" << std::endl;
175     return EXIT_FAILURE;
176     }
177 
178 
179   QString foundSeriesDescription = database.instanceValue(instanceUID, tag);
180 
181   if (foundSeriesDescription != knownSeriesDescription)
182     {
183     std::cerr << "ctkDICOMDatabase: invalid element value returned" << std::endl;
184     return EXIT_FAILURE;
185     }
186 
187   // now update the database
188   database.updateSchema();
189 
190   // and repeat the above checks
191   foundFile = database.fileForInstance(instanceUID);
192 
193   if (foundFile != dicomFilePath)
194     {
195     std::cerr << "ctkDICOMDatabase: didn't get back the original file path" << std::endl;
196     return EXIT_FAILURE;
197     }
198 
199   foundSeriesDescription = database.instanceValue(instanceUID, tag);
200 
201   if (foundSeriesDescription != knownSeriesDescription)
202     {
203     std::cerr << "ctkDICOMDatabase: invalid element value returned" << std::endl;
204     return EXIT_FAILURE;
205     }
206 
207   database.closeDatabase();
208   database.initializeDatabase();
209 
210   return EXIT_SUCCESS;
211 }
212