1 | -- $Id: testcase.pgsql 82968 2020-02-04 10:35:17Z vboxsync $
|
---|
2 | --- @file
|
---|
3 | -- VBox Test Manager Database Stored Procedures - TestCases.
|
---|
4 | --
|
---|
5 |
|
---|
6 | --
|
---|
7 | -- Copyright (C) 2012-2020 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 | DROP FUNCTION IF EXISTS TestCaseLogic_addEntry(a_uidAuthor INTEGER, a_sName TEXT, a_sDescription TEXT,
|
---|
35 | a_fEnabled BOOL, a_cSecTimeout INTEGER, a_sTestBoxReqExpr TEXT,
|
---|
36 | a_sBuildReqExpr TEXT, a_sBaseCmd TEXT, a_sTestSuiteZips TEXT);
|
---|
37 | DROP FUNCTION IF EXISTS TestCaseLogic_editEntry(a_uidAuthor INTEGER, a_idTestCase INTEGER, a_sName TEXT, a_sDescription TEXT,
|
---|
38 | a_fEnabled BOOL, a_cSecTimeout INTEGER, a_sTestBoxReqExpr TEXT,
|
---|
39 | a_sBuildReqExpr TEXT, a_sBaseCmd TEXT, a_sTestSuiteZips TEXT);
|
---|
40 |
|
---|
41 | ---
|
---|
42 | -- Checks if the test case name is unique, ignoring a_idTestCaseIgnore.
|
---|
43 | -- Raises exception if duplicates are found.
|
---|
44 | --
|
---|
45 | -- @internal
|
---|
46 | --
|
---|
47 | CREATE OR REPLACE FUNCTION TestCaseLogic_checkUniqueName(a_sName TEXT, a_idTestCaseIgnore INTEGER)
|
---|
48 | RETURNS VOID AS $$
|
---|
49 | DECLARE
|
---|
50 | v_cRows INTEGER;
|
---|
51 | BEGIN
|
---|
52 | SELECT COUNT(*) INTO v_cRows
|
---|
53 | FROM TestCases
|
---|
54 | WHERE sName = a_sName
|
---|
55 | AND tsExpire = 'infinity'::TIMESTAMP
|
---|
56 | AND idTestCase <> a_idTestCaseIgnore;
|
---|
57 | IF v_cRows <> 0 THEN
|
---|
58 | RAISE EXCEPTION 'Duplicate test case name "%" (% times)', a_sName, v_cRows;
|
---|
59 | END IF;
|
---|
60 | END;
|
---|
61 | $$ LANGUAGE plpgsql;
|
---|
62 |
|
---|
63 | ---
|
---|
64 | -- Check that the test case exists.
|
---|
65 | -- Raises exception if it doesn't.
|
---|
66 | --
|
---|
67 | -- @internal
|
---|
68 | --
|
---|
69 | CREATE OR REPLACE FUNCTION TestCaseLogic_checkExists(a_idTestCase INTEGER) RETURNS VOID AS $$
|
---|
70 | BEGIN
|
---|
71 | IF NOT EXISTS( SELECT *
|
---|
72 | FROM TestCases
|
---|
73 | WHERE idTestCase = a_idTestCase
|
---|
74 | AND tsExpire = 'infinity'::TIMESTAMP ) THEN
|
---|
75 | RAISE EXCEPTION 'Test case with ID % does not currently exist', a_idTestCase;
|
---|
76 | END IF;
|
---|
77 | END;
|
---|
78 | $$ LANGUAGE plpgsql;
|
---|
79 |
|
---|
80 |
|
---|
81 | ---
|
---|
82 | -- Historize a row.
|
---|
83 | -- @internal
|
---|
84 | --
|
---|
85 | CREATE OR REPLACE FUNCTION TestCaseLogic_historizeEntry(a_idTestCase INTEGER, a_tsExpire TIMESTAMP WITH TIME ZONE)
|
---|
86 | RETURNS VOID AS $$
|
---|
87 | DECLARE
|
---|
88 | v_cUpdatedRows INTEGER;
|
---|
89 | BEGIN
|
---|
90 | UPDATE TestCases
|
---|
91 | SET tsExpire = a_tsExpire
|
---|
92 | WHERE idTestcase = a_idTestCase
|
---|
93 | AND tsExpire = 'infinity'::TIMESTAMP;
|
---|
94 | GET DIAGNOSTICS v_cUpdatedRows = ROW_COUNT;
|
---|
95 | IF v_cUpdatedRows <> 1 THEN
|
---|
96 | IF v_cUpdatedRows = 0 THEN
|
---|
97 | RAISE EXCEPTION 'Test case ID % does not currently exist', a_idTestCase;
|
---|
98 | END IF;
|
---|
99 | RAISE EXCEPTION 'Integrity error in TestCases: % current rows with idTestCase=%d', v_cUpdatedRows, a_idTestCase;
|
---|
100 | END IF;
|
---|
101 | END;
|
---|
102 | $$ LANGUAGE plpgsql;
|
---|
103 |
|
---|
104 |
|
---|
105 | CREATE OR REPLACE function TestCaseLogic_addEntry(a_uidAuthor INTEGER, a_sName TEXT, a_sDescription TEXT,
|
---|
106 | a_fEnabled BOOL, a_cSecTimeout INTEGER, a_sTestBoxReqExpr TEXT,
|
---|
107 | a_sBuildReqExpr TEXT, a_sBaseCmd TEXT, a_sTestSuiteZips TEXT,
|
---|
108 | a_sComment TEXT)
|
---|
109 | RETURNS INTEGER AS $$
|
---|
110 | DECLARE
|
---|
111 | v_idTestCase INTEGER;
|
---|
112 | BEGIN
|
---|
113 | PERFORM TestCaseLogic_checkUniqueName(a_sName, -1);
|
---|
114 |
|
---|
115 | INSERT INTO TestCases (uidAuthor, sName, sDescription, fEnabled, cSecTimeout,
|
---|
116 | sTestBoxReqExpr, sBuildReqExpr, sBaseCmd, sTestSuiteZips, sComment)
|
---|
117 | VALUES (a_uidAuthor, a_sName, a_sDescription, a_fEnabled, a_cSecTimeout,
|
---|
118 | a_sTestBoxReqExpr, a_sBuildReqExpr, a_sBaseCmd, a_sTestSuiteZips, a_sComment)
|
---|
119 | RETURNING idTestcase INTO v_idTestCase;
|
---|
120 | RETURN v_idTestCase;
|
---|
121 | END;
|
---|
122 | $$ LANGUAGE plpgsql;
|
---|
123 |
|
---|
124 |
|
---|
125 | CREATE OR REPLACE function TestCaseLogic_editEntry(a_uidAuthor INTEGER, a_idTestCase INTEGER, a_sName TEXT, a_sDescription TEXT,
|
---|
126 | a_fEnabled BOOL, a_cSecTimeout INTEGER, a_sTestBoxReqExpr TEXT,
|
---|
127 | a_sBuildReqExpr TEXT, a_sBaseCmd TEXT, a_sTestSuiteZips TEXT,
|
---|
128 | a_sComment TEXT)
|
---|
129 | RETURNS INTEGER AS $$
|
---|
130 | DECLARE
|
---|
131 | v_idGenTestCase INTEGER;
|
---|
132 | BEGIN
|
---|
133 | PERFORM TestCaseLogic_checkExists(a_idTestCase);
|
---|
134 | PERFORM TestCaseLogic_checkUniqueName(a_sName, a_idTestCase);
|
---|
135 |
|
---|
136 | PERFORM TestCaseLogic_historizeEntry(a_idTestCase, CURRENT_TIMESTAMP);
|
---|
137 | INSERT INTO TestCases (idTestCase, uidAuthor, sName, sDescription, fEnabled, cSecTimeout,
|
---|
138 | sTestBoxReqExpr, sBuildReqExpr, sBaseCmd, sTestSuiteZips, sComment)
|
---|
139 | VALUES (a_idTestCase, a_uidAuthor, a_sName, a_sDescription, a_fEnabled, a_cSecTimeout,
|
---|
140 | a_sTestBoxReqExpr, a_sBuildReqExpr, a_sBaseCmd, a_sTestSuiteZips, a_sComment)
|
---|
141 | RETURNING idGenTestCase INTO v_idGenTestCase;
|
---|
142 | RETURN v_idGenTestCase;
|
---|
143 | END;
|
---|
144 | $$ LANGUAGE plpgsql;
|
---|
145 |
|
---|
146 |
|
---|
147 | CREATE OR REPLACE FUNCTION TestCaseLogic_delEntry(a_uidAuthor INTEGER, a_idTestCase INTEGER, a_fCascade BOOLEAN)
|
---|
148 | RETURNS VOID AS $$
|
---|
149 | DECLARE
|
---|
150 | v_Row TestCases%ROWTYPE;
|
---|
151 | v_tsEffective TIMESTAMP WITH TIME ZONE;
|
---|
152 | v_Rec RECORD;
|
---|
153 | v_sErrors TEXT;
|
---|
154 | BEGIN
|
---|
155 | --
|
---|
156 | -- Check preconditions.
|
---|
157 | --
|
---|
158 | IF a_fCascade <> TRUE THEN
|
---|
159 | IF EXISTS( SELECT *
|
---|
160 | FROM TestCaseDeps
|
---|
161 | WHERE idTestCasePreReq = a_idTestCase
|
---|
162 | AND tsExpire = 'infinity'::TIMESTAMP ) THEN
|
---|
163 | v_sErrors := '';
|
---|
164 | FOR v_Rec IN
|
---|
165 | SELECT TestCases.idTestCase AS idTestCase,
|
---|
166 | TestCases.sName AS sName
|
---|
167 | FROM TestCaseDeps, TestCases
|
---|
168 | WHERE TestCaseDeps.idTestCasePreReq = a_idTestCase
|
---|
169 | AND TestCaseDeps.tsExpire = 'infinity'::TIMESTAMP
|
---|
170 | AND TestCases.idTestCase = TestCaseDeps.idTestCase
|
---|
171 | AND TestCases.tsExpire = 'infinity'::TIMESTAMP
|
---|
172 | LOOP
|
---|
173 | IF v_sErrors <> '' THEN
|
---|
174 | v_sErrors := v_sErrors || ', ';
|
---|
175 | END IF;
|
---|
176 | v_sErrors := v_sErrors || v_Rec.sName || ' (idTestCase=' || v_Rec.idTestCase || ')';
|
---|
177 | END LOOP;
|
---|
178 | RAISE EXCEPTION 'Other test cases depends on test case with ID %: % ', a_idTestCase, v_sErrors;
|
---|
179 | END IF;
|
---|
180 |
|
---|
181 | IF EXISTS( SELECT *
|
---|
182 | FROM TestGroupMembers
|
---|
183 | WHERE idTestCase = a_idTestCase
|
---|
184 | AND tsExpire = 'infinity'::TIMESTAMP ) THEN
|
---|
185 | v_sErrors := '';
|
---|
186 | FOR v_Rec IN
|
---|
187 | SELECT TestGroups.idTestGroup AS idTestGroup,
|
---|
188 | TestGroups.sName AS sName
|
---|
189 | FROM TestGroupMembers, TestGroups
|
---|
190 | WHERE TestGroupMembers.idTestCase = a_idTestCase
|
---|
191 | AND TestGroupMembers.tsExpire = 'infinity'::TIMESTAMP
|
---|
192 | AND TestGroupMembers.idTestGroup = TestGroups.idTestGroup
|
---|
193 | AND TestGroups.tsExpire = 'infinity'::TIMESTAMP
|
---|
194 | LOOP
|
---|
195 | IF v_sErrors <> '' THEN
|
---|
196 | v_sErrors := v_sErrors || ', ';
|
---|
197 | END IF;
|
---|
198 | v_sErrors := v_sErrors || v_Rec.sName || ' (idTestGroup=' || v_Rec.idTestGroup || ')';
|
---|
199 | END LOOP;
|
---|
200 | RAISE EXCEPTION 'Test case with ID % is member of the following test group(s): % ', a_idTestCase, v_sErrors;
|
---|
201 | END IF;
|
---|
202 | END IF;
|
---|
203 |
|
---|
204 | --
|
---|
205 | -- To preserve the information about who deleted the record, we try to
|
---|
206 | -- add a dummy record which expires immediately. I say try because of
|
---|
207 | -- the primary key, we must let the new record be valid for 1 us. :-(
|
---|
208 | --
|
---|
209 | SELECT * INTO STRICT v_Row
|
---|
210 | FROM TestCases
|
---|
211 | WHERE idTestCase = a_idTestCase
|
---|
212 | AND tsExpire = 'infinity'::TIMESTAMP;
|
---|
213 |
|
---|
214 | v_tsEffective := CURRENT_TIMESTAMP - INTERVAL '1 microsecond';
|
---|
215 | IF v_Row.tsEffective < v_tsEffective THEN
|
---|
216 | PERFORM TestCaseLogic_historizeEntry(a_idTestCase, v_tsEffective);
|
---|
217 | v_Row.tsEffective := v_tsEffective;
|
---|
218 | v_Row.tsExpire := CURRENT_TIMESTAMP;
|
---|
219 | v_Row.uidAuthor := a_uidAuthor;
|
---|
220 | SELECT NEXTVAL('TestCaseGenIdSeq') INTO v_Row.idGenTestCase;
|
---|
221 | INSERT INTO TestCases VALUES (v_Row.*);
|
---|
222 | ELSE
|
---|
223 | PERFORM TestCaseLogic_historizeEntry(a_idTestCase, CURRENT_TIMESTAMP);
|
---|
224 | END IF;
|
---|
225 |
|
---|
226 | --
|
---|
227 | -- Delete arguments, test case dependencies and resource dependencies.
|
---|
228 | -- (We don't bother recording who deleted the records here since it's
|
---|
229 | -- a lot of work and sufficiently covered in the TestCases table.)
|
---|
230 | --
|
---|
231 | UPDATE TestCaseArgs
|
---|
232 | SET tsExpire = CURRENT_TIMESTAMP
|
---|
233 | WHERE idTestCase = a_idTestCase
|
---|
234 | AND tsExpire = 'infinity'::TIMESTAMP;
|
---|
235 |
|
---|
236 | UPDATE TestCaseDeps
|
---|
237 | SET tsExpire = CURRENT_TIMESTAMP
|
---|
238 | WHERE idTestCase = a_idTestCase
|
---|
239 | AND tsExpire = 'infinity'::TIMESTAMP;
|
---|
240 |
|
---|
241 | UPDATE TestCaseGlobalRsrcDeps
|
---|
242 | SET tsExpire = CURRENT_TIMESTAMP
|
---|
243 | WHERE idTestCase = a_idTestCase
|
---|
244 | AND tsExpire = 'infinity'::TIMESTAMP;
|
---|
245 |
|
---|
246 | IF a_fCascade = TRUE THEN
|
---|
247 | UPDATE TestCaseDeps
|
---|
248 | SET tsExpire = CURRENT_TIMESTAMP
|
---|
249 | WHERE idTestCasePreReq = a_idTestCase
|
---|
250 | AND tsExpire = 'infinity'::TIMESTAMP;
|
---|
251 |
|
---|
252 | UPDATE TestGroupMembers
|
---|
253 | SET tsExpire = CURRENT_TIMESTAMP
|
---|
254 | WHERE idTestCase = a_idTestCase
|
---|
255 | AND tsExpire = 'infinity'::TIMESTAMP;
|
---|
256 | END IF;
|
---|
257 |
|
---|
258 | EXCEPTION
|
---|
259 | WHEN NO_DATA_FOUND THEN
|
---|
260 | RAISE EXCEPTION 'Test case with ID % does not currently exist', a_idTestCase;
|
---|
261 | WHEN TOO_MANY_ROWS THEN
|
---|
262 | RAISE EXCEPTION 'Integrity error in TestCases: Too many current rows for %', a_idTestCase;
|
---|
263 | END;
|
---|
264 | $$ LANGUAGE plpgsql;
|
---|
265 |
|
---|