Testing of Non-deterministic Client

advertisement
Testing of Non-deterministic Client-server Database Applications
Gwan-Hwan Hwang*
Dept. Information Management
National Chi-nan University
Puli, Taiwan 545
Huey-Der Chu
Dept. Information Management
National Defense Management College
Chungho, Taiwan 235
Abstract
An execution of a client-server application
with database access exercises a sequence of database
transaction events, calls a transaction sequence (or
T-sequence). A client-server database application may
have non-deterministic behavior, since its multiple
executions with the same input may produce different
T-sequences. In this paper, we present a framework for
testing all possible T-sequences of a client-server
database application. Such testing is referred to as
reachability testing. We define race conditions between
transactions. For a collected T-sequence, we show how to
change the outcomes of race conditions in order to derive
race-variants, which are prefixes of other T-sequences.
Finally, we discuss how to perform prefix-based testing
of a database application, according to a race-variant, in
order to generate new T-sequences.
Keywords:
client-server,
client-server
testing,
non-deterministic behavior, SQL transaction, database
1 Introduction
Given the nature of client-server applications, a
significant degree of randomness exists in terms of
the way in which a component or an object may be
selected. Likewise, these components or objects
may be selected in several different orders.
Therefore, there may be non-deterministic
behaviors within the client-server applications. As a
result of non-deterministic behavior, multiple
executions of a client-server application with the
same input scripts may execute different paths and
produce different results. The complexity of the
client-server makes testing more difficult and poses
new challenges to the development organization
[2,5]. This problem might arise when the same
portion of shared data is simultaneously accessed
from different clients without the consideration of
mutual exclusive access. Moreover, when testing
client-server applications, there is rarely ever
testing performed which specifically addresses the
database and the statements that access it [4]. The
following shows an example which a client-server
application with SQL transactions was proven with
*
G. H. Hwang’s work was supported in part by the ROC
National Science Council under grant 89-2218-E-260-016
and ROC MOE/NSC program for promoting academic
excellence of universities under grant 89-E-FA04-1-4.
Kuo-Chung Tai
Dept. of Computer Science
North Carolina State Univ.
Raleigh, NC 27695-7534, USA
non-deterministic behavior [1]. It is a 3-tier banking
client/server application written using Java Remote
Method Invocation (RMI) and Java DataBase
Connectivity (JDBC).
As shown in Figure 1, the same test data
“test1.in” are sent to two clients which execute in
“Anick” (an Windows PC) and “Kielder” (an Unix
Sun workstation) respectively. The “test1.in”
represents a simplified form of a series of SQL
transactions which the clients are going to proceed.
According to the experiments in [1], multiple
executions produced different results. The reason is
that different executions across the two clients may
have different interleave of SQL transactions which
issue by “Anick” and “Kielder”. However, there is
no solution to overcome the non-deterministic
behavior in [1].
What we want to find in this paper is whether
or not we can find all the possible behaviors, i.e. all
the possible interleave of access to the shared data,
for execution of a client-server applications with
SQL transactions. The reachability testing which
presents in [3] provides a way to overcome the
non-deterministic behavior. If every execution of P
with input X terminates, reachability testing of P
with input X can accomplish exhaustive testing of P
with input X, and thus can determine the
correctness of P with X. However, [3] only
provides reachability testing for shared-memory
concurrent programs. The essence of reachability
testing includes both the race analysis and the
prefixed-based testing. Compared with reachability
testing for shared-memory model of concurrent
programs, the race analysis for SQL database
access is more complicated: (1) each transaction
may access multiple rows among multiple tables as
opposed to the shared-memory model which each
“read” or “write” operation only accesses to a
single variable; (2) a transaction may insert or
delete rows from tables as opposed to the
shared-memory model which the variables are
allocated statically. We define the appropriate data
structure of the transaction event and the
transaction-sequence for the sophisticated race
analysis. Also, the scheme to activate prefix-based
testing in the client-server SQL application is not
addressed in previous work. We suggest two
solutions: the first one is to use the standard
synchronization mechanism in SQL server and the
other is to let the SQL server control and monitor
the order of transaction events.
In Section 2 of this paper, concept of
reachability testing is presented. The distinction of
the reachability testing between shared-memory
concurrent programs and client-server database
applications is described in Section 3. Section 4
defines the transaction race relation and shows how
to detect transaction-race of two transaction events
in a transaction-sequence. In Section 5, an
algorithm is presented for deriving race-variants of
a transaction-sequence. Section 6 briefly describes
how to implement the prefix-based testing for the
transaction-sequence. Section 7 summarizes this
paper.
9700(account#)
Current(account type)
1112(password)
2(deposit)
500
1(balance)
3(withdraw)
2(deposit)
57
5(exit)
ck
test1.in on Anick
9700(account#)
Current(account type)
1112(password)
2(deposit)
500
1(balance)
3(withdraw)
2(deposit)
57
5(exit)
Deposited 500.00 balanced is 2441.0
The balance is:2941.0
Withdraw 350.00 balance is :2591.0
Deposited 57.00 balance is :2705.0.
The
Banking
Application
Execution result of Anick
Execute result of Kielder
Execution result of Kielder
Deposited 500.00 balanced is 2941.0
The balance is:2941.0
Withdraw 350.00 balance is :2591.0
Deposited 57.00 balance is :2648.0.
**Account No.970001 from ->Anick Deposited(e32)
**Account No.970001 from ->Kielder Deposited(e32)
**Account No.970001 from ->Anick Check Balance(e31)
**Account No.970001 from ->Kielder Check Balance(e31)
**Account No.970001 from ->Kielder Withdraw(e33)
**Account No.970001 from ->Anick Withdraw(e33)
**Account No.970001 from ->Kielder Deposited(e32)
**Account No.970001 from ->Anick Deposited(e32)
test1.in on Kielder
Transaction processed by the SQL server in total order
Figure 1: Two applications under test with the same input
2 Concepts of Reachability Testing
An execution of a concurrent program
non-deterministically exercises a sequence of
synchronization events called a synchronization
sequence (or SYN-sequence). The format of a
SYN-sequence of a concurrent program depends on
the concurrent constructs used.
Assume that every execution of P with input X
terminates. A general description of reachability
testing of P with input X is the following:
Step 1: Perform non-deterministic testing of P
with input X to collect some (feasible) SYN-sequences.
Step 2: For each collected SYN-sequence S, derive
its race-variants by changing the outcome of race
conditions in S. These race-variants are prefixes of
other SYN-sequences of P with input X.
Step 3: For each new race-variant derived in Step
2, perform prefix-based testing of P with input X and
the race-variant to execute and collect additional
SYN-sequences for P with input X. The prefix-based
testing of P with race-variant R is first to replay all the
synchronization events in R then records the
subsequent synchronization events after replaying of
R.
Step 4: For each new SYN-sequence collected in
Step 3, repeated Step 2, 3 and 4.
In the database access environments in
client-server perspective, P contains all the clients
and databases in servers. X covers input for each
client and the initial state for each database.
3 Approaches to Testing Client-server
applications
In the client-server environment, clients and
servers are separate logical entities that work
together over a network to accomplish a task.
Multiple clients may request data-related services
from a database concurrently. The database server
responses to the clients' requests and provides
secured access to shared data. The request is
represented in a standard query language such as
SQL. The concurrent queries of several clients to
the same database may race the same portion of
shared data. The majority of the modern SQL
servers are transaction servers. With a transaction
server, the client invokes remote procedures that
reside on the server with a SQL database engine.
There remote procedures on the server execute a
group of SQL statements call a transaction. The
SQL statements either all succeed or fail as a unit.
Also, a transaction will lock the accessed data
automatically. The special case of a transaction is a
transaction with only one query statement.
In [3], it showed how to perform reachability
testing of concurrent programs using read and write
operations. Compared with concurrent access to
relational database, the data-sharing model of
relational database is far more complicated than
shared-memory model in [3]. First, the data
manipulation language of relational database
includes "INSERT", "DELETE", "UPDATE",
"SELECT", “JOIN”, “STORED PROCEDURE”,
“TRIGGER”, “RULE”, “CURSOR” and so on. A
single SQL statement may refer to multiple tables
which contain multiple rows (as opposed to
shared-memory model which each read or write
operation only access to a single shared-variable).
Second, the shared-memory model in [3] is with
fixed number of shared-variables which are
declared and initialized before program execution.
However, with the "INSERT" and "DELETE"
operations in relational database, the amount of
data in any table may vary depending on the
transaction operations of clients. Some relational
data provides execution log which records all the
SQL statements issued in this server for
administration. However, this kind of information is
insufficient to do race analysis for transaction
events. Therefore, the next section defines the
transaction race relation and shows how to detect
transaction-race of two transaction events in a
transaction-sequence.
4 Transaction-sequences and Race
Analysis for Client-server programs
Let the client-server application P containing
clients CL1, CL2, ..., CLn and relational database
DB1, DB2, ... and DBm among all the database
transaction servers, n>1, m>0. Note that there may
be more than one database in a database transaction
server. An execution of P exercises a sequence of
database
transactions,
referred
to
a
transaction-sequence (or T-sequence). More
specifically, a transaction-sequence of P is denoted
as (T1 , ... , Ti , ... , Tx), where Ti, 1  i  x, is a
transaction event.
Consider the following two SQL statements:
Statement 1: Read rows from “table 1” where
the column value of “value1” is equal to “1”,
SELECT *
FROM table1
WHERE table1.value1=”1”
Statement 2: Modify rows from “table 2“ where
the column value of “value2” is equal to “2”,
UPDATE table1
SET table1.value2=”3”
WHERE table1.value2=”2”
There is a race between statement 1 and 2 only
if there is a row in table 1 where “value1”=”1” and
“value2”=”2”. This example shows that the
existence of races between two SQL statements
may depend on the states of the database. Thus, for
the race analysis, the data structure of a T-sequence
should contain more information than the
RW-sequence defined in [3]. We define the
transaction-event as the following data structure.
Ta={ Database_name, Database _transaction_order,
Client_name, Client_transaction_order,
[table_name1, row_primary_key1, operation1],
.
[table_namei, row_primary_keyi, operationi],,
.
[table_names, row_primary_keys, operations]
}
Ta is a transaction event. In the header of a
transaction event, it records the name of the
database and the name of the requested client which
are
"Database_name"
and
"Client_name"
respectively. Each database is assigned a
transaction number, which is initialized to one and
increased by one after each transaction on this
database. "Database_Transaction_order" records
the relative order of this transaction among all
transactions executed on the database by different
clients. Similarly, the "Client_Transaction_order"
indicates the relative order of this transaction
among all transactions executed by the client.
After the header, there is a serial of accessed
row records. We have mentioned that a single SQL
statement may access multiple rows from multiple
tables. For the race analysis, we translate each SQL
statement into multiple accessed row records. For
each accessed row in a SQL statement, there is a
3-tuple representation to show the access details
including "table_namei", "row_primary_keyi" and
"operationi", 1 i  s. They represent the table
name, the corresponding primary key value of this
row, and operation to this row respectively. We
summarize the operation to have "insert", "read",
"update", and "delete". The combination of these
four operations can represent any SQL data
manipulation statements. Since a transaction may
contain multiple SQL statements, we should
include accessed row records of each single SQL
statement in the transaction event.
In the follows, we define the transaction race
relation of two transaction events. Two transaction
events are said to have transaction-race if they may
access the same portion of data in the same
database and the different execution order of them
may cause different execution results.
Definition: For a transaction-sequence or
T-sequence (T1, T2, ..., Ty),
Tu={Database_nameu , Database_transaction_orderu ,
Client_nameu , Client_Transaction_orderu ,
[table_nameu1, row_primary_key u1, operation u1],
.
[table_nameui, row_primary_keyui, operationui],
.
[table_nameul, row_primary_keyul, operationul]
},
and
Tv={Database_namev, Database_transaction_orderv,
Client_namev, Client_Transaction_orderv,
[table_namev1, row_ primary_key v1, operation v1],
.
[table_namevj, row_primary_keyvj, operationvj],
.
[table_namevl’, row_primary_key vl’, operation vl’]
},
where 1 u, v  y and u≠v are said to have a
transation-race if either (1) or (2) holds:
(1) Client_nameu≠Client_namev,
Database_nameu=Database_namev, and
there exists i and j such that 1 i l, 1 j l’ ,
table_nameui=table_namevj,
row_primary_keyui=row_primary_keyvj,
at least one of the operationui and operationvj is
"update", and
none of operationui and operationvj is "insert" or
“delete”.
(2) Client_nameu≠Client_namev,
Database_nameu=Database_namev, and
there exists i and j such that 1 i l, 1 j l’ ,
table_nameui=table_namevj, and
at least one of operationui and operationvj is "insert"
or "delete".
End of Definition
In condition (1), it shows two transactions race
the same portion in database server if two
operations access the same row (the same table
with the same primary key), and one of the row
operations is "update" and the other is either
"update" or "read". However, in condition (2),
only with accessing to the same table and one of the
operations is either "insert" or "delete", the race
may exist. Using primary key to identify the race is
sufficient for the "update" and "read" operations. It
is because two separate rows in a table have
different primary keys according to the definition of
relational database. However, it is insufficient to
use primary key to identify race for "insert" or
"delete" operations. Consider the following
example. Assume the table is the "table 1" of
database "DBS" and the column "id" is the primary
key of table 1.
Id
1
2
3
4
Amount
100
200
500
1000
Client 1 issues the following operation:
INSERT INTO “Table 1”
VALUES (5, 700)
It is to insert a row (id=5, amount=700) into
table 1 in database DBS. Client 2 issues the
following operation:
SELECT *
FROM “Table 1”
WHERE “Table 1”.”amount”>=500
It selects rows from table 1 in DBS where
amount  500. If the execution of Client 1 is prior
to Client 2, then the transaction event of client 1
and 2 are
{DBS, 1, Client 1, 1,
and {DBS, 2, Client 2, 1,
[table1, 5, insert]
[table1, 3, read],
[table1, 4, read],
[table1, 5, read]
}
}
respectively. By observing the primary key
information in the two transaction event, it is
obviously that the two clients race because they
access the same row. However, If the execution of
Client 2 is prior to Client 1, then the transaction
event of client 1 and 2 are
{DBS, 1, Client 2, 1,
and {DBS, 2, Client 1, 1,
[table1, 3, read],
[table1, 4, read]
[table1, 5, insert]
}
}
respectively. The primary key information in the
transaction events does not show the race. For the
"delete" operation, it is with the similar situation. It
is true that one "insert" and one "read" may not
access to the same row. However, to make sure that
we should not skip any specific race condition, we
assume there is a transaction-race if one of the
operations is either “delete” or “insert” operation.
5 Derive Race-variants from a
Transaction-sequence
Section 4 defines the format of a
transaction-sequence and shows how to detect
transaction-race of two transaction events in a
transaction-sequence. This section presents an
algorithm for deriving race-variants of a
transaction-sequence.
Let the client-server application P containing
clients CL1, CL2, ..., CLn and relational database
DB1, DB2, ... and DBm among all the database
transaction servers, n > 1, m > 0. Let TS be a
feasible T-sequence of P with input X. X contains
input for each client and the initial state for each
database. For the convenience, we definition the
following notations: (1) TS(CLi) is the ordered set
of the transaction events of Client CLi; (2) TS(CLi,
j) is the jth transaction event of Client CLi. It is
trivial that both TS(CLi) and TS(CLi, j) can be
easily derived from the TS according to the
definition of transaction event.
5.1 Derive the happened-before
relationship between each pair of
transaction events
Before we present how to derive race-variants
for a T-sequence, we show how to construct a
directed partially-ordered graph of a T-sequence.
The partially-ordered graph is used to determine if
there exists a change of race in Algorithm 2 of
Section 5.2. The vertices in a partially-ordered
graph are transaction events. If there is a path from
one vertex to another vertex in the graph, there is a
happened-before relation of the two transaction
events.
Algorithm 1:Generat Partially-ordered graph of a
T-sequence
Input: TS={T1,T2,…,Tn}, a T-sequence
Output: G, the produced partially-ordered graph
according to TS
(1) Add each transaction-event of TS to G as a
vertex.
(2) For the transaction events of the same
client. Add edge from the transaction event
with (client_transaction_order = i) to the
transaction with (client_transaction_order
= i+1), where 1  i < the maximum value of
client_transaction_order of the client.
(3) Add edge (Tx, Ty) to G if Tx and Ty have race
and the database transaction number of Ty
is greater than Tx.
(4) Remove edge(Tp, Tq) from G if
 there exists another path from Tp to Tq in
G, and
 Tp and Tq are not transaction events of the
same client.
End of Algorithm 1
Assume Ta and Tb are transaction evnets in G,
i.e., vertices in G. Ta is happened before Tb if
there is a path from Ta to Tb in G.
We use the following example to illustrate
Algorithm 1. Assume there are two database DB1
and DB2; three clients C0, C1 and C2; TS includes
the following transaction events:
TS(C1,1)={ DB1 ,1, C1,1,…,},
TS(C2,1)={ DB1 ,2, C2,1,…,},
TS(C1,2)={ DB2 ,1, C1,2,…,},
TS(C3,1)={ DB2 ,2, C3,1,…,},
TS(C2,2)={ DB2 ,3, C2,2,…,},
TS(C2,3)={ DB1 ,3, C2,3,…,},
TS(C1,3)={ DB1 ,4, C1,3,…,},
For simplicity, we only list the database name,
database transaction order, client name and client
transaction order in the transaction events. Also,
assume the race situation is shown as following
table:
TS(C1,1) TS(C1,2) TS(C1,3
TS(C1,1)
TS(C1,2)
TS(C1,3
TS(C2,1)
TS(C2,2)
TS(C2,3)
TS(C3,1)
TS(C2,1) TS(C2,2) TS(C2,3) TS(C3,1)
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
Notes that “yes” means there exists a
transaction-race between two transaction events.
After Step (1) and (2), we have G as following:
TS(C1,1)
TS(C2,1)
TS(C1,2)
TS(C2,2)
TS(C1,3)
TS(C2,3)
TS(C3,1)
After Step (3), we obtain:
TS(C1,1)
TS(C2,1)
TS(C1,2)
TS(C2,2)
TS(C1,3)
TS(C2,3)
TS(C3,1)
Finally, we derive G is as following:
TS(C1,1)
TS(C2,1)
TS(C1,2)
TS(C2,2)
TS(C1,3)
TS(C2,3)
TS(C3,1)
5.2 Derive race-variants from
transaction-sequence and its
partially-ordered graph
To derive the possible race-variants of TS, we
construct the race-variant diagram (or RV-diagram)
for TS, which is a tree with each node representing
a prefix or race-variant of TS. The nodes in the RV
diagram for TS are generated by considering all the
possible interleavings of transaction events. For a
node in the RV diagram for TS, the path from the
root node of the diagram to this node is a
totally-ordered sequence of transaction events. The
RV-diagram scheme was first proposed in [3],
which uses the version number of variable access to
determine if there exists a different race outcomes
in the nodes of RV-diagram. However, the
transaction order is insufficient for race analysis in
transaction-sequence (As shown in the example of
Section 5.1, TS(C1,2) and TS(C3,1) access to the
same database but do not race. Reordering of this
two transaction events does not change the race
condition. Since version number is insufficient to
determine whether race conditions are changed, the
RV diagram defined in [3] is insufficient. Therefore,
we add a transaction event set in the node of
RV-diagram.
Each node N in the RV diagram for S contains
two vectors which are used in [3] and a set of
transaction events which is used to determine if the
race conditions are changed. See the follows:
Client transaction order vector: (I1, I2, …, In),
where Ij, 1  j  n, is the order number of the
last transaction event in client CLj that is
executed for generated node N.
Database transaction order vector: (E1,E2, …,
Em), where Ek, 1  k  m, is the transaction
order number of database DBk when node N is
generated.
Transaction event set: contains the transaction
events in order which node N is generated. It
contains a race-variant if N is a race-variant
node.
The following algorithm shows how to drive
race-variants from a T-sequence. Assume the target
T-sequence is TS.
Algorithm 2: Derive all the race-variants from a
T-sequence
Input: A T-sequence TS
Output: A set RV which contains all the possible
race-variants of TS
(1) Call Algorithm 1 to generate
partially-ordered graph G of TS
(2) Initially, the RV diagram of TS contains the
root node only, set its client transaction
order vector to (0,0,…,0), its database
transaction order vector to (0,0,…,0), and
transaction event set to be empty set. Also,
Label the root node “unmarked”.
(3) Select an unmarked node, say N, in the RV
diagram for TS. Assume that the client
transaction order vector of N is (I1, I2,…,
Ij, …,In). For each j, 1<=j<=n, if Ij<the
length of T(CLj), construct a child node N’ of
N according to step (a) – (c). Then label N
“marked”
(a) Set the client transaction order vector
of N’ to that of N except that the jth
number is Ij+1.
(b) Set the database transaction order
vector of N’ to that of N.
(c) Assume T(CLj,Ij+1)= {DBk , x, CLj,
Ij+1, …….} and E is the kth element in
database transaction order vector.
Set the kth element in database
transaction order vector to E+1.
Add a transaction event {DBk,
E+1,CLj,Ij+1,…….} to the transaction
event set of N’.
IF there exists a transaction event in G
which is happened before T(CLj,Ij+1)
and is not in the transaction event
set of N’
THEN
 Label N’ “marked” and
“race-variant node”
 Add the transaction event set to
RV(TS)
ELSE
If the RV diagram for TS already
contains a node with the same client
transaction order vector and
database transaction order vector,
then label N’ “marked”, else label N’
“unmarked”
(4) Repeat (3) until all the nodes are marked.
End of Algorithm 2
We use the T-sequence TS in the running
example of Section 5.1 to illustrate Algorithm 2.
Figure 2 is part of the race-variant diagram
generated from TS. Because of space limitation, we
do not show the whole graph. There are two
race-variant nodes.
6 Prefix-based testing of T-sequence
The prefix-based testing is necessary for the
reachability test. In the first phase of prefix-based
testing for a race-variant R, the execution of the
concurrent application is controlled to follow the
order of the synchronization events in R. It is
referred to as the reply phase. Note that R is only a
prefix of some T-sequence. After all the
synchronization events in the R are replayed, it then
proceeds to the monitor phase. The concurrent
application is executed and the successive
synchronization events of the concurrent
application are recorded. Combining R and
recorded synchronization events, a feasible
T-sequence of the concurrent application is
obtained.
The prefix-based testing for shared-memory
model is presented in [6,7]. For each shared object
(variable), there is a version number maintained in
the system. Before the prefix-based testing, a
program is processed by a preprocessor. The
preprocessor inserts entry and exit section codes
before and behind each synchronization statement
respectively. The codes in entry and exit sections
contain synchronization statements such as
semaphore to fulfill the reply and monitor phases.
However, the shared-memory model in [6,7] is
different from the client-server SQL transaction
model. We redesign the entry and exit section by
using the data lock and unlock operations in the
standard SQL to control the replay and monitor
phase of prefix-based testing. Similar to the work in
[6,7], entry and exit sections should be inserted into
the source codes of the client program before the
prefix-based testing. In this scenario, the SQL
server does not need any special design to support
reachability testing.
Usually, it is impossible to get the source codes
of the target concurrent applications as we may
only have the binary codes. However, if a SQL
server could have specific design to support
reachability testing, then the source code
modification is avoidable. The way to implement
this is to enhance the SQL server to have the ability
to understand and analyze the data structure of
T-sequence, i.e., it could analyze a T-sequence to
know the partial order of the transaction events of it.
Before the prefix-based testing of a race-variant R
proceeds, the SQL server reads and analyzes R.
Then, the SQL server will control the proceeding of
the transactions according to the analysis of R in
the reply phase. For the second monitor phase, the
SQL server just records the transactions issued by
each client. Combining the recorded transaction
events and R, it derives a feasible T-sequence. Since
all the reply and monitor tasks are handled by the
SQL server, it is no need for a preprocessor to insert
the codes entry and exit sections to the source
codes of the client program.
7 Conclusion
Concurrent software is very difficult to test and
validate because of its non-deterministic behavior
which multiple executions of a single concurrent
program with the same input may produce different
results. In this paper, we focus on the testing of
client-server applications which SQL transactions
are issued by clients concurrently. We show an
example to demonstrate the non-deterministic
behavior. It is an application with multiple clients
which issue SQL transactions to database server
concurrently. In this paper, we first propose to use
reachability
testing
to
overcome
the
non-deterministic behavior for client-server SQL
applications. Compared with reachability testing for
shared-memory model of concurrent programs, the
race analysis for database access is more
complicated: (1) each transaction may access
Race variant node
Prefix node
multiple rows among multiple tables as opposed to
the shared-memory model which each “read” or
“write” operation only accesses to a single variable;
(2) a transaction may insert or delete rows from
tables as opposed to the shared-memory model
which the variables are allocated statically. We
define the appropriate data structure of the
transaction event and the transaction-sequence for
the sophisticated race analysis. Accordingly, the
definition of race between transaction events and an
algorithm to derive the race-variants from a
transaction-sequence are also presented to support
reachability testing.
“marked”
(0,0,0)
(0,0)
{}
Client transaction version vector
Database transaction version vector
Transaction event set
“marked”
“marked”
(1,0,0)
(1,0)
{TS(C1,1)=[DB1,1,Cl,1]}
(0,1,0)
(1,0)
{TS(C2,1)=[DB1,1,C2,1]}
“unmarked”
“unmarked”
(0,0,1)
(0,1)
{TS(C3,1)=[DB2,1,C3,1]}
“marked”
(2,0,0)
(1,1)
{TS(C1,1)=[DB1,1,Cl,1],
TS(C1,2)=[DB2,1,Cl,2] }
(1,1,0)
(2,0)
{TS(C1,1)=[DB1,1,Cl,1],
TS(C2,1)=[DB1,2,C2,1] }
“unmarked”
(1,0,1)
(1,1)
{TS(C1,1)=[DB1,1,Cl,1],
TS(C3,1)=[DB2,1,C3,1]}
“marked”
“unmarked”
(2,1,0)
(2,1)
{TS(C1,1)=[DB1,1,Cl,1],
TS(C2,1)=[DB1,2,C2,1],
TS(C1,2)=[DB2,1,C1,2]}
“unmarked”
(1,2,0)
(2,1)
{TS(C1,1)=[DB1,1,Cl,1],
TS(C2,1)=[DB1,2,C2,1],
TS(C2,2)=[DB2,1,C2,2]}
(1,1,1)
(2,1)
{TS(C1,1)=[DB1,1,Cl,1],
TS(C2,1)=[DB1,2,C2,1],
TS(C3,1)=[DB2,1,C3,1]}
Figure 2: Example of race-variant diagram
Put on another way, the scheme to activate
prefix-based testing in client-server SQL
application is not addressed in previous work. We
suggest two solutions. The first one is to use the
standard synchronization mechanism in SQL server.
It is similar to the previous proposed schemes. One
of its drawbacks is that it needs a preprocessor to
modify the source codes of the client programs.
Since all the transactions issued by clients are
processed by the SQL server, we propose another
way for prefix-based testing. It is to let the SQL
server replay and monitor the order of transaction
events.
Reference
[1]Chu, H. and Dobson, J. Towards Quality
Programming in the Automated Testing of
Client/Server Applications. In Proc. of PNSQC98
and join with ICSQ'98, Oct. 1998, Oregon, USA.
[2]Gerrard, P., Testing Client/Server Systems,
Available
at
http://www.evolutif.co.uk/articles/cstesting.html.
[3]Hwang, G. H., Tai, K. C., and Huang, T.L.,
Reachability Testing: an approach to testing
concurrent software, Inter. Journal of Software Eng.
and Knowledge Eng., 5, 4, (Dec. 1995), 493-510.
[4]Ranade, J., Testing Client/Server Systems,
McGraw-Hill, Inc., 1997.
[5]Ulrich, A.W., Zimmerer, P. and Chrobok-Diening,
G., Test Architectures for Testing Distributed
Systems. Workshop on Testing Distributed
Component-Based
Systems,
Los
Angeles,
California, May 1999.
[6]Thomas J. LeBlanc and John M. Mellor-Crummey,
Debugging Parallel Programs with Instant Replay,
IEEE Transactions on Computers, C-36(4), pp.
471-482, April 1987.
[7]Gwan-Hwan Hwang, A Systematic Parallel Testing
Method for Concurrent Programs, Master Thesis,
Institute of Computer Science and Information
Engineering, National Chiao-Tung University,
Taiwan, 1993.
Download