sysutils_test.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package sysutils
  15. import (
  16. "fmt"
  17. "net"
  18. "reflect"
  19. "testing"
  20. "yunion.io/x/jsonutils"
  21. "yunion.io/x/onecloud/pkg/apis/compute"
  22. "yunion.io/x/onecloud/pkg/cloudcommon/types"
  23. )
  24. func Test_valueOfKeyword(t *testing.T) {
  25. type args struct {
  26. line string
  27. key string
  28. }
  29. t1 := "Manufacturer: LENOVO"
  30. w1 := "LENOVO"
  31. tests := []struct {
  32. name string
  33. args args
  34. want *string
  35. }{
  36. {
  37. name: "EmptyInput",
  38. args: args{
  39. line: "",
  40. key: "Family",
  41. },
  42. want: nil,
  43. },
  44. {
  45. name: "NormalInput",
  46. args: args{
  47. line: t1,
  48. key: "manufacturer:",
  49. },
  50. want: &w1,
  51. },
  52. }
  53. for _, tt := range tests {
  54. t.Run(tt.name, func(t *testing.T) {
  55. if got := valueOfKeyword(tt.args.line, tt.args.key); got != nil && *got != *(tt.want) {
  56. t.Errorf("valueOfKeyword() = %q, want %q", *got, *(tt.want))
  57. } else if got == nil && tt.want != nil {
  58. t.Errorf("valueOfKeyword() = %v, want %v", got, tt.want)
  59. }
  60. })
  61. }
  62. }
  63. func TestParseDMISysinfo(t *testing.T) {
  64. type args struct {
  65. lines []string
  66. }
  67. tests := []struct {
  68. name string
  69. args args
  70. want *types.SSystemInfo
  71. wantErr bool
  72. }{
  73. {
  74. name: "EmptyInput",
  75. args: args{lines: nil},
  76. want: nil,
  77. wantErr: true,
  78. },
  79. {
  80. name: "NormalInput",
  81. args: args{lines: []string{
  82. "Handle 0x000C, DMI type 1, 27 bytes",
  83. "System Information",
  84. " Manufacturer: LENOVO",
  85. " Product Name: 20J6CTO1WW",
  86. " Version: ThinkPad T470p",
  87. " Serial Number: PF112JKK",
  88. " UUID: bca177cc-2bce-11b2-a85c-e98996f19d2f",
  89. " SKU Number: LENOVO_MT_20J6_BU_Think_FM_ThinkPad T470p",
  90. }},
  91. want: &types.SSystemInfo{
  92. Manufacture: "LENOVO",
  93. Model: "20J6CTO1WW",
  94. Version: "ThinkPad T470p",
  95. SN: "PF112JKK",
  96. OemName: "lenovo",
  97. },
  98. wantErr: false,
  99. },
  100. {
  101. name: "NoneVersionInput",
  102. args: args{lines: []string{
  103. " Product Name: 20J6CTO1WW",
  104. " Version: None",
  105. " Serial Number: PF112JKK",
  106. }},
  107. want: &types.SSystemInfo{
  108. Model: "20J6CTO1WW",
  109. Version: "",
  110. SN: "PF112JKK",
  111. },
  112. wantErr: false,
  113. },
  114. }
  115. for _, tt := range tests {
  116. t.Run(tt.name, func(t *testing.T) {
  117. got, err := ParseDMISysinfo(tt.args.lines)
  118. if (err != nil) != tt.wantErr {
  119. t.Errorf("ParseDMISysinfo() error = %v, wantErr %v", err, tt.wantErr)
  120. return
  121. }
  122. if !reflect.DeepEqual(got, tt.want) {
  123. t.Errorf("ParseDMISysinfo() = %v, want %v", got, tt.want)
  124. }
  125. })
  126. }
  127. }
  128. func TestParseCPUInfo(t *testing.T) {
  129. type args struct {
  130. lines []string
  131. }
  132. tests := []struct {
  133. name string
  134. args args
  135. want *types.SCPUInfo
  136. wantErr bool
  137. }{
  138. {
  139. name: "NormalInput",
  140. args: args{lines: []string{
  141. "model name : Intel(R) Xeon(R) CPU E5-2680 v2 @ 2.80GHz",
  142. "cpu MHz : 2793.238",
  143. "processor : 0",
  144. "processor : 1",
  145. "cache size : 16384 KB",
  146. }},
  147. want: &types.SCPUInfo{
  148. Model: "Intel(R) Xeon(R) CPU E5-2680 v2 @ 2.80GHz",
  149. Count: 2,
  150. Freq: 2793,
  151. Cache: 16384,
  152. },
  153. wantErr: false,
  154. },
  155. {
  156. name: "arm",
  157. args: args{lines: []string{
  158. "processor\t: 62",
  159. "BogoMIPS\t: 200.00",
  160. "Features\t: fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma dcpop",
  161. "CPU implementer\t: 0x48",
  162. "CPU architecture: 8",
  163. "CPU variant\t: 0x1",
  164. "CPU part\t: 0xd01",
  165. "CPU revision\t: 0",
  166. }},
  167. want: &types.SCPUInfo{
  168. Model: "0xd01",
  169. Microcode: "0",
  170. Count: 1,
  171. },
  172. wantErr: false,
  173. },
  174. }
  175. for _, tt := range tests {
  176. t.Run(tt.name, func(t *testing.T) {
  177. got, err := ParseCPUInfo(tt.args.lines)
  178. if (err != nil) != tt.wantErr {
  179. t.Errorf("ParseCPUInfo() error = %v, wantErr %v", err, tt.wantErr)
  180. return
  181. }
  182. if !reflect.DeepEqual(got, tt.want) {
  183. t.Errorf("ParseCPUInfo() = %v, want %v", got, tt.want)
  184. }
  185. })
  186. }
  187. }
  188. func TestParseDMICPUInfo(t *testing.T) {
  189. type args struct {
  190. lines []string
  191. }
  192. tests := []struct {
  193. name string
  194. args args
  195. want *types.SDMICPUInfo
  196. }{
  197. {
  198. name: "NormalInput",
  199. args: args{
  200. lines: []string{"Processor Information"},
  201. },
  202. want: &types.SDMICPUInfo{Nodes: 1},
  203. },
  204. }
  205. for _, tt := range tests {
  206. t.Run(tt.name, func(t *testing.T) {
  207. if got := ParseDMICPUInfo(tt.args.lines); !reflect.DeepEqual(got, tt.want) {
  208. t.Errorf("ParseDMICPUInfo() = %v, want %v", got, tt.want)
  209. }
  210. })
  211. }
  212. }
  213. func TestParseDMIMemInfo(t *testing.T) {
  214. type args struct {
  215. lines []string
  216. }
  217. tests := []struct {
  218. name string
  219. args args
  220. want *types.SDMIMemInfo
  221. }{
  222. {
  223. name: "NormalInputMB",
  224. args: args{
  225. lines: []string{
  226. " Size: 16384 MB",
  227. " Size: No Module Installed"},
  228. },
  229. want: &types.SDMIMemInfo{Total: 16384},
  230. },
  231. {
  232. name: "NormalInputGB",
  233. args: args{
  234. lines: []string{
  235. " Size: 16 GB",
  236. " Size: No Module Installed"},
  237. },
  238. want: &types.SDMIMemInfo{Total: 16 * 1024},
  239. },
  240. }
  241. for _, tt := range tests {
  242. t.Run(tt.name, func(t *testing.T) {
  243. if got := ParseDMIMemInfo(tt.args.lines); !reflect.DeepEqual(got, tt.want) {
  244. t.Errorf("ParseDMIMemInfo() = %v, want %v", got, tt.want)
  245. }
  246. })
  247. }
  248. }
  249. func TestParseNicInfo(t *testing.T) {
  250. type args struct {
  251. lines []string
  252. }
  253. up := true
  254. down := false
  255. mac1Str := "00:22:25:0b:ab:49"
  256. mac2Str := "00:22:25:0b:ab:50"
  257. mac1, _ := net.ParseMAC(mac1Str)
  258. mac2, _ := net.ParseMAC(mac2Str)
  259. tests := []struct {
  260. name string
  261. args args
  262. want []*types.SNicDevInfo
  263. }{
  264. {
  265. name: "NormalInput",
  266. args: args{
  267. lines: []string{
  268. fmt.Sprintf("eth0 %s 0 1 1500", mac1Str),
  269. fmt.Sprintf("eth1 %s 0 0 1500", mac2Str),
  270. },
  271. },
  272. want: []*types.SNicDevInfo{
  273. {Dev: "eth0", Mac: mac1, Speed: 0, Up: &up, Mtu: 1500},
  274. {Dev: "eth1", Mac: mac2, Speed: 0, Up: &down, Mtu: 1500},
  275. },
  276. },
  277. }
  278. for _, tt := range tests {
  279. t.Run(tt.name, func(t *testing.T) {
  280. got := ParseNicInfo(tt.args.lines)
  281. gotJson := jsonutils.Marshal(got)
  282. wantJson := jsonutils.Marshal(tt.want)
  283. if !gotJson.Equals(wantJson) {
  284. t.Errorf("got:\n%s\nwant:\n%s", gotJson, wantJson)
  285. }
  286. })
  287. }
  288. }
  289. func TestGetSecureTTYs(t *testing.T) {
  290. tests := []struct {
  291. name string
  292. lines []string
  293. want []string
  294. }{
  295. {
  296. name: "empty tty",
  297. lines: []string{"", "#comment"},
  298. want: []string{},
  299. },
  300. {
  301. name: "ttys",
  302. lines: []string{
  303. "tty1",
  304. "ttyS0",
  305. "console",
  306. "#tty0",
  307. },
  308. want: []string{
  309. "tty1",
  310. "ttyS0",
  311. "console",
  312. },
  313. },
  314. }
  315. for _, tt := range tests {
  316. t.Run(tt.name, func(t *testing.T) {
  317. if got := GetSecureTTYs(tt.lines); !reflect.DeepEqual(got, tt.want) {
  318. t.Errorf("GetSecureTTYs() = %v, want %v", got, tt.want)
  319. }
  320. })
  321. }
  322. }
  323. func TestParseDiskInfo(t *testing.T) {
  324. type args struct {
  325. lines []string
  326. driver string
  327. }
  328. tests := []struct {
  329. name string
  330. args args
  331. want []*types.SDiskInfo
  332. }{
  333. {
  334. name: "raid",
  335. args: args{
  336. lines: []string{
  337. "sda 15625879552 512 1 megaraid_sas 0x010400 DELL PERC H730P Mini 4.26",
  338. },
  339. driver: "raid",
  340. },
  341. want: []*types.SDiskInfo{
  342. {
  343. Dev: "sda",
  344. Sector: 15625879552,
  345. Block: 512,
  346. Size: 15625879552 * 512 / 1024 / 1024,
  347. Rotate: true,
  348. Kernel: "megaraid_sas",
  349. PCIClass: "0x010400",
  350. ModuleInfo: "DELL PERC H730P Mini 4.26",
  351. Driver: "raid",
  352. },
  353. },
  354. },
  355. }
  356. for _, tt := range tests {
  357. t.Run(tt.name, func(t *testing.T) {
  358. got := ParseDiskInfo(tt.args.lines, tt.args.driver)
  359. gotStr := jsonutils.Marshal(got).PrettyString()
  360. wantStr := jsonutils.Marshal(tt.want).PrettyString()
  361. if !reflect.DeepEqual(gotStr, wantStr) {
  362. t.Errorf("ParseDiskInfo() = %v, want %v", gotStr, wantStr)
  363. }
  364. })
  365. }
  366. }
  367. func TestParseSGMap(t *testing.T) {
  368. tests := []struct {
  369. name string
  370. lines []string
  371. want []compute.SGMapItem
  372. }{
  373. {
  374. name: "empty",
  375. lines: []string{""},
  376. want: []compute.SGMapItem{},
  377. },
  378. {
  379. name: "normal",
  380. lines: []string{
  381. "/dev/sg0 0 0 3 0 0 /dev/sda",
  382. "/dev/sg1 2 0 4 0 5 /dev/sr0",
  383. },
  384. want: []compute.SGMapItem{
  385. {
  386. SGDeviceName: "/dev/sg0",
  387. HostNumber: 0,
  388. Bus: 0,
  389. SCSIId: 3,
  390. Lun: 0,
  391. Type: 0,
  392. LinuxDeviceName: "/dev/sda",
  393. },
  394. {
  395. SGDeviceName: "/dev/sg1",
  396. HostNumber: 2,
  397. Bus: 0,
  398. SCSIId: 4,
  399. Lun: 0,
  400. Type: 5,
  401. LinuxDeviceName: "/dev/sr0",
  402. },
  403. },
  404. },
  405. }
  406. for _, tt := range tests {
  407. t.Run(tt.name, func(t *testing.T) {
  408. if got := ParseSGMap(tt.lines); !reflect.DeepEqual(got, tt.want) {
  409. t.Errorf("ParseSGMap() = %v, want %v", got, tt.want)
  410. }
  411. })
  412. }
  413. }
  414. func TestParseIPMIUser(t *testing.T) {
  415. tests := []struct {
  416. name string
  417. args []string
  418. want []compute.IPMIUser
  419. }{
  420. {
  421. name: "empty line",
  422. args: []string{"ID Name Callin Link Auth IPMI Msg Channel Priv Limit"},
  423. want: []compute.IPMIUser{},
  424. },
  425. {
  426. name: "users",
  427. args: []string{
  428. "ID Name Callin Link Auth IPMI Msg Channel Priv Limit",
  429. "1 root true false true ADMINISTRATOR",
  430. "2 admin true false true ADMINISTRATOR",
  431. "3 true false true USER",
  432. "4 (Empty User) true false false NO ACCESS",
  433. "5 (Empty User) true false false NO ACCESS",
  434. },
  435. want: []compute.IPMIUser{
  436. {
  437. Id: 1,
  438. Name: "root",
  439. Priv: "ADMINISTRATOR",
  440. },
  441. {
  442. Id: 2,
  443. Name: "admin",
  444. Priv: "ADMINISTRATOR",
  445. },
  446. {
  447. Id: 4,
  448. Name: "",
  449. Priv: "",
  450. },
  451. {
  452. Id: 5,
  453. Name: "",
  454. Priv: "",
  455. },
  456. },
  457. },
  458. }
  459. for _, tt := range tests {
  460. t.Run(tt.name, func(t *testing.T) {
  461. if got := ParseIPMIUser(tt.args); !reflect.DeepEqual(got, tt.want) {
  462. t.Errorf("ParseIPMIUser() = %v, want %v", got, tt.want)
  463. }
  464. })
  465. }
  466. }