config_test.go 5.5 KB

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