config_test.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  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(t *testing.T, wNet *mockwrap.Net)
  15. config *Config
  16. err string
  17. }{
  18. {
  19. name: "success",
  20. file: "success.yml",
  21. setup: func(t *testing.T, wNet *mockwrap.Net) {
  22. wNet.AddInterfaceByName(func(name string) (*net.Interface, error) {
  23. assert.Equal(t, "eth0", name)
  24. return &net.Interface{}, nil
  25. })
  26. wNet.AddInterfaceByName(func(name string) (*net.Interface, error) {
  27. assert.Equal(t, "eth1", name)
  28. return &net.Interface{}, nil
  29. })
  30. },
  31. config: &Config{
  32. Interval: 1 * time.Minute,
  33. Interfaces: []string{"eth0", "eth1"},
  34. MACAddresses: []string{"00:00:00:00:00:0a", "00:00:00:00:00:0b"},
  35. PingCount: 5,
  36. IFTTT: IFTTT{
  37. BaseURL: "https://example.com",
  38. Key: "abcdef123456",
  39. Events: Events{
  40. Present: Event{
  41. Event: "event_presence_detected",
  42. Value1: "event_presence_detected_value1",
  43. Value2: "event_presence_detected_value2",
  44. Value3: "event_presence_detected_value3",
  45. },
  46. Absent: Event{
  47. Event: "event_absence_detected",
  48. Value1: "event_absence_detected_value1",
  49. Value2: "event_absence_detected_value2",
  50. Value3: "event_absence_detected_value3",
  51. },
  52. },
  53. },
  54. },
  55. },
  56. {
  57. name: "defaults",
  58. file: "defaults.yml",
  59. setup: func(t *testing.T, wNet *mockwrap.Net) {
  60. wNet.AddInterfaces(func() ([]net.Interface, error) {
  61. return []net.Interface{{Name: "eth0"}, {Name: "eth1"}, {Name: "lo"}}, nil
  62. })
  63. },
  64. config: &Config{
  65. Interval: 30 * time.Second,
  66. Interfaces: []string{"eth0", "eth1", "lo"},
  67. MACAddresses: []string{"00:00:00:00:00:01", "00:00:00:00:00:02"},
  68. PingCount: 1,
  69. IFTTT: IFTTT{
  70. BaseURL: defaultBaseURL,
  71. Key: "xyz7890!@#",
  72. Events: Events{
  73. Present: Event{Event: defaultPresentEvent},
  74. Absent: Event{Event: defaultAbsentEvent},
  75. },
  76. },
  77. },
  78. },
  79. {
  80. name: "nonexistent file",
  81. file: "nonexistent.yml",
  82. err: "open tests/nonexistent.yml: no such file or directory",
  83. },
  84. {
  85. name: "wrong MAC encoding",
  86. file: "wrong_mac_encoding.yml",
  87. err: "yaml: unmarshal errors:\n line 2: cannot unmarshal !!seq into string",
  88. },
  89. {
  90. name: "bad MAC encoding",
  91. file: "bad_mac_encoding.yml",
  92. setup: func(t *testing.T, wNet *mockwrap.Net) {
  93. wNet.AddInterfaces(func() ([]net.Interface, error) {
  94. return []net.Interface{{Name: "eth0"}, {Name: "eth1"}, {Name: "lo"}}, nil
  95. })
  96. },
  97. err: "address 00-00-00-00-00-0x: invalid MAC address",
  98. },
  99. {
  100. name: "negative interval",
  101. file: "negative_interval.yml",
  102. err: "negative interval (-1ns)",
  103. },
  104. {
  105. name: "error listing interfaces",
  106. file: "defaults.yml",
  107. setup: func(t *testing.T, wNet *mockwrap.Net) {
  108. wNet.AddInterfaces(func() ([]net.Interface, error) {
  109. return nil, fmt.Errorf("no network interfaces")
  110. })
  111. },
  112. err: "no network interfaces",
  113. },
  114. {
  115. name: "error getting interface by name",
  116. file: "success.yml",
  117. setup: func(t *testing.T, wNet *mockwrap.Net) {
  118. wNet.AddInterfaceByName(func(name string) (*net.Interface, error) {
  119. assert.Equal(t, "eth0", name)
  120. return nil, fmt.Errorf("no such network interface")
  121. })
  122. },
  123. err: "interface eth0: no such network interface",
  124. },
  125. {
  126. name: "no MAC addresses",
  127. file: "no_mac_addresses.yml",
  128. setup: func(t *testing.T, wNet *mockwrap.Net) {
  129. wNet.AddInterfaceByName(func(name string) (*net.Interface, error) {
  130. assert.Equal(t, "eth0", name)
  131. return &net.Interface{}, nil
  132. })
  133. },
  134. err: "no MAC addresses",
  135. },
  136. {
  137. name: "duplicate MAC address",
  138. file: "duplicate_mac_address.yml",
  139. setup: func(t *testing.T, wNet *mockwrap.Net) {
  140. wNet.AddInterfaceByName(func(name string) (*net.Interface, error) {
  141. assert.Equal(t, "eth0", name)
  142. return &net.Interface{}, nil
  143. })
  144. },
  145. err: "duplicate MAC address (00:00:00:00:00:0e)",
  146. },
  147. {
  148. name: "invalid IFTTT base URL",
  149. file: "invalid_ifttt_base_url.yml",
  150. setup: func(t *testing.T, wNet *mockwrap.Net) {
  151. wNet.AddInterfaceByName(func(name string) (*net.Interface, error) {
  152. assert.Equal(t, "eth0", name)
  153. return &net.Interface{}, nil
  154. })
  155. },
  156. err: `IFTTT base URL: parse "%": invalid URL escape "%"`,
  157. },
  158. {
  159. name: "no IFTTT key",
  160. file: "no_ifttt_key.yml",
  161. setup: func(t *testing.T, wNet *mockwrap.Net) {
  162. wNet.AddInterfaceByName(func(name string) (*net.Interface, error) {
  163. assert.Equal(t, "eth0", name)
  164. return &net.Interface{}, nil
  165. })
  166. },
  167. err: "no IFTTT key",
  168. },
  169. {
  170. name: "invalid IFTTT present event name",
  171. file: "invalid_ifttt_present_event_name.yml",
  172. setup: func(t *testing.T, wNet *mockwrap.Net) {
  173. wNet.AddInterfaceByName(func(name string) (*net.Interface, error) {
  174. assert.Equal(t, "eth0", name)
  175. return &net.Interface{}, nil
  176. })
  177. },
  178. err: `invalid IFTTT present event name: "$"`,
  179. },
  180. {
  181. name: "invalid IFTTT absent event name",
  182. file: "invalid_ifttt_absent_event_name.yml",
  183. setup: func(t *testing.T, wNet *mockwrap.Net) {
  184. wNet.AddInterfaceByName(func(name string) (*net.Interface, error) {
  185. assert.Equal(t, "eth0", name)
  186. return &net.Interface{}, nil
  187. })
  188. },
  189. err: `invalid IFTTT absent event name: "^"`,
  190. },
  191. }
  192. for _, tc := range cases {
  193. tc := tc
  194. t.Run(tc.name, func(t *testing.T) {
  195. t.Parallel()
  196. assert := assert.New(t)
  197. wNet := mockwrap.NewNet(t)
  198. if tc.setup != nil {
  199. tc.setup(t, wNet)
  200. }
  201. c, err := ParseConfig(filepath.Join("tests", tc.file), wNet)
  202. if tc.err != "" {
  203. assert.ErrorContains(err, tc.err)
  204. } else {
  205. assert.NoError(err)
  206. assert.Equal(tc.config, c)
  207. }
  208. assert.False(wNet.HasMore(), "missing expected net calls")
  209. })
  210. }
  211. }