github.com/la5nta/wl2k-go@v0.11.8/fbb/message_test.go (about)

     1  // Copyright 2016 Martin Hebnes Pedersen (LA5NTA). All rights reserved.
     2  // Use of this source code is governed by the MIT-license that can be
     3  // found in the LICENSE file.
     4  
     5  package fbb
     6  
     7  import (
     8  	"bytes"
     9  	"reflect"
    10  	"strings"
    11  	"testing"
    12  	"time"
    13  	"unicode"
    14  )
    15  
    16  func TestReadMessageWithWhitespaceBeforeHeader(t *testing.T) {
    17  	m1 := NewMessage(Private, "one-long-mid")
    18  	m1.AddTo("N0CALL")
    19  	m1.SetFrom("LA5NTA")
    20  	m1.SetBody("Hello world")
    21  
    22  	// Write the message with leading whitespace garbage
    23  	var buf bytes.Buffer
    24  	buf.WriteString("\r\n\r\n\t ")
    25  	if err := m1.Write(&buf); err != nil {
    26  		t.Fatal(err)
    27  	}
    28  
    29  	// Read the message and verify that we decoded the header successfully.
    30  	m2 := &Message{}
    31  	if err := m2.ReadFrom(bytes.NewReader(buf.Bytes())); err != nil {
    32  		t.Fatal(err)
    33  	}
    34  	if !reflect.DeepEqual(m1.Header, m2.Header) {
    35  		t.Error("parsed message header differs", m1, m2)
    36  	}
    37  }
    38  
    39  func TestEmptyMessageReadError(t *testing.T) {
    40  	if err := (&Message{}).ReadFrom(strings.NewReader("")); err == nil {
    41  		t.Errorf("Reading empty message did not error")
    42  	}
    43  	if err := (&Message{}).ReadFrom(strings.NewReader("\r\n\r\nfoobar")); err == nil {
    44  		t.Errorf("Reading headerless message did not error")
    45  	}
    46  }
    47  
    48  func TestParseDate(t *testing.T) {
    49  	tests := []string{
    50  		"2016/12/30 01:00", // The correct format according to winlink.org/b2f.
    51  		"2016.12.30 01:00", // RMS Relay store-and-forward re-formats date headers in this undocumented layout.
    52  		"2016-12-30 01:00", // Seen in a Radio Only message via RMS Relay-3.0.30.0.
    53  		"20161230010000",   // Format known to be produced by some versions of BPQ Mail.
    54  
    55  		// Extended format support to ensure we support common email formats.
    56  		"Fri, 30 Dec 2016 01:00:00 -0000", // RFC 5322, Appendix A.1.1.
    57  		"Fri, 30 Dec 2016 01:00:00 GMT",   // RFC 5322, Appendix A.6.2. Obsolete date.
    58  	}
    59  	expect := time.Date(2016, time.December, 30, 01, 00, 00, 00, time.UTC).Local()
    60  
    61  	for _, str := range tests {
    62  		got, _ := ParseDate(str)
    63  		if !got.Equal(expect) {
    64  			t.Errorf("Unexpected Time when parsing `%s`: %s", str, got)
    65  		}
    66  	}
    67  }
    68  
    69  func TestAddressFromString(t *testing.T) {
    70  	tests := map[string]Address{
    71  		"LA5NTA":             {Proto: "", Addr: "LA5NTA"},
    72  		"la5nta":             {Proto: "", Addr: "LA5NTA"},
    73  		"LA5NTA@winlink.org": {Proto: "", Addr: "LA5NTA"},
    74  		"LA5NTA@WINLINK.org": {Proto: "", Addr: "LA5NTA"},
    75  		"la5nta@WINLINK.org": {Proto: "", Addr: "LA5NTA"},
    76  
    77  		"foo@bar.baz": {Proto: "SMTP", Addr: "foo@bar.baz"},
    78  	}
    79  
    80  	for str, expect := range tests {
    81  		got := AddressFromString(str)
    82  		if !reflect.DeepEqual(expect, got) {
    83  			t.Errorf("'%s' got %#v expected %#v", str, got, expect)
    84  		}
    85  	}
    86  }
    87  
    88  func TestEncodeNonASCIIFileNames(t *testing.T) {
    89  	msg := NewMessage(Private, "NOCALL")
    90  	msg.AddFile(NewFile("æøå.txt", []byte{}))
    91  
    92  	if h := msg.Header.Get("File"); IsIllegalHeader(h) {
    93  		t.Error("Non-ascii character in encoded File header")
    94  	}
    95  }
    96  
    97  func TestDecodeNonASCIIFileNames(t *testing.T) {
    98  	msg := NewMessage(Private, "NOCALL")
    99  	msg.AddFile(NewFile("æøå.txt", []byte{}))
   100  
   101  	samples := []string{
   102  		msg.Header["File"][0], // Word encoded (round trip)
   103  		"0 æøå.txt",           // UTF8
   104  		"0 \xE6\xF8\xE5.txt",  // Latin1
   105  	}
   106  
   107  	for i, v := range samples {
   108  		msg.Header["File"][0] = v
   109  
   110  		var buf bytes.Buffer
   111  		msg.Write(&buf)
   112  
   113  		decoded := new(Message)
   114  		decoded.ReadFrom(&buf)
   115  		if msg.Files()[0].Name() != "æøå.txt" {
   116  			t.Errorf("Sample %d failed", i)
   117  		}
   118  	}
   119  }
   120  
   121  func TestEmptyAttachment(t *testing.T) {
   122  	msg := NewMessage(Private, "N0CALL")
   123  	msg.AddFile(NewFile("foo.txt", nil))
   124  	var buf bytes.Buffer
   125  	if err := msg.Write(&buf); err != nil {
   126  		t.Fatalf("Error writing message: %v", err)
   127  	}
   128  	if !strings.Contains(buf.String(), "File: 0 foo.txt") {
   129  		t.Error("Expected File header")
   130  	}
   131  	decoded := new(Message)
   132  	if err := decoded.ReadFrom(&buf); err != nil {
   133  		t.Fatalf("Error while decoding produced message: %v", err)
   134  	}
   135  	if n := len(msg.Files()); n != 1 {
   136  		t.Fatalf("Expected one attachment after roundtrip, found %d", n)
   137  	}
   138  	f := msg.Files()[0]
   139  	if f.Size() != 0 {
   140  		t.Errorf("Expected size 0 after roundtrip, found %d", f.Size())
   141  	}
   142  	if f.Name() != "foo.txt" {
   143  		t.Errorf("Got unexpected attachment name after roundtrip: %s", f.Name())
   144  	}
   145  	body, err := msg.Body()
   146  	if err != nil {
   147  		t.Errorf("Got error reading body: %v", err)
   148  	}
   149  	if len(body) != 0 {
   150  		t.Errorf("Expected no body, got length %d", len(body))
   151  	}
   152  }
   153  
   154  func IsIllegalHeader(str string) bool {
   155  	for _, c := range str {
   156  		if !IsGraphicASCII(c) {
   157  			return true
   158  		}
   159  	}
   160  	return false
   161  }
   162  
   163  func IsGraphicASCII(c rune) bool {
   164  	return c <= unicode.MaxASCII && unicode.IsGraphic(c)
   165  }