From 9bcbad6a0761f4c971e5ccfb9c9e47511e0efa28 Mon Sep 17 00:00:00 2001 From: Zorchenhimer Date: Tue, 26 Mar 2019 11:41:31 -0400 Subject: [PATCH 1/7] Expand graceful shutdown to use http.Shutdown() Not sure if this is better or not, but I'm testing it out. --- chatroom.go | 30 +++++++++++++ main.go | 121 ++++++++++++++++++++++++++++++---------------------- 2 files changed, 101 insertions(+), 50 deletions(-) diff --git a/chatroom.go b/chatroom.go index aebde3e..ca1e118 100644 --- a/chatroom.go +++ b/chatroom.go @@ -30,6 +30,8 @@ type ChatRoom struct { modPasswords []string // single-use mod passwords modPasswordsMtx sync.Mutex + + isShutdown bool } //initializing the chatroom @@ -53,6 +55,10 @@ func newChatRoom() (*ChatRoom, error) { } func (cr *ChatRoom) JoinTemp(conn *chatConnection) (string, error) { + if cr.isShutdown { + return "", fmt.Errorf("Server is shutting down") + } + defer cr.clientsMtx.Unlock() cr.clientsMtx.Lock() @@ -77,6 +83,10 @@ func (cr *ChatRoom) JoinTemp(conn *chatConnection) (string, error) { //registering a new client //returns pointer to a Client, or Nil, if the name is already taken func (cr *ChatRoom) Join(name, uid string) (*Client, error) { + if cr.isShutdown { + return nil, fmt.Errorf("Server is shutting down") + } + defer cr.clientsMtx.Unlock() cr.clientsMtx.Lock() @@ -504,3 +514,23 @@ func (cr *ChatRoom) changeName(oldName, newName string, forced bool) error { return fmt.Errorf("Client not found with name %q", oldName) } + +func (cr *ChatRoom) Shutdown() { + cr.isShutdown = true + common.LogInfoln("ChatRoom is shutting down.") + + cr.clientsMtx.Lock() + defer cr.clientsMtx.Unlock() + + for uuid, client := range cr.clients { + common.LogDebugf("Closing connection for %s", uuid) + client.conn.Close() + } + + for uuid, conn := range cr.tempConn { + common.LogDebugf("Closing connection for temp %s", uuid) + conn.Close() + } + + common.LogInfoln("ChatRoom Shutdown() finished") +} diff --git a/main.go b/main.go index 929bae3..e59121c 100644 --- a/main.go +++ b/main.go @@ -1,11 +1,13 @@ package main import ( + "context" "flag" "fmt" "net/http" "os" "os/signal" + "time" "github.com/nareix/joy4/format" "github.com/nareix/joy4/format/rtmp" @@ -13,9 +15,10 @@ import ( ) var ( - addr string - sKey string - stats = newStreamStats() + addr string + sKey string + stats = newStreamStats() + chatServer *http.Server ) func setupSettings() error { @@ -52,9 +55,6 @@ func main() { os.Exit(1) } - exit := make(chan bool) - go handleInterrupt(exit) - // Load emotes before starting server. var err error if chat, err = newChatRoom(); err != nil { @@ -76,53 +76,74 @@ func main() { common.LogInfoln("Admin password: ", settings.AdminPassword) common.LogInfoln("Listen and serve ", addr) - go startServer() - go startRmtpServer() - - <-exit -} - -func startRmtpServer() { server := &rtmp.Server{ HandlePlay: handlePlay, HandlePublish: handlePublish, } - err := server.ListenAndServe() - if err != nil { - // If the server cannot start, don't pretend we can continue. - panic("Error trying to start rtmp server: " + err.Error()) + chatServer := &http.Server{ + Addr: addr, + ReadTimeout: 10 * time.Second, + WriteTimeout: 10 * time.Second, + MaxHeaderBytes: 1 << 20, } -} - -func startServer() { - // Chat websocket - http.HandleFunc("/ws", wsHandler) - http.HandleFunc("/static/js/", wsStaticFiles) - http.HandleFunc("/static/css/", wsStaticFiles) - http.HandleFunc("/static/img/", wsImages) - http.HandleFunc("/static/main.wasm", wsWasmFile) - http.HandleFunc("/emotes/", wsEmotes) - http.HandleFunc("/favicon.ico", wsStaticFiles) - http.HandleFunc("/chat", handleIndexTemplate) - http.HandleFunc("/video", handleIndexTemplate) - http.HandleFunc("/help", handleHelpTemplate) - - http.HandleFunc("/", handleDefault) - - err := http.ListenAndServe(addr, nil) - if err != nil { - // If the server cannot start, don't pretend we can continue. - panic("Error trying to start chat/http server: " + err.Error()) - } -} - -func handleInterrupt(exit chan bool) { - ch := make(chan os.Signal) - signal.Notify(ch, os.Interrupt) - <-ch - common.LogInfoln("Closing server") - if settings.StreamStats { - stats.Print() - } - exit <- true + + chatServer.RegisterOnShutdown(func() { chat.Shutdown() }) + //server.RegisterOnShutdown(func() { common.LogDebugln("server shutdown callback called.") }) + + // Signal handler + exit := make(chan bool) + go func() { + ch := make(chan os.Signal) + signal.Notify(ch, os.Interrupt) + <-ch + common.LogInfoln("Closing server") + if settings.StreamStats { + stats.Print() + } + + if err := chatServer.Shutdown(context.Background()); err != nil { + common.LogErrorf("Error shutting down chat server: %v", err) + } + + common.LogInfoln("Shutdown() sent. Sending exit.") + exit <- true + }() + + // Chat and HTTP server + go func() { + // Chat websocket + mux := http.NewServeMux() + mux.HandleFunc("/ws", wsHandler) + mux.HandleFunc("/static/js/", wsStaticFiles) + mux.HandleFunc("/static/css/", wsStaticFiles) + mux.HandleFunc("/static/img/", wsImages) + mux.HandleFunc("/static/main.wasm", wsWasmFile) + mux.HandleFunc("/emotes/", wsEmotes) + mux.HandleFunc("/favicon.ico", wsStaticFiles) + mux.HandleFunc("/chat", handleIndexTemplate) + mux.HandleFunc("/video", handleIndexTemplate) + mux.HandleFunc("/help", handleHelpTemplate) + + mux.HandleFunc("/", handleDefault) + + chatServer.Handler = mux + err := chatServer.ListenAndServe() + if err != http.ErrServerClosed { + // If the server cannot start, don't pretend we can continue. + panic("Error trying to start chat/http server: " + err.Error()) + } + common.LogDebugln("ChatServer closed.") + }() + + // RTMP server + go func() { + err := server.ListenAndServe() + if err != http.ErrServerClosed { + // If the server cannot start, don't pretend we can continue. + panic("Error trying to start rtmp server: " + err.Error()) + } + common.LogDebugln("RTMP server closed.") + }() + + <-exit } From e879112b1bd133100425b8e66184103863084e6f Mon Sep 17 00:00:00 2001 From: Zorchenhimer Date: Thu, 28 Mar 2019 10:18:17 -0400 Subject: [PATCH 2/7] Add some comments clarifying some things --- chatroom.go | 5 +++++ main.go | 15 ++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/chatroom.go b/chatroom.go index ca1e118..8fb41bd 100644 --- a/chatroom.go +++ b/chatroom.go @@ -55,6 +55,7 @@ func newChatRoom() (*ChatRoom, error) { } func (cr *ChatRoom) JoinTemp(conn *chatConnection) (string, error) { + // Don't allow new joins when the server is closing. if cr.isShutdown { return "", fmt.Errorf("Server is shutting down") } @@ -83,6 +84,7 @@ func (cr *ChatRoom) JoinTemp(conn *chatConnection) (string, error) { //registering a new client //returns pointer to a Client, or Nil, if the name is already taken func (cr *ChatRoom) Join(name, uid string) (*Client, error) { + // Don't allow new joins when the server is closing. if cr.isShutdown { return nil, fmt.Errorf("Server is shutting down") } @@ -515,6 +517,9 @@ func (cr *ChatRoom) changeName(oldName, newName string, forced bool) error { return fmt.Errorf("Client not found with name %q", oldName) } +// Shutdown the chatroom. First, dissallow new joins by setting +// isShutdown, then close each client connection. This would be +// a good place to put a final command that gets sent to the client. func (cr *ChatRoom) Shutdown() { cr.isShutdown = true common.LogInfoln("ChatRoom is shutting down.") diff --git a/main.go b/main.go index e59121c..dae9ef6 100644 --- a/main.go +++ b/main.go @@ -80,6 +80,8 @@ func main() { HandlePlay: handlePlay, HandlePublish: handlePublish, } + + // Define this here so we can set some timeouts and things. chatServer := &http.Server{ Addr: addr, ReadTimeout: 10 * time.Second, @@ -88,8 +90,13 @@ func main() { } chatServer.RegisterOnShutdown(func() { chat.Shutdown() }) + // rtmp.Server does not implement .RegisterOnShutdown() //server.RegisterOnShutdown(func() { common.LogDebugln("server shutdown callback called.") }) + // These have been moved back to annon functitons so I could use + // `server`, `chatServer`, and `exit` in them without needing to + // pass them as parameters. + // Signal handler exit := make(chan bool) go func() { @@ -111,7 +118,9 @@ func main() { // Chat and HTTP server go func() { - // Chat websocket + // Use a ServeMux here instead of the default, global, + // http handler. It's a good idea when we're starting more + // than one server. mux := http.NewServeMux() mux.HandleFunc("/ws", wsHandler) mux.HandleFunc("/static/js/", wsStaticFiles) @@ -128,6 +137,8 @@ func main() { chatServer.Handler = mux err := chatServer.ListenAndServe() + // http.ErrServerClosed is returned when server.Shuddown() + // is called. if err != http.ErrServerClosed { // If the server cannot start, don't pretend we can continue. panic("Error trying to start chat/http server: " + err.Error()) @@ -138,6 +149,8 @@ func main() { // RTMP server go func() { err := server.ListenAndServe() + // http.ErrServerClosed is returned when server.Shuddown() + // is called. if err != http.ErrServerClosed { // If the server cannot start, don't pretend we can continue. panic("Error trying to start rtmp server: " + err.Error()) From 5aa41cc80c046309e0eacaa75748ecefd29d19bf Mon Sep 17 00:00:00 2001 From: joeyak Date: Sat, 30 Mar 2019 16:08:41 -0400 Subject: [PATCH 3/7] Hide color div when clicking color button closes #69 --- static/css/site.css | 32 +++++++++++++++++++++++--------- static/js/chat.js | 4 ++++ static/main.html | 7 +++++-- 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/static/css/site.css b/static/css/site.css index 1b3c489..08b0f2b 100644 --- a/static/css/site.css +++ b/static/css/site.css @@ -42,6 +42,23 @@ span.svmsg { color: #ea6260; } +input[type=text] { + background: transparent; + border: var(--var-border); + border-radius: var(--var-border-radius); + color: var(--var-message-color); + padding: 5px; + font-weight: bold; +} + +#colorInputDiv { + font-size: 14px; +} + +#colorInput { + border: 2px solid var(--var-message-color); +} + .root { max-width: var(--var-max-width); max-height: var(--var-max-height); @@ -219,15 +236,6 @@ span.svmsg { margin: 5px auto; } -#name { - background: transparent; - border: var(--var-border); - border-radius: var(--var-border-radius); - color: var(--var-message-color); - padding: 5px; - font-weight: bold; -} - #chat { display: grid; grid-template-rows: 1.5em 2em 1fr 6em 2.5em 1em; @@ -291,6 +299,12 @@ span.svmsg { color: #b1b1b1; } +#colorName { + font-weight: bold; + background: var(--var-background-color); + padding: -10px; +} + #colorSubmit:disabled { display: none; } diff --git a/static/js/chat.js b/static/js/chat.js index 6c5a0eb..a3c07cd 100644 --- a/static/js/chat.js +++ b/static/js/chat.js @@ -158,6 +158,10 @@ function help() { } function showColors(show) { + if (show === undefined) { + show = $("#hiddencolor").css("display") === "none"; + } + $("#hiddencolor").css("display", show ? "block" : ""); } diff --git a/static/main.html b/static/main.html index 3607ce8..d098b08 100644 --- a/static/main.html +++ b/static/main.html @@ -50,7 +50,7 @@
- + {{if .Video}} @@ -75,7 +75,10 @@
-
+
+ # +
+
NAME
From a0a5e4be7d66609aab4af3eb140a249f2e183a57 Mon Sep 17 00:00:00 2001 From: Zorchenhimer Date: Sat, 30 Mar 2019 16:18:26 -0400 Subject: [PATCH 4/7] Replace some fmt.Printf()'s that were missed --- emotes.go | 2 +- stats.go | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/emotes.go b/emotes.go index 242f8c0..a936a16 100644 --- a/emotes.go +++ b/emotes.go @@ -47,7 +47,7 @@ func (tc *twitchChannel) downloadEmotes() (*EmoteSet, error) { b := emote.Code[i] if b >= 'A' && b <= 'Z' { es.Prefix = emote.Code[0 : i-1] - fmt.Printf("Found prefix for channel %q: %q (%q)\n", es.Channel, es.Prefix, emote) + common.LogDebugf("Found prefix for channel %q: %q (%q)\n", es.Channel, es.Prefix, emote) break } } diff --git a/stats.go b/stats.go index a5b6bbc..3aef4de 100644 --- a/stats.go +++ b/stats.go @@ -29,7 +29,7 @@ func (s *streamStats) msgOutInc() { } func (s *streamStats) Print() { - fmt.Printf("Messages In: %d\n", s.messageIn) - fmt.Printf("Messages Out: %d\n", s.messageOut) - fmt.Printf("Total Time: %s\n", time.Since(s.start)) + common.LogInfof("Messages In: %d\n", s.messageIn) + common.LogInfof("Messages Out: %d\n", s.messageOut) + common.LogInfof("Total Time: %s\n", time.Since(s.start)) } From ec0c6752bc236ada82d4c6d4bb957b6f7b7f8f75 Mon Sep 17 00:00:00 2001 From: Zorchenhimer Date: Sat, 30 Mar 2019 16:20:06 -0400 Subject: [PATCH 5/7] Fix some imports Whoops. --- emotes.go | 2 ++ stats.go | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/emotes.go b/emotes.go index a936a16..dcd6335 100644 --- a/emotes.go +++ b/emotes.go @@ -7,6 +7,8 @@ import ( "net/http" "os" "strings" + + "github.com/zorchenhimer/MovieNight/common" ) type twitchChannel struct { diff --git a/stats.go b/stats.go index 3aef4de..c96ef3d 100644 --- a/stats.go +++ b/stats.go @@ -1,9 +1,10 @@ package main import ( - "fmt" "sync" "time" + + "github.com/zorchenhimer/MovieNight/common" ) type streamStats struct { From e5f1598cd064ac5b6be2dd3a8082a25a637d72a4 Mon Sep 17 00:00:00 2001 From: joeyak Date: Sat, 30 Mar 2019 17:01:44 -0400 Subject: [PATCH 6/7] Add color dropdown issue #69 --- common/colors.go | 57 ++++++++++++++++++++++------------------------- static/js/chat.js | 49 +++++++++++----------------------------- static/main.html | 4 ++-- wasm/main.go | 10 +++++++++ 4 files changed, 52 insertions(+), 68 deletions(-) diff --git a/common/colors.go b/common/colors.go index f2c18e1..e05654f 100644 --- a/common/colors.go +++ b/common/colors.go @@ -7,39 +7,36 @@ import ( "github.com/lucasb-eyer/go-colorful" ) +// Colors holds all the valid html color names for MovieNight // the values in colors must be lowercase so it matches with the color input // this saves from having to call strings.ToLower(color) every time to check -var colors = []string{ +var Colors = []string{ "aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", - "beige", "bisque", "black", "blanchedalmond", "blue", - "blueviolet", "brown", "burlywood", "cadetblue", "chartreuse", - "chocolate", "coral", "cornflowerblue", "cornsilk", "crimson", - "cyan", "darkblue", "darkcyan", "darkgoldenrod", "darkgray", - "darkgrey", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen", - "darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen", - "darkslateblue", "darkslategray", "darkslategrey", "darkturquoise", "darkviolet", - "deeppink", "deepskyblue", "dimgray", "dimgrey", "dodgerblue", - "firebrick", "floralwhite", "forestgreen", "fuchsia", "gainsboro", - "ghostwhite", "gold", "goldenrod", "gray", "grey", - "green", "greenyellow", "honeydew", "hotpink", "indianred", - "indigo", "ivory", "khaki", "lavender", "lavenderblush", - "lawngreen", "lemonchiffon", "lightblue", "lightcoral", "lightcyan", - "lightgoldenrodyellow", "lightgray", "lightgrey", "lightgreen", "lightpink", - "lightsalmon", "lightseagreen", "lightskyblue", "lightslategray", "lightslategrey", - "lightsteelblue", "lightyellow", "lime", "limegreen", "linen", - "magenta", "maroon", "mediumaquamarine", "mediumblue", "mediumorchid", + "beige", "bisque", "blanchedalmond", "blueviolet", "brown", + "burlywood", "cadetblue", "chartreuse", "chocolate", "coral", + "cornflowerblue", "cornsilk", "crimson", "cyan", "darkcyan", + "darkgoldenrod", "darkgray", "darkkhaki", "darkmagenta", "darkolivegreen", + "darkorange", "darkorchid", "darksalmon", "darkseagreen", "darkslateblue", + "darkslategray", "darkturquoise", "darkviolet", "deeppink", "deepskyblue", + "dimgray", "dodgerblue", "firebrick", "floralwhite", "forestgreen", + "fuchsia", "gainsboro", "ghostwhite", "gold", "goldenrod", + "gray", "greenyellow", "honeydew", "hotpink", "indigo", + "ivory", "khaki", "lavender", "lavenderblush", "lawngreen", + "lemonchiffon", "lightblue", "lightcoral", "lightcyan", "lightgoldenrodyellow", + "lightgrey", "lightgreen", "lightpink", "lightsalmon", "lightseagreen", + "lightskyblue", "lightslategray", "lightsteelblue", "lightyellow", "lime", + "limegreen", "linen", "magenta", "mediumaquamarine", "mediumorchid", "mediumpurple", "mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise", - "mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin", - "navajowhite", "navy", "oldlace", "olive", "olivedrab", - "orange", "orangered", "orchid", "palegoldenrod", "palegreen", - "paleturquoise", "palevioletred", "papayawhip", "peachpuff", "peru", - "pink", "plum", "powderblue", "purple", "rebeccapurple", - "red", "rosybrown", "royalblue", "saddlebrown", "salmon", - "sandybrown", "seagreen", "seashell", "sienna", "silver", - "skyblue", "slateblue", "slategray", "slategrey", "snow", - "springgreen", "steelblue", "tan", "teal", "thistle", - "tomato", "turquoise", "violet", "wheat", "white", - "whitesmoke", "yellow", "yellowgreen", + "mediumvioletred", "mintcream", "mistyrose", "moccasin", "navajowhite", + "oldlace", "olive", "olivedrab", "orange", "orangered", + "orchid", "palegoldenrod", "palegreen", "paleturquoise", "palevioletred", + "papayawhip", "peachpuff", "peru", "pink", "plum", + "powderblue", "purple", "rebeccapurple", "red", "rosybrown", + "royalblue", "saddlebrown", "salmon", "sandybrown", "seagreen", + "seashell", "sienna", "silver", "skyblue", "slateblue", + "slategray", "snow", "springgreen", "steelblue", "tan", + "teal", "thistle", "tomato", "turquoise", "violet", + "wheat", "white", "whitesmoke", "yellow", "yellowgreen", } var ( @@ -50,7 +47,7 @@ var ( // It also accepts hex codes in the form of #RGB and #RRGGBB func IsValidColor(s string) bool { s = strings.ToLower(s) - for _, c := range colors { + for _, c := range Colors { if s == c { return true } diff --git a/static/js/chat.js b/static/js/chat.js index a3c07cd..abe0587 100644 --- a/static/js/chat.js +++ b/static/js/chat.js @@ -192,11 +192,22 @@ function updateColor() { function changeColor() { if (isValidColor(colorAsHex())) { - sendMessage("/color " + colorAsHex()); - showColors(false); + sendColor(colorAsHex()); } } +function colorSelectChange() { + let val = $("#colorSelect").val() + if (val !== "") { + sendColor(val); + } +} + +function sendColor(color) { + sendMessage("/color " + color); + showColors(false); +} + function setTimestamp(v) { showTimestamp(v) document.cookie = "timestamp=" + v @@ -272,37 +283,3 @@ window.addEventListener("load", () => { // Make sure name is focused on start $("#name").focus(); }); - -function pleaseremovethis() { - colors = ["aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", - "beige", "bisque", "black", "blanchedalmond", "blue", - "blueviolet", "brown", "burlywood", "cadetblue", "chartreuse", - "chocolate", "coral", "cornflowerblue", "cornsilk", "crimson", - "cyan", "darkblue", "darkcyan", "darkgoldenrod", "darkgray", - "darkgrey", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen", - "darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen", - "darkslateblue", "darkslategray", "darkslategrey", "darkturquoise", "darkviolet", - "deeppink", "deepskyblue", "dimgray", "dimgrey", "dodgerblue", - "firebrick", "floralwhite", "forestgreen", "fuchsia", "gainsboro", - "ghostwhite", "gold", "goldenrod", "gray", "grey", - "green", "greenyellow", "honeydew", "hotpink", "indianred", - "indigo", "ivory", "khaki", "lavender", "lavenderblush", - "lawngreen", "lemonchiffon", "lightblue", "lightcoral", "lightcyan", - "lightgoldenrodyellow", "lightgray", "lightgrey", "lightgreen", "lightpink", - "lightsalmon", "lightseagreen", "lightskyblue", "lightslategray", "lightslategrey", - "lightsteelblue", "lightyellow", "lime", "limegreen", "linen", - "magenta", "maroon", "mediumaquamarine", "mediumblue", "mediumorchid", - "mediumpurple", "mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise", - "mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin", - "navajowhite", "navy", "oldlace", "olive", "olivedrab", - "orange", "orangered", "orchid", "palegoldenrod", "palegreen", - "paleturquoise", "palevioletred", "papayawhip", "peachpuff", "peru", - "pink", "plum", "powderblue", "purple", "rebeccapurple", - "red", "rosybrown", "royalblue", "saddlebrown", "salmon", - "sandybrown", "seagreen", "seashell", "sienna", "silver", - "skyblue", "slateblue", "slategray", "slategrey", "snow", - "springgreen", "steelblue", "tan", "teal", "thistle", - "tomato", "turquoise", "violet", "wheat", "white", - "whitesmoke", "yellow", "yellowgreen",] - -} diff --git a/static/main.html b/static/main.html index d098b08..7704486 100644 --- a/static/main.html +++ b/static/main.html @@ -75,8 +75,8 @@
-
- # +
+
NAME diff --git a/wasm/main.go b/wasm/main.go index 5df650b..7092d2a 100644 --- a/wasm/main.go +++ b/wasm/main.go @@ -189,6 +189,16 @@ func main() { js.Set("debugValues", js.CallbackOf(debugValues)) js.Set("showTimestamp", js.CallbackOf(showTimestamp)) + go func() { + time.Sleep(time.Second * 1) + inner := `` + for _, c := range common.Colors { + inner += fmt.Sprintf(`\n`, c, c) + } + + js.Get("colorSelect").Set("innerHTML", inner) + }() + // This is needed so the goroutine does not end for { // heatbeat to keep connection alive to deal with nginx From 2acf382f1fe290c160ea12e467ec1173adf23405 Mon Sep 17 00:00:00 2001 From: Zorchenhimer Date: Sat, 30 Mar 2019 17:19:10 -0400 Subject: [PATCH 7/7] Add some tests for emote parsing --- common/emotes_test.go | 44 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 common/emotes_test.go diff --git a/common/emotes_test.go b/common/emotes_test.go new file mode 100644 index 0000000..f531b6f --- /dev/null +++ b/common/emotes_test.go @@ -0,0 +1,44 @@ +package common + +import ( + "os" + "testing" +) + +var data_good = map[string]string{ + "one": ``, + "two": ``, + "three": ``, + + ":one:": ``, + ":two:": ``, + ":three:": ``, + + "[one]": ``, + "[two]": ``, + "[three]": ``, + + ":one: two [three]": ` `, + + "nope one what": `nope what`, + "nope :two: what": `nope what`, + "nope [three] what": `nope what`, +} + +func TestMain(m *testing.M) { + Emotes = map[string]string{ + "one": "one.png", + "two": "two.png", + "three": "three.gif", + } + os.Exit(m.Run()) +} + +func TestEmotes_ParseEmotes(t *testing.T) { + for input, expected := range data_good { + got := ParseEmotes(input) + if got != expected { + t.Errorf("%s failed to parse into %q. Received: %q", input, expected, got) + } + } +}