config_test.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. package presence
  2. import (
  3. "fmt"
  4. "net"
  5. "path/filepath"
  6. "testing"
  7. "time"
  8. "github.com/stretchr/testify/assert"
  9. mockwrap "douglasthrift.net/presence/wrap/mocks"
  10. )
  11. func TestParseConfig(t *testing.T) {
  12. cases := []struct {
  13. name, file string
  14. setup func(wNet *mockwrap.Net)
  15. config *Config
  16. err string
  17. }{
  18. {
  19. name: "success",
  20. file: "success.yml",
  21. setup: func(wNet *mockwrap.Net) {
  22. wNet.Mock.On("InterfaceByName", "eth0").Return(&net.Interface{}, nil)
  23. wNet.Mock.On("InterfaceByName", "eth1").Return(&net.Interface{}, nil)
  24. },
  25. config: &Config{
  26. Interval: 1 * time.Minute,
  27. Interfaces: []string{"eth0", "eth1"},
  28. MACAddresses: []string{"00:00:00:00:00:0a", "00:00:00:00:00:0b"},
  29. PingCount: 5,
  30. IFTTT: IFTTT{
  31. BaseURL: "https://example.com",
  32. Key: "abcdef123456",
  33. Events: Events{
  34. Present: "event_presence_detected",
  35. Absent: "event_absence_detected",
  36. },
  37. },
  38. },
  39. },
  40. {
  41. name: "defaults",
  42. file: "defaults.yml",
  43. setup: func(wNet *mockwrap.Net) {
  44. wNet.Mock.On("Interfaces").Return([]net.Interface{{Name: "eth0"}, {Name: "eth1"}, {Name: "lo"}}, nil)
  45. },
  46. config: &Config{
  47. Interval: 30 * time.Second,
  48. Interfaces: []string{"eth0", "eth1", "lo"},
  49. MACAddresses: []string{"00:00:00:00:00:01", "00:00:00:00:00:02"},
  50. PingCount: 1,
  51. IFTTT: IFTTT{
  52. BaseURL: defaultBaseURL,
  53. Key: "xyz7890!@#",
  54. Events: Events{
  55. Present: defaultPresentEvent,
  56. Absent: defaultAbsentEvent,
  57. },
  58. },
  59. },
  60. },
  61. {
  62. name: "nonexistent file",
  63. file: "nonexistent.yml",
  64. err: "open tests/nonexistent.yml: no such file or directory",
  65. },
  66. {
  67. name: "wrong MAC encoding",
  68. file: "wrong_mac_encoding.yml",
  69. err: "yaml: unmarshal errors:\n line 2: cannot unmarshal !!seq into string",
  70. },
  71. {
  72. name: "bad MAC encoding",
  73. file: "bad_mac_encoding.yml",
  74. setup: func(wNet *mockwrap.Net) {
  75. wNet.Mock.On("Interfaces").Return([]net.Interface{{Name: "eth0"}, {Name: "eth1"}, {Name: "lo"}}, nil)
  76. },
  77. err: "address 00-00-00-00-00-0x: invalid MAC address",
  78. },
  79. {
  80. name: "negative interval",
  81. file: "negative_interval.yml",
  82. err: "negative interval (-1ns)",
  83. },
  84. {
  85. name: "error listing interfaces",
  86. file: "defaults.yml",
  87. setup: func(wNet *mockwrap.Net) {
  88. wNet.Mock.On("Interfaces").Return(nil, fmt.Errorf("no network interfaces"))
  89. },
  90. err: "no network interfaces",
  91. },
  92. {
  93. name: "error getting interface by name",
  94. file: "success.yml",
  95. setup: func(wNet *mockwrap.Net) {
  96. wNet.Mock.On("InterfaceByName", "eth0").Return(nil, fmt.Errorf("no such network interface"))
  97. },
  98. err: "interface eth0: no such network interface",
  99. },
  100. {
  101. name: "no MAC addresses",
  102. file: "no_mac_addresses.yml",
  103. setup: func(wNet *mockwrap.Net) {
  104. wNet.Mock.On("InterfaceByName", "eth0").Return(&net.Interface{}, nil)
  105. },
  106. err: "no MAC addresses",
  107. },
  108. {
  109. name: "duplicate MAC address",
  110. file: "duplicate_mac_address.yml",
  111. setup: func(wNet *mockwrap.Net) {
  112. wNet.Mock.On("InterfaceByName", "eth0").Return(&net.Interface{}, nil)
  113. },
  114. err: "duplicate MAC address (00:00:00:00:00:0e)",
  115. },
  116. {
  117. name: "invalid IFTTT base URL",
  118. file: "invalid_ifttt_base_url.yml",
  119. setup: func(wNet *mockwrap.Net) {
  120. wNet.Mock.On("InterfaceByName", "eth0").Return(&net.Interface{}, nil)
  121. },
  122. err: `IFTTT base URL: parse "%": invalid URL escape "%"`,
  123. },
  124. {
  125. name: "no IFTTT key",
  126. file: "no_ifttt_key.yml",
  127. setup: func(wNet *mockwrap.Net) {
  128. wNet.Mock.On("InterfaceByName", "eth0").Return(&net.Interface{}, nil)
  129. },
  130. err: "no IFTTT key",
  131. },
  132. {
  133. name: "invalid IFTTT present event name",
  134. file: "invalid_ifttt_present_event_name.yml",
  135. setup: func(wNet *mockwrap.Net) {
  136. wNet.Mock.On("InterfaceByName", "eth0").Return(&net.Interface{}, nil)
  137. },
  138. err: `invalid IFTTT present event name: "$"`,
  139. },
  140. {
  141. name: "invalid IFTTT absent event name",
  142. file: "invalid_ifttt_absent_event_name.yml",
  143. setup: func(wNet *mockwrap.Net) {
  144. wNet.Mock.On("InterfaceByName", "eth0").Return(&net.Interface{}, nil)
  145. },
  146. err: `invalid IFTTT absent event name: "^"`,
  147. },
  148. }
  149. for _, tc := range cases {
  150. tc := tc
  151. t.Run(tc.name, func(t *testing.T) {
  152. t.Parallel()
  153. assert := assert.New(t)
  154. wNet := mockwrap.NewNet(t)
  155. if tc.setup != nil {
  156. tc.setup(wNet)
  157. }
  158. c, err := ParseConfig(filepath.Join("tests", tc.file), wNet)
  159. if tc.err != "" {
  160. assert.ErrorContains(err, tc.err)
  161. } else {
  162. assert.NoError(err)
  163. assert.Equal(tc.config, c)
  164. }
  165. })
  166. }
  167. }