log_parser_useragent_test.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. package nginx_log
  2. import (
  3. "testing"
  4. )
  5. func TestSimpleUserAgentParser_Parse(t *testing.T) {
  6. parser := NewSimpleUserAgentParser()
  7. testCases := []struct {
  8. name string
  9. userAgent string
  10. expected UserAgentInfo
  11. }{
  12. {
  13. name: "Chrome on Windows",
  14. userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
  15. expected: UserAgentInfo{
  16. Browser: "Chrome",
  17. BrowserVer: "91.0",
  18. OS: "Windows 10",
  19. DeviceType: "Desktop",
  20. },
  21. },
  22. {
  23. name: "Mobile Safari",
  24. userAgent: "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1",
  25. expected: UserAgentInfo{
  26. Browser: "Safari",
  27. OS: "iOS",
  28. DeviceType: "iPhone",
  29. },
  30. },
  31. {
  32. name: "Bot",
  33. userAgent: "Googlebot/2.1 (+http://www.google.com/bot.html)",
  34. expected: UserAgentInfo{
  35. Browser: "Unknown",
  36. OS: "Unknown",
  37. DeviceType: "Bot",
  38. },
  39. },
  40. }
  41. for _, tc := range testCases {
  42. t.Run(tc.name, func(t *testing.T) {
  43. result := parser.Parse(tc.userAgent)
  44. if result.Browser != tc.expected.Browser {
  45. t.Errorf("expected Browser %q, got %q", tc.expected.Browser, result.Browser)
  46. }
  47. if result.DeviceType != tc.expected.DeviceType {
  48. t.Errorf("expected DeviceType %q, got %q", tc.expected.DeviceType, result.DeviceType)
  49. }
  50. })
  51. }
  52. }
  53. func TestUserAgentVersionParsing(t *testing.T) {
  54. parser := NewSimpleUserAgentParser()
  55. testCases := []struct {
  56. name string
  57. userAgent string
  58. expectedBrowser string
  59. expectedVersion string
  60. }{
  61. {
  62. name: "Chrome with correct version",
  63. userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
  64. expectedBrowser: "Chrome",
  65. expectedVersion: "91.0",
  66. },
  67. {
  68. name: "Safari with correct version",
  69. userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15",
  70. expectedBrowser: "Safari",
  71. expectedVersion: "14.1",
  72. },
  73. {
  74. name: "Firefox with correct version",
  75. userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0",
  76. expectedBrowser: "Firefox",
  77. expectedVersion: "89.0",
  78. },
  79. {
  80. name: "Edge with correct version",
  81. userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.59",
  82. expectedBrowser: "Edge",
  83. expectedVersion: "91.0",
  84. },
  85. }
  86. for _, tc := range testCases {
  87. t.Run(tc.name, func(t *testing.T) {
  88. result := parser.Parse(tc.userAgent)
  89. if result.Browser != tc.expectedBrowser {
  90. t.Errorf("expected browser %q, got %q", tc.expectedBrowser, result.Browser)
  91. }
  92. if result.BrowserVer != tc.expectedVersion {
  93. t.Errorf("expected version %q, got %q", tc.expectedVersion, result.BrowserVer)
  94. }
  95. })
  96. }
  97. }
  98. func TestOSVersionParsing(t *testing.T) {
  99. parser := NewSimpleUserAgentParser()
  100. testCases := []struct {
  101. name string
  102. userAgent string
  103. expectedOS string
  104. expectedOSVer string
  105. }{
  106. {
  107. name: "Windows 10",
  108. userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
  109. expectedOS: "Windows 10",
  110. expectedOSVer: "10.0",
  111. },
  112. {
  113. name: "macOS",
  114. userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36",
  115. expectedOS: "macOS",
  116. expectedOSVer: "10.15.7",
  117. },
  118. {
  119. name: "iOS",
  120. userAgent: "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15",
  121. expectedOS: "iOS",
  122. expectedOSVer: "14.6",
  123. },
  124. {
  125. name: "Android",
  126. userAgent: "Mozilla/5.0 (Linux; Android 11; SM-G991B) AppleWebKit/537.36",
  127. expectedOS: "Android",
  128. expectedOSVer: "11",
  129. },
  130. }
  131. for _, tc := range testCases {
  132. t.Run(tc.name, func(t *testing.T) {
  133. result := parser.Parse(tc.userAgent)
  134. if result.OS != tc.expectedOS {
  135. t.Errorf("expected OS %q, got %q", tc.expectedOS, result.OS)
  136. }
  137. if result.OSVersion != tc.expectedOSVer {
  138. t.Errorf("expected OS version %q, got %q", tc.expectedOSVer, result.OSVersion)
  139. }
  140. })
  141. }
  142. }
  143. func TestDeviceTypeParsing(t *testing.T) {
  144. parser := NewSimpleUserAgentParser()
  145. testCases := []struct {
  146. name string
  147. userAgent string
  148. expectedDeviceType string
  149. }{
  150. {
  151. name: "Desktop Chrome",
  152. userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
  153. expectedDeviceType: "Desktop",
  154. },
  155. {
  156. name: "iPhone Safari",
  157. userAgent: "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15",
  158. expectedDeviceType: "iPhone",
  159. },
  160. {
  161. name: "iPad Safari",
  162. userAgent: "Mozilla/5.0 (iPad; CPU OS 14_6 like Mac OS X) AppleWebKit/605.1.15",
  163. expectedDeviceType: "iPad",
  164. },
  165. {
  166. name: "Android Mobile",
  167. userAgent: "Mozilla/5.0 (Linux; Android 11; SM-G991B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.120 Mobile Safari/537.36",
  168. expectedDeviceType: "Mobile",
  169. },
  170. {
  171. name: "Android Tablet",
  172. userAgent: "Mozilla/5.0 (Linux; Android 11; SM-T870) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.120 Safari/537.36",
  173. expectedDeviceType: "Tablet",
  174. },
  175. {
  176. name: "Bot",
  177. userAgent: "Googlebot/2.1 (+http://www.google.com/bot.html)",
  178. expectedDeviceType: "Bot",
  179. },
  180. }
  181. for _, tc := range testCases {
  182. t.Run(tc.name, func(t *testing.T) {
  183. result := parser.Parse(tc.userAgent)
  184. if result.DeviceType != tc.expectedDeviceType {
  185. t.Errorf("expected device type %q, got %q", tc.expectedDeviceType, result.DeviceType)
  186. }
  187. })
  188. }
  189. }
  190. func TestAndroidOSParsing(t *testing.T) {
  191. parser := NewSimpleUserAgentParser()
  192. testCases := []struct {
  193. name string
  194. userAgent string
  195. expectedOS string
  196. expectedOSVer string
  197. expectedDevice string
  198. }{
  199. {
  200. name: "Samsung Galaxy S21",
  201. userAgent: "Mozilla/5.0 (Linux; Android 11; SM-G991B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.120 Mobile Safari/537.36",
  202. expectedOS: "Android",
  203. expectedOSVer: "11",
  204. expectedDevice: "Mobile",
  205. },
  206. {
  207. name: "Samsung Galaxy Tab",
  208. userAgent: "Mozilla/5.0 (Linux; Android 11; SM-T870) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.120 Safari/537.36",
  209. expectedOS: "Android",
  210. expectedOSVer: "11",
  211. expectedDevice: "Tablet",
  212. },
  213. {
  214. name: "Pixel 5",
  215. userAgent: "Mozilla/5.0 (Linux; Android 12; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Mobile Safari/537.36",
  216. expectedOS: "Android",
  217. expectedOSVer: "12",
  218. expectedDevice: "Mobile",
  219. },
  220. {
  221. name: "Android 10",
  222. userAgent: "Mozilla/5.0 (Linux; Android 10; SM-A505FN) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Mobile Safari/537.36",
  223. expectedOS: "Android",
  224. expectedOSVer: "10",
  225. expectedDevice: "Mobile",
  226. },
  227. }
  228. for _, tc := range testCases {
  229. t.Run(tc.name, func(t *testing.T) {
  230. result := parser.Parse(tc.userAgent)
  231. if result.OS != tc.expectedOS {
  232. t.Errorf("expected OS %q, got %q", tc.expectedOS, result.OS)
  233. }
  234. if result.OSVersion != tc.expectedOSVer {
  235. t.Errorf("expected OS version %q, got %q", tc.expectedOSVer, result.OSVersion)
  236. }
  237. if result.DeviceType != tc.expectedDevice {
  238. t.Errorf("expected device type %q, got %q", tc.expectedDevice, result.DeviceType)
  239. }
  240. })
  241. }
  242. }
  243. func TestRealWorldAndroidUserAgents(t *testing.T) {
  244. parser := NewSimpleUserAgentParser()
  245. testCases := []struct {
  246. name string
  247. userAgent string
  248. expectedOS string
  249. expectedOSVer string
  250. expectedDevice string
  251. expectedBrowser string
  252. }{
  253. {
  254. name: "Samsung Internet on Galaxy S20",
  255. userAgent: "Mozilla/5.0 (Linux; Android 10; SM-G981B) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/12.0 Chrome/79.0.3945.136 Mobile Safari/537.36",
  256. expectedOS: "Android",
  257. expectedOSVer: "10",
  258. expectedDevice: "Mobile",
  259. expectedBrowser: "Samsung Internet",
  260. },
  261. {
  262. name: "Chrome on OnePlus",
  263. userAgent: "Mozilla/5.0 (Linux; Android 11; OnePlus 8 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.164 Mobile Safari/537.36",
  264. expectedOS: "Android",
  265. expectedOSVer: "11",
  266. expectedDevice: "Mobile",
  267. expectedBrowser: "Chrome",
  268. },
  269. {
  270. name: "Firefox on Android",
  271. userAgent: "Mozilla/5.0 (Mobile; rv:89.0) Gecko/89.0 Firefox/89.0",
  272. expectedOS: "Android",
  273. expectedOSVer: "",
  274. expectedDevice: "Mobile",
  275. expectedBrowser: "Firefox",
  276. },
  277. {
  278. name: "Edge on Android",
  279. userAgent: "Mozilla/5.0 (Linux; Android 10; HD1913) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Mobile Safari/537.36 EdgA/46.3.4.5155",
  280. expectedOS: "Android",
  281. expectedOSVer: "10",
  282. expectedDevice: "Mobile",
  283. expectedBrowser: "Edge",
  284. },
  285. {
  286. name: "Opera on Android",
  287. userAgent: "Mozilla/5.0 (Linux; Android 10; SM-A205U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.88 Mobile Safari/537.36 OPR/64.2.3282.60455",
  288. expectedOS: "Android",
  289. expectedOSVer: "10",
  290. expectedDevice: "Mobile",
  291. expectedBrowser: "Opera",
  292. },
  293. }
  294. for _, tc := range testCases {
  295. t.Run(tc.name, func(t *testing.T) {
  296. result := parser.Parse(tc.userAgent)
  297. if result.OS != tc.expectedOS {
  298. t.Errorf("expected OS %q, got %q", tc.expectedOS, result.OS)
  299. }
  300. if result.OSVersion != tc.expectedOSVer && tc.expectedOSVer != "" {
  301. t.Errorf("expected OS version %q, got %q", tc.expectedOSVer, result.OSVersion)
  302. }
  303. if result.DeviceType != tc.expectedDevice {
  304. t.Errorf("expected device type %q, got %q", tc.expectedDevice, result.DeviceType)
  305. }
  306. if result.Browser != tc.expectedBrowser {
  307. t.Errorf("expected browser %q, got %q", tc.expectedBrowser, result.Browser)
  308. }
  309. })
  310. }
  311. }