Next milestone: production memory under 5 GiB, ready for upaas #6
+22
-18
@@ -63,24 +63,28 @@ type RISLiveMessage struct {
|
||||
// the actual BGP update data including AS path, communities, announcements,
|
||||
// and withdrawals.
|
||||
type RISMessage struct {
|
||||
Type string `json:"type"`
|
||||
Timestamp float64 `json:"timestamp"`
|
||||
ParsedTimestamp time.Time `json:"-"` // Parsed from Timestamp field
|
||||
Peer string `json:"peer"`
|
||||
PeerASN string `json:"peer_asn"`
|
||||
ID string `json:"id"`
|
||||
Host string `json:"host"`
|
||||
RRC string `json:"rrc,omitempty"`
|
||||
MrtTime float64 `json:"mrt_time,omitempty"`
|
||||
SocketTime float64 `json:"socket_time,omitempty"`
|
||||
Path ASPath `json:"path,omitempty"`
|
||||
Community [][]int `json:"community,omitempty"`
|
||||
Origin string `json:"origin,omitempty"`
|
||||
MED *int `json:"med,omitempty"`
|
||||
LocalPref *int `json:"local_pref,omitempty"`
|
||||
Announcements []RISAnnouncement `json:"announcements,omitempty"`
|
||||
Withdrawals []string `json:"withdrawals,omitempty"`
|
||||
Raw string `json:"raw,omitempty"`
|
||||
Type string `json:"type"`
|
||||
Timestamp float64 `json:"timestamp"`
|
||||
ParsedTimestamp time.Time `json:"-"` // Parsed from Timestamp field
|
||||
Peer string `json:"peer"`
|
||||
PeerASN string `json:"peer_asn"`
|
||||
ID string `json:"id"`
|
||||
Host string `json:"host"`
|
||||
RRC string `json:"rrc,omitempty"`
|
||||
MrtTime float64 `json:"mrt_time,omitempty"`
|
||||
SocketTime float64 `json:"socket_time,omitempty"`
|
||||
Path ASPath `json:"path,omitempty"`
|
||||
// Community and Raw are present in the feed but read by no handler.
|
||||
// They are the largest fields on a message that lives in up to four
|
||||
// handler queues, so json:"-" keeps them out of the decoded message
|
||||
// to save queue memory. Do not decode them without a consumer.
|
||||
Community [][]int `json:"-"`
|
||||
Origin string `json:"origin,omitempty"`
|
||||
MED *int `json:"med,omitempty"`
|
||||
LocalPref *int `json:"local_pref,omitempty"`
|
||||
Announcements []RISAnnouncement `json:"announcements,omitempty"`
|
||||
Withdrawals []string `json:"withdrawals,omitempty"`
|
||||
Raw string `json:"-"`
|
||||
}
|
||||
|
||||
// RISAnnouncement represents a BGP route announcement within a RIS message.
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
package ristypes
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// messageExamplesPath is the captured RIS Live feed used as decode fixtures,
|
||||
// one JSON message per line.
|
||||
const messageExamplesPath = "../../docs/message-examples.json"
|
||||
|
||||
// TestDecodeDropsCommunityAndRaw decodes every captured message the way the
|
||||
// streamer does and checks that the fields no handler reads (Community, Raw)
|
||||
// stay empty while the fields handlers use (Path, Announcements) still decode.
|
||||
func TestDecodeDropsCommunityAndRaw(t *testing.T) {
|
||||
f, err := os.Open(messageExamplesPath)
|
||||
if err != nil {
|
||||
t.Fatalf("open fixtures: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
var messages, withPath, withAnnouncements int
|
||||
|
||||
scanner := bufio.NewScanner(f)
|
||||
scanner.Buffer(make([]byte, 0, 64*1024), 1024*1024)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Bytes()
|
||||
if len(line) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
var wrapper RISLiveMessage
|
||||
if err := json.Unmarshal(line, &wrapper); err != nil {
|
||||
t.Fatalf("unmarshal message %d: %v", messages+1, err)
|
||||
}
|
||||
messages++
|
||||
|
||||
msg := wrapper.Data
|
||||
if msg.Community != nil {
|
||||
t.Errorf("message %d: Community decoded, want empty: %v", messages, msg.Community)
|
||||
}
|
||||
if msg.Raw != "" {
|
||||
t.Errorf("message %d: Raw decoded, want empty", messages)
|
||||
}
|
||||
|
||||
if len(msg.Path) > 0 {
|
||||
withPath++
|
||||
}
|
||||
if len(msg.Announcements) > 0 {
|
||||
withAnnouncements++
|
||||
}
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
t.Fatalf("scan fixtures: %v", err)
|
||||
}
|
||||
|
||||
if messages == 0 {
|
||||
t.Fatal("no messages decoded from fixtures")
|
||||
}
|
||||
// The fixtures include announcement messages; a used field must still decode,
|
||||
// otherwise an empty Community/Raw would prove nothing.
|
||||
if withPath == 0 || withAnnouncements == 0 {
|
||||
t.Fatalf("used fields did not decode: withPath=%d withAnnouncements=%d", withPath, withAnnouncements)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user