useragent_test.go 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. package parser
  2. import (
  3. "testing"
  4. "github.com/stretchr/testify/assert"
  5. )
  6. func TestSimpleUserAgentParser_Parse(t *testing.T) {
  7. parser := NewSimpleUserAgentParser()
  8. testCases := []struct {
  9. name string
  10. userAgent string
  11. expectedInfo UserAgentInfo
  12. }{
  13. {
  14. name: "Chrome on Windows",
  15. userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
  16. expectedInfo: UserAgentInfo{
  17. Browser: "Chrome",
  18. BrowserVer: "91.0",
  19. OS: "Windows",
  20. OSVersion: "10",
  21. DeviceType: "Desktop",
  22. },
  23. },
  24. {
  25. name: "Firefox on Ubuntu",
  26. userAgent: "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:89.0) Gecko/20100101 Firefox/89.0",
  27. expectedInfo: UserAgentInfo{
  28. Browser: "Firefox",
  29. BrowserVer: "89.0",
  30. OS: "Ubuntu",
  31. OSVersion: "",
  32. DeviceType: "Desktop",
  33. },
  34. },
  35. {
  36. name: "Safari on iPhone",
  37. userAgent: "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Mobile/15E148 Safari/604.1",
  38. expectedInfo: UserAgentInfo{
  39. Browser: "Safari",
  40. BrowserVer: "14.1",
  41. OS: "iOS",
  42. OSVersion: "14.6",
  43. DeviceType: "iPhone",
  44. },
  45. },
  46. {
  47. name: "Safari on iPad",
  48. userAgent: "Mozilla/5.0 (iPad; CPU OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Mobile/15E148 Safari/604.1",
  49. expectedInfo: UserAgentInfo{
  50. Browser: "Safari",
  51. BrowserVer: "14.1",
  52. OS: "iOS",
  53. OSVersion: "14.6",
  54. DeviceType: "iPad",
  55. },
  56. },
  57. {
  58. name: "WeChat Browser",
  59. userAgent: "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.7(0x18000733) NetType/WIFI Language/zh_CN",
  60. expectedInfo: UserAgentInfo{
  61. Browser: "WeChat",
  62. BrowserVer: "8.0",
  63. OS: "iOS",
  64. OSVersion: "14.6",
  65. DeviceType: "iPhone",
  66. },
  67. },
  68. {
  69. name: "Chrome on Android Phone",
  70. userAgent: "Mozilla/5.0 (Linux; Android 11; SM-G991B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.120 Mobile Safari/537.36",
  71. expectedInfo: UserAgentInfo{
  72. Browser: "Chrome",
  73. BrowserVer: "91.0",
  74. OS: "Android",
  75. OSVersion: "11",
  76. DeviceType: "Mobile",
  77. },
  78. },
  79. {
  80. name: "Chrome on Android Tablet",
  81. userAgent: "Mozilla/5.0 (Linux; Android 11; SM-T870) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.120 Safari/537.36",
  82. expectedInfo: UserAgentInfo{
  83. Browser: "Chrome",
  84. BrowserVer: "91.0",
  85. OS: "Android",
  86. OSVersion: "11",
  87. DeviceType: "Tablet",
  88. },
  89. },
  90. {
  91. name: "Edge Browser",
  92. 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",
  93. expectedInfo: UserAgentInfo{
  94. Browser: "Edge",
  95. BrowserVer: "91.0",
  96. OS: "Windows",
  97. OSVersion: "10",
  98. DeviceType: "Desktop",
  99. },
  100. },
  101. {
  102. name: "UC Browser",
  103. userAgent: "Mozilla/5.0 (Linux; U; Android 8.1.0; zh-CN; EML-AL00 Build/HUAWEIEML-AL00) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 UCBrowser/11.9.4.974 Mobile Safari/537.36",
  104. expectedInfo: UserAgentInfo{
  105. Browser: "UC Browser",
  106. BrowserVer: "11.9",
  107. OS: "Android",
  108. OSVersion: "8.1",
  109. DeviceType: "Mobile",
  110. },
  111. },
  112. {
  113. name: "QQ Browser",
  114. userAgent: "Mozilla/5.0 (Linux; Android 5.0; SM-N9100 Build/LRX21V; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/53.0.2785.49 Mobile MQQBrowser/6.2 TBS/043632 Safari/537.36 MicroMessenger/6.6.1.1220(0x26060135) NetType/WIFI Language/zh_CN",
  115. expectedInfo: UserAgentInfo{
  116. Browser: "WeChat",
  117. BrowserVer: "6.6",
  118. OS: "Android",
  119. OSVersion: "5",
  120. DeviceType: "Mobile",
  121. },
  122. },
  123. {
  124. name: "Googlebot",
  125. userAgent: "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)",
  126. expectedInfo: UserAgentInfo{
  127. Browser: "Bot",
  128. BrowserVer: "",
  129. OS: "Unknown",
  130. OSVersion: "",
  131. DeviceType: "Bot",
  132. },
  133. },
  134. {
  135. name: "Samsung Browser",
  136. userAgent: "Mozilla/5.0 (Linux; Android 9; SM-G973F) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/9.2 Chrome/67.0.3396.87 Mobile Safari/537.36",
  137. expectedInfo: UserAgentInfo{
  138. Browser: "Samsung Browser",
  139. BrowserVer: "9.2",
  140. OS: "Android",
  141. OSVersion: "9",
  142. DeviceType: "Mobile",
  143. },
  144. },
  145. }
  146. for _, tc := range testCases {
  147. t.Run(tc.name, func(t *testing.T) {
  148. result := parser.Parse(tc.userAgent)
  149. assert.Equal(t, tc.expectedInfo.Browser, result.Browser, "Browser mismatch")
  150. assert.Equal(t, tc.expectedInfo.BrowserVer, result.BrowserVer, "Browser version mismatch")
  151. assert.Equal(t, tc.expectedInfo.OS, result.OS, "OS mismatch")
  152. assert.Equal(t, tc.expectedInfo.OSVersion, result.OSVersion, "OS version mismatch")
  153. assert.Equal(t, tc.expectedInfo.DeviceType, result.DeviceType, "Device type mismatch")
  154. })
  155. }
  156. }
  157. func TestSimpleUserAgentParser_IsBot(t *testing.T) {
  158. parser := NewSimpleUserAgentParser()
  159. testCases := []struct {
  160. name string
  161. userAgent string
  162. expected bool
  163. }{
  164. {
  165. name: "Googlebot",
  166. userAgent: "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)",
  167. expected: true,
  168. },
  169. {
  170. name: "Bingbot",
  171. userAgent: "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)",
  172. expected: true,
  173. },
  174. {
  175. name: "Regular Chrome",
  176. userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
  177. expected: false,
  178. },
  179. }
  180. for _, tc := range testCases {
  181. t.Run(tc.name, func(t *testing.T) {
  182. result := parser.IsBot(tc.userAgent)
  183. assert.Equal(t, tc.expected, result)
  184. })
  185. }
  186. }
  187. func TestSimpleUserAgentParser_IsMobile(t *testing.T) {
  188. parser := NewSimpleUserAgentParser()
  189. testCases := []struct {
  190. name string
  191. userAgent string
  192. expected bool
  193. }{
  194. {
  195. name: "iPhone",
  196. userAgent: "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15",
  197. expected: true,
  198. },
  199. {
  200. name: "Android Phone",
  201. userAgent: "Mozilla/5.0 (Linux; Android 11; SM-G991B) AppleWebKit/537.36 Chrome/91.0.4472.120 Mobile Safari/537.36",
  202. expected: true,
  203. },
  204. {
  205. name: "Desktop Chrome",
  206. userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/91.0.4472.124 Safari/537.36",
  207. expected: false,
  208. },
  209. {
  210. name: "iPad",
  211. userAgent: "Mozilla/5.0 (iPad; CPU OS 14_6 like Mac OS X) AppleWebKit/605.1.15",
  212. expected: false, // iPad should be tablet, not mobile
  213. },
  214. }
  215. for _, tc := range testCases {
  216. t.Run(tc.name, func(t *testing.T) {
  217. result := parser.IsMobile(tc.userAgent)
  218. assert.Equal(t, tc.expected, result)
  219. })
  220. }
  221. }
  222. func TestSimpleUserAgentParser_IsTablet(t *testing.T) {
  223. parser := NewSimpleUserAgentParser()
  224. testCases := []struct {
  225. name string
  226. userAgent string
  227. expected bool
  228. }{
  229. {
  230. name: "iPad",
  231. userAgent: "Mozilla/5.0 (iPad; CPU OS 14_6 like Mac OS X) AppleWebKit/605.1.15",
  232. expected: true,
  233. },
  234. {
  235. name: "Android Tablet",
  236. userAgent: "Mozilla/5.0 (Linux; Android 11; SM-T870) AppleWebKit/537.36 Chrome/91.0.4472.120 Safari/537.36",
  237. expected: true,
  238. },
  239. {
  240. name: "iPhone",
  241. userAgent: "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15",
  242. expected: false,
  243. },
  244. {
  245. name: "Desktop",
  246. userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
  247. expected: false,
  248. },
  249. }
  250. for _, tc := range testCases {
  251. t.Run(tc.name, func(t *testing.T) {
  252. result := parser.IsTablet(tc.userAgent)
  253. assert.Equal(t, tc.expected, result)
  254. })
  255. }
  256. }
  257. func TestCachedUserAgentParser_Enhanced(t *testing.T) {
  258. baseParser := NewSimpleUserAgentParser()
  259. cachedParser := NewCachedUserAgentParser(baseParser, 10)
  260. userAgent := "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/91.0.4472.124 Safari/537.36"
  261. // First call should parse and cache
  262. result1 := cachedParser.Parse(userAgent)
  263. assert.Equal(t, "Chrome", result1.Browser)
  264. // Second call should return cached result
  265. result2 := cachedParser.Parse(userAgent)
  266. assert.Equal(t, result1, result2)
  267. // Check cache stats
  268. size, maxSize := cachedParser.GetCacheStats()
  269. assert.Equal(t, 1, size)
  270. assert.Equal(t, 10, maxSize)
  271. // Clear cache
  272. cachedParser.ClearCache()
  273. size, _ = cachedParser.GetCacheStats()
  274. assert.Equal(t, 0, size)
  275. }
  276. func TestSimpleUserAgentParser_GetSimpleDeviceType(t *testing.T) {
  277. parser := NewSimpleUserAgentParser()
  278. testCases := []struct {
  279. name string
  280. userAgent string
  281. expected string
  282. }{
  283. {
  284. name: "iPhone",
  285. userAgent: "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15",
  286. expected: "Mobile",
  287. },
  288. {
  289. name: "iPad",
  290. userAgent: "Mozilla/5.0 (iPad; CPU OS 14_6 like Mac OS X) AppleWebKit/605.1.15",
  291. expected: "Tablet",
  292. },
  293. {
  294. name: "Bot",
  295. userAgent: "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)",
  296. expected: "Bot",
  297. },
  298. {
  299. name: "Desktop",
  300. userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
  301. expected: "Desktop",
  302. },
  303. }
  304. for _, tc := range testCases {
  305. t.Run(tc.name, func(t *testing.T) {
  306. result := parser.GetSimpleDeviceType(tc.userAgent)
  307. assert.Equal(t, tc.expected, result)
  308. })
  309. }
  310. }