config_test.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. // Copyright (c) 2017 Arista Networks, Inc.
  2. // Use of this source code is governed by the Apache License 2.0
  3. // that can be found in the COPYING file.
  4. package main
  5. import (
  6. "regexp"
  7. "testing"
  8. "notabug.org/themusicgod1/goarista/test"
  9. "github.com/prometheus/client_golang/prometheus"
  10. )
  11. func TestParseConfig(t *testing.T) {
  12. tCases := []struct {
  13. input []byte
  14. config Config
  15. }{
  16. {
  17. input: []byte(`
  18. devicelabels:
  19. 10.1.1.1:
  20. lab1: val1
  21. lab2: val2
  22. '*':
  23. lab1: val3
  24. lab2: val4
  25. subscriptions:
  26. - /Sysdb/environment/cooling/status
  27. - /Sysdb/environment/power/status
  28. metrics:
  29. - name: intfCounter
  30. path: /Sysdb/(lag|slice/phy/.+)/intfCounterDir/(?P<intf>.+)/intfCounter
  31. help: Per-Interface Bytes/Errors/Discards Counters
  32. - name: fanSpeed
  33. path: /Sysdb/environment/cooling/fan/speed/value
  34. help: Fan Speed`),
  35. config: Config{
  36. DeviceLabels: map[string]prometheus.Labels{
  37. "10.1.1.1": {
  38. "lab1": "val1",
  39. "lab2": "val2",
  40. },
  41. "*": {
  42. "lab1": "val3",
  43. "lab2": "val4",
  44. },
  45. },
  46. Subscriptions: []string{
  47. "/Sysdb/environment/cooling/status",
  48. "/Sysdb/environment/power/status",
  49. },
  50. Metrics: []*MetricDef{
  51. {
  52. Path: "/Sysdb/(lag|slice/phy/.+)/intfCounterDir/(?P<intf>.+)/intfCounter",
  53. re: regexp.MustCompile(
  54. "/Sysdb/(lag|slice/phy/.+)/intfCounterDir/(?P<intf>.+)/intfCounter"),
  55. Name: "intfCounter",
  56. Help: "Per-Interface Bytes/Errors/Discards Counters",
  57. devDesc: map[string]*prometheus.Desc{
  58. "10.1.1.1": prometheus.NewDesc("intfCounter",
  59. "Per-Interface Bytes/Errors/Discards Counters",
  60. []string{"unnamedLabel1", "intf"},
  61. prometheus.Labels{"lab1": "val1", "lab2": "val2"}),
  62. },
  63. desc: prometheus.NewDesc("intfCounter",
  64. "Per-Interface Bytes/Errors/Discards Counters",
  65. []string{"unnamedLabel1", "intf"},
  66. prometheus.Labels{"lab1": "val3", "lab2": "val4"}),
  67. },
  68. {
  69. Path: "/Sysdb/environment/cooling/fan/speed/value",
  70. re: regexp.MustCompile("/Sysdb/environment/cooling/fan/speed/value"),
  71. Name: "fanSpeed",
  72. Help: "Fan Speed",
  73. devDesc: map[string]*prometheus.Desc{
  74. "10.1.1.1": prometheus.NewDesc("fanSpeed", "Fan Speed", []string{},
  75. prometheus.Labels{"lab1": "val1", "lab2": "val2"}),
  76. },
  77. desc: prometheus.NewDesc("fanSpeed", "Fan Speed", []string{},
  78. prometheus.Labels{"lab1": "val3", "lab2": "val4"}),
  79. },
  80. },
  81. },
  82. },
  83. {
  84. input: []byte(`
  85. devicelabels:
  86. '*':
  87. lab1: val3
  88. lab2: val4
  89. subscriptions:
  90. - /Sysdb/environment/cooling/status
  91. - /Sysdb/environment/power/status
  92. metrics:
  93. - name: intfCounter
  94. path: /Sysdb/(?:lag|slice/phy/.+)/intfCounterDir/(?P<intf>.+)/intfCounter
  95. help: Per-Interface Bytes/Errors/Discards Counters
  96. - name: fanSpeed
  97. path: /Sysdb/environment/cooling/fan/speed/value
  98. help: Fan Speed`),
  99. config: Config{
  100. DeviceLabels: map[string]prometheus.Labels{
  101. "*": {
  102. "lab1": "val3",
  103. "lab2": "val4",
  104. },
  105. },
  106. Subscriptions: []string{
  107. "/Sysdb/environment/cooling/status",
  108. "/Sysdb/environment/power/status",
  109. },
  110. Metrics: []*MetricDef{
  111. {
  112. Path: "/Sysdb/(?:lag|slice/phy/.+)/intfCounterDir/(?P<intf>.+)/intfCounter",
  113. re: regexp.MustCompile(
  114. "/Sysdb/(?:lag|slice/phy/.+)/intfCounterDir/(?P<intf>.+)/intfCounter"),
  115. Name: "intfCounter",
  116. Help: "Per-Interface Bytes/Errors/Discards Counters",
  117. devDesc: map[string]*prometheus.Desc{},
  118. desc: prometheus.NewDesc("intfCounter",
  119. "Per-Interface Bytes/Errors/Discards Counters",
  120. []string{"intf"},
  121. prometheus.Labels{"lab1": "val3", "lab2": "val4"}),
  122. },
  123. {
  124. Path: "/Sysdb/environment/cooling/fan/speed/value",
  125. re: regexp.MustCompile("/Sysdb/environment/cooling/fan/speed/value"),
  126. Name: "fanSpeed",
  127. Help: "Fan Speed",
  128. devDesc: map[string]*prometheus.Desc{},
  129. desc: prometheus.NewDesc("fanSpeed", "Fan Speed", []string{},
  130. prometheus.Labels{"lab1": "val3", "lab2": "val4"}),
  131. },
  132. },
  133. },
  134. },
  135. {
  136. input: []byte(`
  137. devicelabels:
  138. 10.1.1.1:
  139. lab1: val1
  140. lab2: val2
  141. subscriptions:
  142. - /Sysdb/environment/cooling/status
  143. - /Sysdb/environment/power/status
  144. metrics:
  145. - name: intfCounter
  146. path: /Sysdb/(?:lag|slice/phy/.+)/intfCounterDir/(?P<intf>.+)/intfCounter
  147. help: Per-Interface Bytes/Errors/Discards Counters
  148. - name: fanSpeed
  149. path: /Sysdb/environment/cooling/fan/speed/value
  150. help: Fan Speed`),
  151. config: Config{
  152. DeviceLabels: map[string]prometheus.Labels{
  153. "10.1.1.1": {
  154. "lab1": "val1",
  155. "lab2": "val2",
  156. },
  157. },
  158. Subscriptions: []string{
  159. "/Sysdb/environment/cooling/status",
  160. "/Sysdb/environment/power/status",
  161. },
  162. Metrics: []*MetricDef{
  163. {
  164. Path: "/Sysdb/(?:lag|slice/phy/.+)/intfCounterDir/(?P<intf>.+)/intfCounter",
  165. re: regexp.MustCompile(
  166. "/Sysdb/(?:lag|slice/phy/.+)/intfCounterDir/(?P<intf>.+)/intfCounter"),
  167. Name: "intfCounter",
  168. Help: "Per-Interface Bytes/Errors/Discards Counters",
  169. devDesc: map[string]*prometheus.Desc{
  170. "10.1.1.1": prometheus.NewDesc("intfCounter",
  171. "Per-Interface Bytes/Errors/Discards Counters",
  172. []string{"intf"},
  173. prometheus.Labels{"lab1": "val1", "lab2": "val2"}),
  174. },
  175. },
  176. {
  177. Path: "/Sysdb/environment/cooling/fan/speed/value",
  178. re: regexp.MustCompile("/Sysdb/environment/cooling/fan/speed/value"),
  179. Name: "fanSpeed",
  180. Help: "Fan Speed",
  181. devDesc: map[string]*prometheus.Desc{
  182. "10.1.1.1": prometheus.NewDesc("fanSpeed", "Fan Speed", []string{},
  183. prometheus.Labels{"lab1": "val1", "lab2": "val2"}),
  184. },
  185. },
  186. },
  187. },
  188. },
  189. {
  190. input: []byte(`
  191. subscriptions:
  192. - /Sysdb/environment/cooling/status
  193. - /Sysdb/environment/power/status
  194. metrics:
  195. - name: intfCounter
  196. path: /Sysdb/(?:lag|slice/phy/.+)/intfCounterDir/(?P<intf>.+)/intfCounter
  197. help: Per-Interface Bytes/Errors/Discards Counters
  198. - name: fanSpeed
  199. path: /Sysdb/environment/cooling/fan/speed/value
  200. help: Fan Speed`),
  201. config: Config{
  202. DeviceLabels: map[string]prometheus.Labels{},
  203. Subscriptions: []string{
  204. "/Sysdb/environment/cooling/status",
  205. "/Sysdb/environment/power/status",
  206. },
  207. Metrics: []*MetricDef{
  208. {
  209. Path: "/Sysdb/(?:lag|slice/phy/.+)/intfCounterDir/(?P<intf>.+)/intfCounter",
  210. re: regexp.MustCompile(
  211. "/Sysdb/(?:lag|slice/phy/.+)/intfCounterDir/(?P<intf>.+)/intfCounter"),
  212. Name: "intfCounter",
  213. Help: "Per-Interface Bytes/Errors/Discards Counters",
  214. devDesc: map[string]*prometheus.Desc{},
  215. desc: prometheus.NewDesc("intfCounter",
  216. "Per-Interface Bytes/Errors/Discards Counters",
  217. []string{"intf"}, prometheus.Labels{}),
  218. },
  219. {
  220. Path: "/Sysdb/environment/cooling/fan/speed/value",
  221. re: regexp.MustCompile("/Sysdb/environment/cooling/fan/speed/value"),
  222. Name: "fanSpeed",
  223. Help: "Fan Speed",
  224. devDesc: map[string]*prometheus.Desc{},
  225. desc: prometheus.NewDesc("fanSpeed", "Fan Speed", []string{},
  226. prometheus.Labels{}),
  227. },
  228. },
  229. },
  230. },
  231. }
  232. for i, c := range tCases {
  233. cfg, err := parseConfig(c.input)
  234. if err != nil {
  235. t.Errorf("Unexpected error in case %d: %v", i+1, err)
  236. continue
  237. }
  238. if !test.DeepEqual(*cfg, c.config) {
  239. t.Errorf("Test case %d: mismatch %v", i+1, test.Diff(*cfg, c.config))
  240. }
  241. }
  242. }
  243. func TestGetDescAndLabels(t *testing.T) {
  244. config := []byte(`
  245. devicelabels:
  246. 10.1.1.1:
  247. lab1: val1
  248. lab2: val2
  249. '*':
  250. lab1: val3
  251. lab2: val4
  252. subscriptions:
  253. - /Sysdb/environment/cooling/status
  254. - /Sysdb/environment/power/status
  255. metrics:
  256. - name: intfCounter
  257. path: /Sysdb/(lag|slice/phy/.+)/intfCounterDir/(?P<intf>.+)/intfCounter
  258. help: Per-Interface Bytes/Errors/Discards Counters
  259. - name: fanSpeed
  260. path: /Sysdb/environment/cooling/status/fan/speed/value
  261. help: Fan Speed`)
  262. cfg, err := parseConfig(config)
  263. if err != nil {
  264. t.Fatalf("Unexpected error: %v", err)
  265. }
  266. tCases := []struct {
  267. src source
  268. desc *prometheus.Desc
  269. labels []string
  270. }{
  271. {
  272. src: source{
  273. addr: "10.1.1.1",
  274. path: "/Sysdb/lag/intfCounterDir/Ethernet1/intfCounter",
  275. },
  276. desc: prometheus.NewDesc("intfCounter", "Per-Interface Bytes/Errors/Discards Counters",
  277. []string{"unnamedLabel1", "intf"},
  278. prometheus.Labels{"lab1": "val1", "lab2": "val2"}),
  279. labels: []string{"lag", "Ethernet1"},
  280. },
  281. {
  282. src: source{
  283. addr: "10.2.2.2",
  284. path: "/Sysdb/lag/intfCounterDir/Ethernet1/intfCounter",
  285. },
  286. desc: prometheus.NewDesc("intfCounter", "Per-Interface Bytes/Errors/Discards Counters",
  287. []string{"unnamedLabel1", "intf"},
  288. prometheus.Labels{"lab1": "val3", "lab2": "val4"}),
  289. labels: []string{"lag", "Ethernet1"},
  290. },
  291. {
  292. src: source{
  293. addr: "10.2.2.2",
  294. path: "/Sysdb/environment/cooling/status/fan/speed/value",
  295. },
  296. desc: prometheus.NewDesc("fanSpeed", "Fan Speed",
  297. []string{},
  298. prometheus.Labels{"lab1": "val3", "lab2": "val4"}),
  299. labels: []string{},
  300. },
  301. {
  302. src: source{
  303. addr: "10.2.2.2",
  304. path: "/Sysdb/environment/nonexistent",
  305. },
  306. desc: nil,
  307. labels: nil,
  308. },
  309. }
  310. for i, c := range tCases {
  311. desc, labels := cfg.getDescAndLabels(c.src)
  312. if !test.DeepEqual(desc, c.desc) {
  313. t.Errorf("Test case %d: desc mismatch %v", i+1, test.Diff(desc, c.desc))
  314. }
  315. if !test.DeepEqual(labels, c.labels) {
  316. t.Errorf("Test case %d: labels mismatch %v", i+1, test.Diff(labels, c.labels))
  317. }
  318. }
  319. }
  320. func TestGetAllDescs(t *testing.T) {
  321. tCases := []struct {
  322. config []byte
  323. descs []*prometheus.Desc
  324. }{
  325. {
  326. config: []byte(`
  327. devicelabels:
  328. 10.1.1.1:
  329. lab1: val1
  330. lab2: val2
  331. '*':
  332. lab1: val3
  333. lab2: val4
  334. subscriptions:
  335. - /Sysdb/environment/cooling/status
  336. - /Sysdb/environment/power/status
  337. metrics:
  338. - name: intfCounter
  339. path: /Sysdb/(lag|slice/phy/.+)/intfCounterDir/(?P<intf>.+)/intfCounter
  340. help: Per-Interface Bytes/Errors/Discards Counters
  341. - name: fanSpeed
  342. path: /Sysdb/environment/cooling/status/fan/speed/value
  343. help: Fan Speed`),
  344. descs: []*prometheus.Desc{
  345. prometheus.NewDesc("intfCounter", "Per-Interface Bytes/Errors/Discards Counters",
  346. []string{"unnamedLabel1", "intf"},
  347. prometheus.Labels{"lab1": "val3", "lab2": "val4"}),
  348. prometheus.NewDesc("intfCounter", "Per-Interface Bytes/Errors/Discards Counters",
  349. []string{"unnamedLabel1", "intf"},
  350. prometheus.Labels{"lab1": "val1", "lab2": "val2"}),
  351. prometheus.NewDesc("fanSpeed", "Fan Speed", []string{},
  352. prometheus.Labels{"lab1": "val3", "lab2": "val4"}),
  353. prometheus.NewDesc("fanSpeed", "Fan Speed", []string{},
  354. prometheus.Labels{"lab1": "val1", "lab2": "val2"}),
  355. },
  356. },
  357. {
  358. config: []byte(`
  359. devicelabels:
  360. 10.1.1.1:
  361. lab1: val1
  362. lab2: val2
  363. subscriptions:
  364. - /Sysdb/environment/cooling/status
  365. - /Sysdb/environment/power/status
  366. metrics:
  367. - name: intfCounter
  368. path: /Sysdb/(lag|slice/phy/.+)/intfCounterDir/(?P<intf>.+)/intfCounter
  369. help: Per-Interface Bytes/Errors/Discards Counters
  370. - name: fanSpeed
  371. path: /Sysdb/environment/cooling/status/fan/speed/value
  372. help: Fan Speed`),
  373. descs: []*prometheus.Desc{
  374. prometheus.NewDesc("intfCounter", "Per-Interface Bytes/Errors/Discards Counters",
  375. []string{"unnamedLabel1", "intf"},
  376. prometheus.Labels{"lab1": "val1", "lab2": "val2"}),
  377. prometheus.NewDesc("fanSpeed", "Fan Speed", []string{},
  378. prometheus.Labels{"lab1": "val1", "lab2": "val2"}),
  379. },
  380. },
  381. }
  382. for i, c := range tCases {
  383. cfg, err := parseConfig(c.config)
  384. if err != nil {
  385. t.Fatalf("Unexpected error: %v", err)
  386. }
  387. ch := make(chan *prometheus.Desc, 10)
  388. cfg.getAllDescs(ch)
  389. j := 0
  390. for d := range ch {
  391. if !test.DeepEqual(c.descs[j], d) {
  392. t.Errorf("Test case %d: desc %d mismatch %v", i+1, j+1, test.Diff(c.descs[j], d))
  393. }
  394. j++
  395. if j == len(c.descs) {
  396. break
  397. }
  398. }
  399. select {
  400. case <-ch:
  401. t.Errorf("Test case %d: too many descs", i+1)
  402. default:
  403. }
  404. }
  405. }