1 | -- $Id: testcase.pgsql 56295 2015-06-09 14:29:55Z vboxsync $
|
---|
2 | --- @file
|
---|
3 | -- VBox Test Manager Database Stored Procedures - TestCases.
|
---|
4 | --
|
---|
5 |
|
---|
6 | --
|
---|
7 | -- Copyright (C) 2012-2015 Oracle Corporation
|
---|
8 | --
|
---|
9 | -- This file is part of VirtualBox Open Source Edition (OSE), as
|
---|
10 | -- available from http://www.virtualbox.org. This file is free software;
|
---|
11 | -- you can redistribute it and/or modify it under the terms of the GNU
|
---|
12 | -- General Public License (GPL) as published by the Free Software
|
---|
13 | -- Foundation, in version 2 as it comes in the "COPYING" file of the
|
---|
14 | -- VirtualBox OSE distribution. VirtualBox OSE is distributed in the
|
---|
15 | -- hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
|
---|
16 | --
|
---|
17 | -- The contents of this file may alternatively be used under the terms
|
---|
18 | -- of the Common Development and Distribution License Version 1.0
|
---|
19 | -- (CDDL) only, as it comes in the "COPYING.CDDL" file of the
|
---|
20 | -- VirtualBox OSE distribution, in which case the provisions of the
|
---|
21 | -- CDDL are applicable instead of those of the GPL.
|
---|
22 | --
|
---|
23 | -- You may elect to license modified versions of this file under the
|
---|
24 | -- terms and conditions of either the GPL or the CDDL or both.
|
---|
25 | --
|
---|
26 |
|
---|
27 | \set ON_ERROR_STOP 1
|
---|
28 | \connect testmanager;
|
---|
29 |
|
---|
30 | DROP FUNCTION IF EXISTS add_testcase(INTEGER, TEXT, TEXT, BOOLEAN, INTEGER, TEXT, TEXT);
|
---|
31 | DROP FUNCTION IF EXISTS edit_testcase(INTEGER, INTEGER, TEXT, TEXT, BOOLEAN, INTEGER, TEXT, TEXT);
|
---|
32 | DROP FUNCTION IF EXISTS del_testcase(INTEGER);
|
---|
33 | DROP FUNCTION IF EXISTS TestCaseLogic_delEntry(INTEGER, INTEGER);
|
---|
34 |
|
---|
35 | ---
|
---|
36 | -- Checks if the test case name is unique, ignoring a_idTestCaseIgnore.
|
---|
37 | -- Raises exception if duplicates are found.
|
---|
38 | --
|
---|
39 | -- @internal
|
---|
40 | --
|
---|
41 | CREATE OR REPLACE FUNCTION TestCaseLogic_checkUniqueName(a_sName TEXT, a_idTestCaseIgnore INTEGER)
|
---|
42 | RETURNS VOID AS $$
|
---|
43 | DECLARE
|
---|
44 | v_cRows INTEGER;
|
---|
45 | BEGIN
|
---|
46 | SELECT COUNT(*) INTO v_cRows
|
---|
47 | FROM TestCases
|
---|
48 | WHERE sName = a_sName
|
---|
49 | AND tsExpire = 'infinity'::TIMESTAMP
|
---|
50 | AND idTestCase <> a_idTestCaseIgnore;
|
---|
51 | IF v_cRows <> 0 THEN
|
---|
52 | RAISE EXCEPTION 'Duplicate test case name "%" (% times)', a_sName, v_cRows;
|
---|
53 | END IF;
|
---|
54 | END;
|
---|
55 | $$ LANGUAGE plpgsql;
|
---|
56 |
|
---|
57 | ---
|
---|
58 | -- Check that the test case exists.
|
---|
59 | -- Raises exception if it doesn't.
|
---|
60 | --
|
---|
61 | -- @internal
|
---|
62 | --
|
---|
63 | CREATE OR REPLACE FUNCTION TestCaseLogic_checkExists(a_idTestCase INTEGER) RETURNS VOID AS $$
|
---|
64 | BEGIN
|
---|
65 | IF NOT EXISTS( SELECT *
|
---|
66 | FROM TestCases
|
---|
67 | WHERE idTestCase = a_idTestCase
|
---|
68 | AND tsExpire = 'infinity'::TIMESTAMP ) THEN
|
---|
69 | RAISE EXCEPTION 'Test case with ID % does not currently exist', a_idTestCase;
|
---|
70 | END IF;
|
---|
71 | END;
|
---|
72 | $$ LANGUAGE plpgsql;
|
---|
73 |
|
---|
74 |
|
---|
75 | ---
|
---|
76 | -- Historize a row.
|
---|
77 | -- @internal
|
---|
78 | --
|
---|
79 | CREATE OR REPLACE FUNCTION TestCaseLogic_historizeEntry(a_idTestCase INTEGER, a_tsExpire TIMESTAMP WITH TIME ZONE)
|
---|
80 | RETURNS VOID AS $$
|
---|
81 | DECLARE
|
---|
82 | v_cUpdatedRows INTEGER;
|
---|
83 | BEGIN
|
---|
84 | UPDATE TestCases
|
---|
85 | SET tsExpire = a_tsExpire
|
---|
86 | WHERE idTestcase = a_idTestCase
|
---|
87 | AND tsExpire = 'infinity'::TIMESTAMP;
|
---|
88 | GET DIAGNOSTICS v_cUpdatedRows = ROW_COUNT;
|
---|
89 | IF v_cUpdatedRows <> 1 THEN
|
---|
90 | IF v_cUpdatedRows = 0 THEN
|
---|
91 | RAISE EXCEPTION 'Test case ID % does not currently exist', a_idTestCase;
|
---|
92 | END IF;
|
---|
93 | RAISE EXCEPTION 'Integrity error in TestCases: % current rows with idTestCase=%d', v_cUpdatedRows, a_idTestCase;
|
---|
94 | END IF;
|
---|
95 | END;
|
---|
96 | $$ LANGUAGE plpgsql;
|
---|
97 |
|
---|
98 | CREATE OR REPLACE function TestCaseLogic_addEntry(a_uidAuthor INTEGER, a_sName TEXT, a_sDescription TEXT,
|
---|
99 | a_fEnabled BOOL, a_cSecTimeout INTEGER, a_sTestBoxReqExpr TEXT,
|
---|
100 | a_sBuildReqExpr TEXT, a_sBaseCmd TEXT, a_sTestSuiteZips TEXT)
|
---|
101 | RETURNS INTEGER AS $$
|
---|
102 | DECLARE
|
---|
103 | v_idTestCase INTEGER;
|
---|
104 | BEGIN
|
---|
105 | PERFORM TestCaseLogic_checkUniqueName(a_sName, -1);
|
---|
106 |
|
---|
107 | INSERT INTO TestCases (uidAuthor, sName, sDescription, fEnabled, cSecTimeout,
|
---|
108 | sTestBoxReqExpr, sBuildReqExpr, sBaseCmd, sTestSuiteZips)
|
---|
109 | VALUES (a_uidAuthor, a_sName, a_sDescription, a_fEnabled, a_cSecTimeout,
|
---|
110 | a_sTestBoxReqExpr, a_sBuildReqExpr, a_sBaseCmd, a_sTestSuiteZips)
|
---|
111 | RETURNING idTestcase INTO v_idTestCase;
|
---|
112 | RETURN v_idTestCase;
|
---|
113 | END;
|
---|
114 | $$ LANGUAGE plpgsql;
|
---|
115 |
|
---|
116 | CREATE OR REPLACE function TestCaseLogic_editEntry(a_uidAuthor INTEGER, a_idTestCase INTEGER, a_sName TEXT, a_sDescription TEXT,
|
---|
117 | a_fEnabled BOOL, a_cSecTimeout INTEGER, a_sTestBoxReqExpr TEXT,
|
---|
118 | a_sBuildReqExpr TEXT, a_sBaseCmd TEXT, a_sTestSuiteZips TEXT)
|
---|
119 | RETURNS INTEGER AS $$
|
---|
120 | DECLARE
|
---|
121 | v_idGenTestCase INTEGER;
|
---|
122 | BEGIN
|
---|
123 | PERFORM TestCaseLogic_checkExists(a_idTestCase);
|
---|
124 | PERFORM TestCaseLogic_checkUniqueName(a_sName, a_idTestCase);
|
---|
125 |
|
---|
126 | PERFORM TestCaseLogic_historizeEntry(a_idTestCase, CURRENT_TIMESTAMP);
|
---|
127 | INSERT INTO TestCases (idTestCase, uidAuthor, sName, sDescription, fEnabled, cSecTimeout,
|
---|
128 | sTestBoxReqExpr, sBuildReqExpr, sBaseCmd, sTestSuiteZips)
|
---|
129 | VALUES (a_idTestCase, a_uidAuthor, a_sName, a_sDescription, a_fEnabled, a_cSecTimeout,
|
---|
130 | a_sTestBoxReqExpr, a_sBuildReqExpr, a_sBaseCmd, a_sTestSuiteZips)
|
---|
131 | RETURNING idGenTestCase INTO v_idGenTestCase;
|
---|
132 | RETURN v_idGenTestCase;
|
---|
133 | END;
|
---|
134 | $$ LANGUAGE plpgsql;
|
---|
135 |
|
---|
136 |
|
---|
137 | CREATE OR REPLACE FUNCTION TestCaseLogic_delEntry(a_uidAuthor INTEGER, a_idTestCase INTEGER, a_fCascade BOOLEAN)
|
---|
138 | RETURNS VOID AS $$
|
---|
139 | DECLARE
|
---|
140 | v_Row TestCases%ROWTYPE;
|
---|
141 | v_tsEffective TIMESTAMP WITH TIME ZONE;
|
---|
142 | v_Rec RECORD;
|
---|
143 | v_sErrors TEXT;
|
---|
144 | BEGIN
|
---|
145 | --
|
---|
146 | -- Check preconditions.
|
---|
147 | --
|
---|
148 | IF a_fCascade <> TRUE THEN
|
---|
149 | IF EXISTS( SELECT *
|
---|
150 | FROM TestCaseDeps
|
---|
151 | WHERE idTestCasePreReq = a_idTestCase
|
---|
152 | AND tsExpire = 'infinity'::TIMESTAMP ) THEN
|
---|
153 | v_sErrors := '';
|
---|
154 | FOR v_Rec IN
|
---|
155 | SELECT TestCases.idTestCase AS idTestCase,
|
---|
156 | TestCases.sName AS sName
|
---|
157 | FROM TestCaseDeps, TestCases
|
---|
158 | WHERE TestCaseDeps.idTestCasePreReq = a_idTestCase
|
---|
159 | AND TestCaseDeps.tsExpire = 'infinity'::TIMESTAMP
|
---|
160 | AND TestCases.idTestCase = TestCaseDeps.idTestCase
|
---|
161 | AND TestCases.tsExpire = 'infinity'::TIMESTAMP
|
---|
162 | LOOP
|
---|
163 | IF v_sErrors <> '' THEN
|
---|
164 | v_sErrors := v_sErrors || ', ';
|
---|
165 | END IF;
|
---|
166 | v_sErrors := v_sErrors || v_Rec.sName || ' (idTestCase=' || v_Rec.idTestCase || ')';
|
---|
167 | END LOOP;
|
---|
168 | RAISE EXCEPTION 'Other test cases depends on test case with ID %: % ', a_idTestCase, v_sErrors;
|
---|
169 | END IF;
|
---|
170 |
|
---|
171 | IF EXISTS( SELECT *
|
---|
172 | FROM TestGroupMembers
|
---|
173 | WHERE idTestCase = a_idTestCase
|
---|
174 | AND tsExpire = 'infinity'::TIMESTAMP ) THEN
|
---|
175 | v_sErrors := '';
|
---|
176 | FOR v_Rec IN
|
---|
177 | SELECT TestGroups.idTestGroup AS idTestGroup,
|
---|
178 | TestGroups.sName AS sName
|
---|
179 | FROM TestGroupMembers, TestGroups
|
---|
180 | WHERE TestGroupMembers.idTestCase = a_idTestCase
|
---|
181 | AND TestGroupMembers.tsExpire = 'infinity'::TIMESTAMP
|
---|
182 | AND TestGroupMembers.idTestGroup = TestGroups.idTestGroup
|
---|
183 | AND TestGroups.tsExpire = 'infinity'::TIMESTAMP
|
---|
184 | LOOP
|
---|
185 | IF v_sErrors <> '' THEN
|
---|
186 | v_sErrors := v_sErrors || ', ';
|
---|
187 | END IF;
|
---|
188 | v_sErrors := v_sErrors || v_Rec.sName || ' (idTestGroup=' || v_Rec.idTestGroup || ')';
|
---|
189 | END LOOP;
|
---|
190 | RAISE EXCEPTION 'Test case with ID % is member of the following test group(s): % ', a_idTestCase, v_sErrors;
|
---|
191 | END IF;
|
---|
192 | END IF;
|
---|
193 |
|
---|
194 | --
|
---|
195 | -- To preserve the information about who deleted the record, we try to
|
---|
196 | -- add a dummy record which expires immediately. I say try because of
|
---|
197 | -- the primary key, we must let the new record be valid for 1 us. :-(
|
---|
198 | --
|
---|
199 | SELECT * INTO STRICT v_Row
|
---|
200 | FROM TestCases
|
---|
201 | WHERE idTestCase = a_idTestCase
|
---|
202 | AND tsExpire = 'infinity'::TIMESTAMP;
|
---|
203 |
|
---|
204 | v_tsEffective := CURRENT_TIMESTAMP - INTERVAL '1 microsecond';
|
---|
205 | IF v_Row.tsEffective < v_tsEffective THEN
|
---|
206 | PERFORM TestCaseLogic_historizeEntry(a_idTestCase, v_tsEffective);
|
---|
207 | v_Row.tsEffective := v_tsEffective;
|
---|
208 | v_Row.tsExpire := CURRENT_TIMESTAMP;
|
---|
209 | SELECT NEXTVAL('TestCaseGenIdSeq') INTO v_Row.idGenTestCase;
|
---|
210 | INSERT INTO TestCases VALUES (v_Row.*);
|
---|
211 | ELSE
|
---|
212 | PERFORM TestCaseLogic_historizeEntry(a_idTestCase, CURRENT_TIMESTAMP);
|
---|
213 | END IF;
|
---|
214 |
|
---|
215 | --
|
---|
216 | -- Delete arguments, test case dependencies and resource dependencies.
|
---|
217 | -- (We don't bother recording who deleted the records here since it's
|
---|
218 | -- a lot of work and sufficiently covered in the TestCases table.)
|
---|
219 | --
|
---|
220 | UPDATE TestCaseArgs
|
---|
221 | SET tsExpire = CURRENT_TIMESTAMP
|
---|
222 | WHERE idTestCase = a_idTestCase
|
---|
223 | AND tsExpire = 'infinity'::TIMESTAMP;
|
---|
224 |
|
---|
225 | UPDATE TestCaseDeps
|
---|
226 | SET tsExpire = CURRENT_TIMESTAMP
|
---|
227 | WHERE idTestCase = a_idTestCase
|
---|
228 | AND tsExpire = 'infinity'::TIMESTAMP;
|
---|
229 |
|
---|
230 | UPDATE TestCaseGlobalRsrcDeps
|
---|
231 | SET tsExpire = CURRENT_TIMESTAMP
|
---|
232 | WHERE idTestCase = a_idTestCase
|
---|
233 | AND tsExpire = 'infinity'::TIMESTAMP;
|
---|
234 |
|
---|
235 | IF a_fCascade = TRUE THEN
|
---|
236 | UPDATE TestCaseDeps
|
---|
237 | SET tsExpire = CURRENT_TIMESTAMP
|
---|
238 | WHERE idTestCasePreReq = a_idTestCase
|
---|
239 | AND tsExpire = 'infinity'::TIMESTAMP;
|
---|
240 |
|
---|
241 | UPDATE TestGroupMembers
|
---|
242 | SET tsExpire = CURRENT_TIMESTAMP
|
---|
243 | WHERE idTestCase = a_idTestCase
|
---|
244 | AND tsExpire = 'infinity'::TIMESTAMP;
|
---|
245 | END IF;
|
---|
246 |
|
---|
247 | EXCEPTION
|
---|
248 | WHEN NO_DATA_FOUND THEN
|
---|
249 | RAISE EXCEPTION 'Test case with ID % does not currently exist', a_idTestCase;
|
---|
250 | WHEN TOO_MANY_ROWS THEN
|
---|
251 | RAISE EXCEPTION 'Integrity error in TestCases: Too many current rows for %', a_idTestCase;
|
---|
252 | END;
|
---|
253 | $$ LANGUAGE plpgsql;
|
---|
254 |
|
---|