提交 a3671929 编写于 作者: S Steven Li

successfully discovered TD-250 crash bug, with params: -p -d -s 3 -t 3

上级 58153639
...@@ -405,6 +405,9 @@ class DbState(): ...@@ -405,6 +405,9 @@ class DbState():
tIndex = self.tableNumQueue.push() tIndex = self.tableNumQueue.push()
return tIndex return tIndex
def getFixedTableName(self):
return "fixed_table"
def releaseTable(self, i): # return the table back, so others can use it def releaseTable(self, i): # return the table back, so others can use it
self.tableNumQueue.release(i) self.tableNumQueue.release(i)
...@@ -433,9 +436,13 @@ class DbState(): ...@@ -433,9 +436,13 @@ class DbState():
def getTasksAtState(self): def getTasksAtState(self):
if ( self._state == self.STATE_EMPTY ): if ( self._state == self.STATE_EMPTY ):
return [CreateDbTask(self), CreateTableTask(self)] return [CreateDbTask(self), CreateFixedTableTask(self)]
elif ( self._state == self.STATE_DB_ONLY ): 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: else:
raise RuntimeError("Unexpected DbState state: {}".format(self._state)) raise RuntimeError("Unexpected DbState state: {}".format(self._state))
...@@ -443,13 +450,58 @@ class DbState(): ...@@ -443,13 +450,58 @@ class DbState():
if ( len(tasks) == 0 ): # before 1st step, or otherwise empty if ( len(tasks) == 0 ): # before 1st step, or otherwise empty
return # do nothing return # do nothing
if ( self._state == self.STATE_EMPTY ): 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) ): if ( self.hasSuccess(tasks, CreateDbTask) ):
self.assertAtMostOneSuccess(tasks, CreateDbTask) # param is class
self._state = self.STATE_DB_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 self._state = self.STATE_DB_ONLY
if ( self.hasSuccess(tasks, CreateTableTask) ): elif ( self.hasSuccess(tasks, AddFixedDataTask) ): # no success dropping the table
self._state = self.STATE_TABLE_ONLY 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: else:
raise RuntimeError("Unexpected DbState state: {}".format(self._state)) raise RuntimeError("Unexpected DbState state: {}".format(self._state))
logger.debug("New DB state is: {}".format(self._state)) logger.debug("New DB state is: {}".format(self._state))
...@@ -466,14 +518,27 @@ class DbState(): ...@@ -466,14 +518,27 @@ class DbState():
def assertIfExistThenSuccess(self, tasks, cls): def assertIfExistThenSuccess(self, tasks, cls):
sCnt = 0 sCnt = 0
exists = False
for task in tasks : for task in tasks :
if not isinstance(task, cls): if not isinstance(task, cls):
continue continue
exists = True # we have a valid instance
if task.isSuccess(): if task.isSuccess():
sCnt += 1 sCnt += 1
if ( sCnt <= 0 ): if ( exists and sCnt <= 0 ):
raise RuntimeError("Unexpected zero success for task: {}".format(cls)) 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): def hasSuccess(self, tasks, cls):
for task in tasks : for task in tasks :
if not isinstance(task, cls): if not isinstance(task, cls):
...@@ -496,15 +561,15 @@ class TaskExecutor(): ...@@ -496,15 +561,15 @@ class TaskExecutor():
logger.debug(" T[{}.x]: ".format(self._curStep) + msg) logger.debug(" T[{}.x]: ".format(self._curStep) + msg)
class Task(): class Task():
def __init__(self, dbState): def __init__(self, dbState: DbState):
self.dbState = dbState self._dbState = dbState
self._err = None self._err = None
def isSuccess(self): def isSuccess(self):
return self._err == None return self._err == None
def _executeInternal(self, te: TaskExecutor, wt: WorkerThread): 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): def execute(self, wt: WorkerThread):
wt.verifyThreadSelf() wt.verifyThreadSelf()
...@@ -522,39 +587,49 @@ class Task(): ...@@ -522,39 +587,49 @@ class Task():
te.logDebug("[=]Unexpected exception") te.logDebug("[=]Unexpected exception")
raise raise
te.logDebug("[X] task execution completed") te.logDebug("[X] task execution completed, status: {}".format(self.isSuccess()))
def execSql(self, sql): def execSql(self, sql):
return self.dbState.execute(sql) return self._dbState.execute(sql)
class CreateDbTask(Task): class CreateDbTask(Task):
def _executeInternal(self, te: TaskExecutor, wt: WorkerThread): def _executeInternal(self, te: TaskExecutor, wt: WorkerThread):
wt.execSql("create database db") wt.execSql("create database db")
class DeleteDbTask(Task): class DropDbTask(Task):
def _executeInternal(self, te: TaskExecutor, wt: WorkerThread): def _executeInternal(self, te: TaskExecutor, wt: WorkerThread):
wt.execSql("drop database db") wt.execSql("drop database db")
class CreateTableTask(Task): class CreateTableTask(Task):
def _executeInternal(self, te: TaskExecutor, wt: WorkerThread): def _executeInternal(self, te: TaskExecutor, wt: WorkerThread):
tIndex = self.dbState.addTable() tIndex = self._dbState.addTable()
te.logDebug("Creating a table {} ...".format(tIndex)) te.logDebug("Creating a table {} ...".format(tIndex))
wt.execSql("create table db.table_{} (ts timestamp, speed int)".format(tIndex)) wt.execSql("create table db.table_{} (ts timestamp, speed int)".format(tIndex))
te.logDebug("Table {} created.".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): class DropTableTask(Task):
def _executeInternal(self, te: TaskExecutor, wt: WorkerThread): def _executeInternal(self, te: TaskExecutor, wt: WorkerThread):
tableName = self.dbState.getTableNameToDelete() tableName = self._dbState.getTableNameToDelete()
if ( not tableName ): # May be "False" if ( not tableName ): # May be "False"
te.logInfo("Cannot generate a table to delete, skipping...") te.logInfo("Cannot generate a table to delete, skipping...")
return return
te.logInfo("Dropping a table db.{} ...".format(tableName)) te.logInfo("Dropping a table db.{} ...".format(tableName))
wt.execSql("drop 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): class AddDataTask(Task):
def _executeInternal(self, te: TaskExecutor, wt: WorkerThread): def _executeInternal(self, te: TaskExecutor, wt: WorkerThread):
ds = self.dbState ds = self._dbState
te.logInfo("Adding some data... numQueue={}".format(ds.tableNumQueue.toText())) te.logInfo("Adding some data... numQueue={}".format(ds.tableNumQueue.toText()))
tIndex = ds.pickAndAllocateTable() tIndex = ds.pickAndAllocateTable()
if ( tIndex == None ): if ( tIndex == None ):
...@@ -566,6 +641,12 @@ class AddDataTask(Task): ...@@ -566,6 +641,12 @@ class AddDataTask(Task):
ds.releaseTable(tIndex) ds.releaseTable(tIndex)
te.logDebug("Finished adding data") 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 # Deterministic random number generator
class Dice(): class Dice():
seeded = False # static, uninitialized seeded = False # static, uninitialized
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册