successfully discovered TD-250 crash bug, with params: -p -d -s 3 -t 3
This commit is contained in:
parent
58153639c5
commit
a3671929fb
|
@ -405,6 +405,9 @@ class DbState():
|
|||
tIndex = self.tableNumQueue.push()
|
||||
return tIndex
|
||||
|
||||
def getFixedTableName(self):
|
||||
return "fixed_table"
|
||||
|
||||
def releaseTable(self, i): # return the table back, so others can use it
|
||||
self.tableNumQueue.release(i)
|
||||
|
||||
|
@ -433,9 +436,13 @@ class DbState():
|
|||
|
||||
def getTasksAtState(self):
|
||||
if ( self._state == self.STATE_EMPTY ):
|
||||
return [CreateDbTask(self), CreateTableTask(self)]
|
||||
return [CreateDbTask(self), CreateFixedTableTask(self)]
|
||||
elif ( self._state == self.STATE_DB_ONLY ):
|
||||
return [DeleteDbTask(self), CreateTableTask(self), AddDataTask(self)]
|
||||
return [DropDbTask(self), CreateFixedTableTask(self), AddFixedDataTask(self)]
|
||||
elif ( self._state == self.STATE_TABLE_ONLY ):
|
||||
return [DropFixedTableTask(self), AddFixedDataTask(self)]
|
||||
elif ( self._state == self.STATE_HAS_DATA ) : # same as above. TODO: adjust
|
||||
return [DropFixedTableTask(self), AddFixedDataTask(self)]
|
||||
else:
|
||||
raise RuntimeError("Unexpected DbState state: {}".format(self._state))
|
||||
|
||||
|
@ -443,13 +450,58 @@ class DbState():
|
|||
if ( len(tasks) == 0 ): # before 1st step, or otherwise empty
|
||||
return # do nothing
|
||||
if ( self._state == self.STATE_EMPTY ):
|
||||
self.assertAtMostOneSuccess(tasks, CreateDbTask) # param is class
|
||||
self.assertIfExistThenSuccess(tasks, CreateDbTask)
|
||||
self.assertAtMostOneSuccess(tasks, CreateTableTask)
|
||||
if ( self.hasSuccess(tasks, CreateDbTask) ):
|
||||
self.assertAtMostOneSuccess(tasks, CreateDbTask) # param is class
|
||||
self._state = self.STATE_DB_ONLY
|
||||
if ( self.hasSuccess(tasks, CreateTableTask) ):
|
||||
self._state = self.STATE_TABLE_ONLY
|
||||
if ( self.hasSuccess(tasks, CreateFixedTableTask )):
|
||||
self._state = self.STATE_TABLE_ONLY
|
||||
# else: # no successful table creation, not much we can say, as it is step 2
|
||||
else: # did not create db
|
||||
self.assertNoTask(tasks, CreateDbTask) # because we did not have such task
|
||||
# self.assertNoSuccess(tasks, CreateDbTask) # not necessary, since we just verified no such task
|
||||
self.assertNoSuccess(tasks, CreateFixedTableTask)
|
||||
|
||||
elif ( self._state == self.STATE_DB_ONLY ):
|
||||
self.assertAtMostOneSuccess(tasks, DropDbTask)
|
||||
self.assertIfExistThenSuccess(tasks, DropDbTask)
|
||||
self.assertAtMostOneSuccess(tasks, CreateFixedTableTask)
|
||||
# Nothing to be said about adding data task
|
||||
if ( self.hasSuccess(tasks, DropDbTask) ): # dropped the DB
|
||||
# self.assertHasTask(tasks, DropDbTask) # implied by hasSuccess
|
||||
self.assertAtMostOneSuccess(tasks, DropDbTask)
|
||||
self._state = self.STATE_EMPTY
|
||||
elif ( self.hasSuccess(tasks, CreateFixedTableTask) ): # did not drop db, create table success
|
||||
# self.assertHasTask(tasks, CreateFixedTableTask) # tried to create table
|
||||
self.assertAtMostOneSuccess(tasks, CreateFixedTableTask) # at most 1 attempt is successful
|
||||
self.assertNoTask(tasks, DropDbTask) # should have have tried
|
||||
if ( not self.hasSuccess(tasks, AddFixedDataTask) ): # just created table, no data yet
|
||||
# can't say there's add-data attempts, since they may all fail
|
||||
self._state = self.STATE_TABLE_ONLY
|
||||
else:
|
||||
self._state = self.STATE_HAS_DATA
|
||||
else: # no success in dropping db tasks, no success in create fixed table, not acceptable
|
||||
raise RuntimeError("Unexpected no-success scenario")
|
||||
|
||||
elif ( self._state == self.STATE_TABLE_ONLY ):
|
||||
if ( self.hasSuccess(tasks, DropFixedTableTask) ):
|
||||
self.assertAtMostOneSuccess(tasks, DropFixedTableTask)
|
||||
self._state = self.STATE_DB_ONLY
|
||||
elif ( self.hasSuccess(tasks, AddFixedDataTask) ): # no success dropping the table
|
||||
self.assertNoTask(tasks, DropFixedTableTask)
|
||||
self._state = self.STATE_HAS_DATA
|
||||
else: # did not drop table, did not insert data, that is impossible
|
||||
raise RuntimeError("Unexpected no-success scenarios")
|
||||
|
||||
elif ( self._state == self.STATE_TABLE_ONLY ): # Same as above, TODO: adjust
|
||||
if ( self.hasSuccess(tasks, DropFixedTableTask) ):
|
||||
self.assertAtMostOneSuccess(tasks, DropFixedTableTask)
|
||||
self._state = self.STATE_DB_ONLY
|
||||
elif ( self.hasSuccess(tasks, AddFixedDataTask) ): # no success dropping the table
|
||||
self.assertNoTask(tasks, DropFixedTableTask)
|
||||
self._state = self.STATE_HAS_DATA
|
||||
else: # did not drop table, did not insert data, that is impossible
|
||||
raise RuntimeError("Unexpected no-success scenarios")
|
||||
|
||||
else:
|
||||
raise RuntimeError("Unexpected DbState state: {}".format(self._state))
|
||||
logger.debug("New DB state is: {}".format(self._state))
|
||||
|
@ -466,14 +518,27 @@ class DbState():
|
|||
|
||||
def assertIfExistThenSuccess(self, tasks, cls):
|
||||
sCnt = 0
|
||||
exists = False
|
||||
for task in tasks :
|
||||
if not isinstance(task, cls):
|
||||
continue
|
||||
exists = True # we have a valid instance
|
||||
if task.isSuccess():
|
||||
sCnt += 1
|
||||
if ( sCnt <= 0 ):
|
||||
if ( exists and sCnt <= 0 ):
|
||||
raise RuntimeError("Unexpected zero success for task: {}".format(cls))
|
||||
|
||||
def assertNoTask(self, tasks, cls):
|
||||
for task in tasks :
|
||||
if isinstance(task, cls):
|
||||
raise RuntimeError("Unexpected task: {}".format(cls))
|
||||
|
||||
def assertNoSuccess(self, tasks, cls):
|
||||
for task in tasks :
|
||||
if isinstance(task, cls):
|
||||
if task.isSuccess():
|
||||
raise RuntimeError("Unexpected successful task: {}".format(cls))
|
||||
|
||||
def hasSuccess(self, tasks, cls):
|
||||
for task in tasks :
|
||||
if not isinstance(task, cls):
|
||||
|
@ -496,15 +561,15 @@ class TaskExecutor():
|
|||
logger.debug(" T[{}.x]: ".format(self._curStep) + msg)
|
||||
|
||||
class Task():
|
||||
def __init__(self, dbState):
|
||||
self.dbState = dbState
|
||||
def __init__(self, dbState: DbState):
|
||||
self._dbState = dbState
|
||||
self._err = None
|
||||
|
||||
def isSuccess(self):
|
||||
return self._err == None
|
||||
|
||||
def _executeInternal(self, te: TaskExecutor, wt: WorkerThread):
|
||||
raise RuntimeError("To be implemeted by child classes")
|
||||
raise RuntimeError("To be implemeted by child classes, class name: {}".format(self.__class__.__name__))
|
||||
|
||||
def execute(self, wt: WorkerThread):
|
||||
wt.verifyThreadSelf()
|
||||
|
@ -522,39 +587,49 @@ class Task():
|
|||
te.logDebug("[=]Unexpected exception")
|
||||
raise
|
||||
|
||||
te.logDebug("[X] task execution completed")
|
||||
te.logDebug("[X] task execution completed, status: {}".format(self.isSuccess()))
|
||||
|
||||
def execSql(self, sql):
|
||||
return self.dbState.execute(sql)
|
||||
return self._dbState.execute(sql)
|
||||
|
||||
class CreateDbTask(Task):
|
||||
def _executeInternal(self, te: TaskExecutor, wt: WorkerThread):
|
||||
wt.execSql("create database db")
|
||||
|
||||
class DeleteDbTask(Task):
|
||||
class DropDbTask(Task):
|
||||
def _executeInternal(self, te: TaskExecutor, wt: WorkerThread):
|
||||
wt.execSql("drop database db")
|
||||
|
||||
class CreateTableTask(Task):
|
||||
def _executeInternal(self, te: TaskExecutor, wt: WorkerThread):
|
||||
tIndex = self.dbState.addTable()
|
||||
tIndex = self._dbState.addTable()
|
||||
te.logDebug("Creating a table {} ...".format(tIndex))
|
||||
wt.execSql("create table db.table_{} (ts timestamp, speed int)".format(tIndex))
|
||||
te.logDebug("Table {} created.".format(tIndex))
|
||||
self.dbState.releaseTable(tIndex)
|
||||
self._dbState.releaseTable(tIndex)
|
||||
|
||||
class CreateFixedTableTask(Task):
|
||||
def _executeInternal(self, te: TaskExecutor, wt: WorkerThread):
|
||||
tblName = self._dbState.getFixedTableName()
|
||||
wt.execSql("create table db.{} (ts timestamp, speed int)".format(tblName))
|
||||
|
||||
class DropTableTask(Task):
|
||||
def _executeInternal(self, te: TaskExecutor, wt: WorkerThread):
|
||||
tableName = self.dbState.getTableNameToDelete()
|
||||
tableName = self._dbState.getTableNameToDelete()
|
||||
if ( not tableName ): # May be "False"
|
||||
te.logInfo("Cannot generate a table to delete, skipping...")
|
||||
return
|
||||
te.logInfo("Dropping a table db.{} ...".format(tableName))
|
||||
wt.execSql("drop table db.{}".format(tableName))
|
||||
|
||||
class DropFixedTableTask(Task):
|
||||
def _executeInternal(self, te: TaskExecutor, wt: WorkerThread):
|
||||
tblName = self._dbState.getFixedTableName()
|
||||
wt.execSql("drop table db.{}".format(tblName))
|
||||
|
||||
class AddDataTask(Task):
|
||||
def _executeInternal(self, te: TaskExecutor, wt: WorkerThread):
|
||||
ds = self.dbState
|
||||
ds = self._dbState
|
||||
te.logInfo("Adding some data... numQueue={}".format(ds.tableNumQueue.toText()))
|
||||
tIndex = ds.pickAndAllocateTable()
|
||||
if ( tIndex == None ):
|
||||
|
@ -566,6 +641,12 @@ class AddDataTask(Task):
|
|||
ds.releaseTable(tIndex)
|
||||
te.logDebug("Finished adding data")
|
||||
|
||||
class AddFixedDataTask(Task):
|
||||
def _executeInternal(self, te: TaskExecutor, wt: WorkerThread):
|
||||
ds = self._dbState
|
||||
sql = "insert into db.table_{} values ('{}', {});".format(ds.getFixedTableName(), ds.getNextTick(), ds.getNextInt())
|
||||
wt.execSql(sql)
|
||||
|
||||
# Deterministic random number generator
|
||||
class Dice():
|
||||
seeded = False # static, uninitialized
|
||||
|
|
Loading…
Reference in New Issue