2 Stimmen

Wie man Golang Channels / Go-Routinen testet

Ich habe einen Typ, der ein Byte Daten enthält und einen Kanal zur Übermittlung neuer Daten annimmt. Anderer Code kann das zuletzt geschriebene Datenbyte mit einer Read-Funktion lesen.

Bearbeitung: Für tatsächlichen ausführbaren Code siehe https://github.com/ariejan/i6502/pull/3 besonders Dateien acia6551.go und acia6551_test.go. Testergebnisse können hier eingesehen werden: https://travis-ci.org/ariejan/i6502/jobs/32862705

Ich habe folgendes:

// Simuliert einen seriellen Schnittstellenchip irgendeiner Art.
type Unit struct {
  // Kanal, den andere verwenden können, Bytes, die hier geschrieben werden, werden in rxChar platziert
  Rx chan byte

  // Interner Speicher des zuletzt geschriebenen Bytes.
  rxChar byte // Interner Speicher
}

// Wird intern verwendet, um die im rxChar gespeicherten Daten zu lesen
func (u *Unit) Read() byte {
  return u.rxChar
}

// Erstellt neue Unit und Goroutine zum Lauschen auf Rx-Bytes
func NewUnit(rx chan byte) *Unit {
  unit := &Unit{Rx: rx}

  go func() {
    for {
      select {
      case data := <-unit.Rx:
        unit.rxChar = data
        fmt.Printf("Posted 0x%02X\n", data)
      }
    }
  }()

  return unit
}

Mein Test sieht so aus:

func TestUnitRx(t *testing.T) {
  rx := make(chan byte)
  u := NewUnit(rx)

  // Byte auf den Rx-Kanal posten
  // Dies druckt "Posted 0x42", wie erwartet
  rx <- 0x42

  // Mit Testing verwenden
  // Sollte das letzte Byte, 0x42, lesen, scheitert aber.
  fmt.Println("Wert wird gelesen...")
  assert.Equal(t, 0x42, u.Read()) 
}

Zunächst dachte ich, dass das "Wert wird gelesen" passierte, bevor sich die Goroutine dazu durchringen konnte, die Daten zu schreiben. Aber die "Posted"-Nachricht wird immer vor dem "Lesen" gedruckt.

Also bleiben zwei Fragen:

  • Ist dies der beste Weg, um einen eingehenden Datenstrom von Bytes zu verarbeiten (bei 9600 Baud ;-))
  • Wenn dies der richtige Weg ist, wie kann ich es richtig testen oder was stimmt nicht mit meinem Code?

1voto

JimB Punkte 95188

Raten Sie anhand der hier geposteten Stücke, es scheint nicht, dass Sie etwas haben, das die Reihenfolge der Operationen beim Zugriff auf die gespeicherten Daten garantiert. Sie können ein Mutex um jegliche Daten verwenden, die zwischen Goroutinen geteilt werden.

Eine bessere Option hier ist die Verwendung von gepufferten Kanälen der Länge 1 zum Schreiben, Speichern und Lesen der Bytes.

Es ist immer eine gute Idee, Ihr Programm mit -race zu testen, um den Race-Detektor zu nutzen.

Da dies sehr "stream"-artig aussieht, möchten Sie vielleicht etwas Pufferung haben und sich einige Beispiele dafür ansehen, wie die Schnittstellen io.Reader und io.Writer oft verwendet werden.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X