2012-03-24 13 views
2

Ich schreibe gerade eine Spielengine in nodejs.Nodejs Testing. Wie vermeide ich Race Conditions?

Mein Spiel hat mehrere Zustände. Nennen wir sie StateA, StateB, StateC. Der Ablauf der Sequenz ist StateA => StateB => StateC.

Ich möchte den Zustand meines Motors am Ende jedes Staates testen. Im Moment habe ich diese Struktur:

function attachEventListeners = function(instance) { 
    instance.on('START_STATE_A', stateA); 
    instance.on('START_STATE_B', stateB); 
    instance.on('START_STATE_C', stateC); 
} 

var stateACallBack = function() {}; 
var stateBCallBack = function() {}; 
var stateCCallBack = function() {}; 

function stateA() { 
    // Do something... 
    stateACallBack(); 
    setTimeout(function() { this.emit('START_STATE_B'); }, 3000) 
} 

function stateB() { 
    // Do something... 
    stateBCallBack(); 
    setTimeout(function() { this.emit('START_STATE_C'); }, 3000) 
} 

function stateC() { 
    // Do something... 
    stateCCallBack(); 
    setTimeout(function() { this.emit('START_STATE_A'); }, 3000) 
} 

Also mein aktueller Ansatz beinhaltet meine Testfälle außer Kraft setzen stateXCallback mit und die Test-Logik in diesen Funktionen ausführen.

Allerdings sehe ich eine Wettlaufsituation, in der stateB gefeuert wird vor stateACallBack hat die Ausführung beendet. Daher sieht stateACallback Zustände, die stattdessen von stateBCallback ausgewertet werden sollten.

Ich habe versucht, eine Verzögerungszeit zwischen den Zuständen zu injizieren, dies führt jedoch zusätzliche Fehler in meiner Codebasis ein.

Kann mir bitte jemand einen besseren Ansatz für dieses Problem aufklären?

Antwort

1

Es ist ziemlich schwierig, dies in einer so abstrakten Weise zu diskutieren, aber es scheint mir, dass das, was Sie Zustände nennen, nicht wirklich Zustände sind, sie sind asynchrone Ereignisse. Jedes dieser Ereignisse kann den internen Zustand des Zustandsautomaten ändern, aber das hängt von der Reihenfolge ab, in der das Ereignis empfangen wird. Ich bin mir nicht sicher, ob der einzige Auslöser für Ereignis B Ereignis A ist, aber ich nehme nicht an. (Wenn dies der Fall ist, warum sollten die Ereignisse in die separaten Ereignisse A, B und C aufgeteilt werden? Scheint willkürlich und sinnlos, warum rufen Sie nicht einfach jeden Rückruf an?).

Um die Zustandsmaschine zu implementieren, benötigen Sie irgendwo eine Variable, die den aktuellen Zustand der Maschine verfolgt. Wenn ein Ereignis empfangen wird, muss der Callback entscheiden, ob er das Ereignis konsumieren und die Zustandsmaschine vorrücken soll um es in eine Warteschlange zu stellen und zu warten, bis sich die Maschine in einem anderen Status befindet.

Wenn Sie mehr Details oder eine genauere Antwort wünschen, müssen Sie mir sagen, was diese Ereignisse sind und was sie auslöst.