implement chat tests, fix database usage
This commit is contained in:
parent
28f296e546
commit
c10bf098c5
487
coverage.out
487
coverage.out
@ -1,487 +0,0 @@
|
||||
mode: set
|
||||
eq2emu/internal/alt_advancement/database.go:9.53,20.16 3 0
|
||||
eq2emu/internal/alt_advancement/database.go:20.16,22.3 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:23.2,26.18 3 0
|
||||
eq2emu/internal/alt_advancement/database.go:26.18,54.17 3 0
|
||||
eq2emu/internal/alt_advancement/database.go:54.17,56.4 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:59.3,62.65 2 0
|
||||
eq2emu/internal/alt_advancement/database.go:62.65,64.24 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:64.24,66.5 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:67.4,67.12 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:70.3,70.16 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:73.2,73.34 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:73.34,75.3 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:78.2,80.22 2 0
|
||||
eq2emu/internal/alt_advancement/database.go:80.22,82.3 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:84.2,84.12 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:88.47,95.16 3 0
|
||||
eq2emu/internal/alt_advancement/database.go:95.16,97.3 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:98.2,101.18 3 0
|
||||
eq2emu/internal/alt_advancement/database.go:101.18,109.17 3 0
|
||||
eq2emu/internal/alt_advancement/database.go:109.17,111.4 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:114.3,114.61 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:114.61,116.24 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:116.24,118.5 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:119.4,119.12 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:122.3,122.16 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:125.2,125.34 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:125.34,127.3 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:129.2,129.22 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:129.22,131.3 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:133.2,133.12 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:137.81,148.16 4 0
|
||||
eq2emu/internal/alt_advancement/database.go:148.16,150.3 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:151.2,156.18 3 0
|
||||
eq2emu/internal/alt_advancement/database.go:156.18,166.17 3 0
|
||||
eq2emu/internal/alt_advancement/database.go:166.17,168.4 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:170.3,170.47 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:170.47,172.4 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:173.3,173.87 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:176.2,176.34 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:176.34,178.3 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:181.2,181.51 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:181.51,185.3 3 0
|
||||
eq2emu/internal/alt_advancement/database.go:188.2,189.16 2 0
|
||||
eq2emu/internal/alt_advancement/database.go:189.16,191.3 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:194.2,195.16 2 0
|
||||
eq2emu/internal/alt_advancement/database.go:195.16,197.3 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:200.2,202.25 2 0
|
||||
eq2emu/internal/alt_advancement/database.go:206.99,214.16 3 0
|
||||
eq2emu/internal/alt_advancement/database.go:214.16,216.3 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:217.2,219.18 2 0
|
||||
eq2emu/internal/alt_advancement/database.go:219.18,234.17 4 0
|
||||
eq2emu/internal/alt_advancement/database.go:234.17,236.4 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:239.3,239.93 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:239.93,241.4 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:242.3,242.89 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:242.89,244.4 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:246.3,246.53 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:249.2,249.19 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:253.97,270.16 4 0
|
||||
eq2emu/internal/alt_advancement/database.go:270.16,272.50 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:272.50,279.4 6 0
|
||||
eq2emu/internal/alt_advancement/database.go:280.3,280.64 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:283.2,283.12 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:287.74,289.32 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:289.32,295.51 4 0
|
||||
eq2emu/internal/alt_advancement/database.go:295.51,296.27 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:296.27,298.5 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:300.3,303.28 3 0
|
||||
eq2emu/internal/alt_advancement/database.go:308.72,309.24 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:309.24,311.3 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:314.2,315.16 2 0
|
||||
eq2emu/internal/alt_advancement/database.go:315.16,317.3 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:318.2,322.16 3 0
|
||||
eq2emu/internal/alt_advancement/database.go:322.16,324.3 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:327.2,328.16 2 0
|
||||
eq2emu/internal/alt_advancement/database.go:328.16,330.3 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:333.2,334.16 2 0
|
||||
eq2emu/internal/alt_advancement/database.go:334.16,336.3 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:339.2,339.35 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:339.35,341.3 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:344.2,347.12 3 0
|
||||
eq2emu/internal/alt_advancement/database.go:351.94,369.2 3 0
|
||||
eq2emu/internal/alt_advancement/database.go:372.96,375.16 2 0
|
||||
eq2emu/internal/alt_advancement/database.go:375.16,377.3 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:380.2,386.50 2 0
|
||||
eq2emu/internal/alt_advancement/database.go:386.50,397.17 2 0
|
||||
eq2emu/internal/alt_advancement/database.go:397.17,399.4 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:402.2,402.12 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:406.97,409.16 2 0
|
||||
eq2emu/internal/alt_advancement/database.go:409.16,411.3 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:414.2,419.49 2 0
|
||||
eq2emu/internal/alt_advancement/database.go:419.49,421.59 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:421.59,422.43 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:422.43,431.19 2 0
|
||||
eq2emu/internal/alt_advancement/database.go:431.19,433.6 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:438.2,438.12 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:442.89,450.16 3 0
|
||||
eq2emu/internal/alt_advancement/database.go:450.16,452.3 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:453.2,457.18 3 0
|
||||
eq2emu/internal/alt_advancement/database.go:457.18,467.17 3 0
|
||||
eq2emu/internal/alt_advancement/database.go:467.17,469.4 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:471.3,471.41 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:471.41,473.4 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:474.3,474.75 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:477.2,477.34 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:477.34,479.3 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:481.2,481.23 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:485.65,488.16 2 0
|
||||
eq2emu/internal/alt_advancement/database.go:488.16,490.3 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:491.2,500.31 3 0
|
||||
eq2emu/internal/alt_advancement/database.go:500.31,503.17 3 0
|
||||
eq2emu/internal/alt_advancement/database.go:503.17,505.4 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:509.2,509.35 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:509.35,511.3 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:513.2,513.12 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:517.75,523.16 4 0
|
||||
eq2emu/internal/alt_advancement/database.go:523.16,525.3 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:526.2,531.16 4 0
|
||||
eq2emu/internal/alt_advancement/database.go:531.16,533.3 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:534.2,546.16 4 0
|
||||
eq2emu/internal/alt_advancement/database.go:546.16,548.3 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:549.2,552.18 3 0
|
||||
eq2emu/internal/alt_advancement/database.go:552.18,556.17 4 0
|
||||
eq2emu/internal/alt_advancement/database.go:556.17,558.4 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:559.3,559.29 1 0
|
||||
eq2emu/internal/alt_advancement/database.go:561.2,563.19 2 0
|
||||
eq2emu/internal/alt_advancement/interfaces.go:191.130,198.2 1 0
|
||||
eq2emu/internal/alt_advancement/interfaces.go:282.77,287.2 1 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:290.54,292.2 1 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:295.45,297.2 1 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:300.79,302.2 1 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:305.70,307.2 1 0
|
||||
eq2emu/internal/alt_advancement/interfaces.go:310.51,312.2 1 0
|
||||
eq2emu/internal/alt_advancement/interfaces.go:315.77,317.2 1 0
|
||||
eq2emu/internal/alt_advancement/interfaces.go:320.60,322.2 1 0
|
||||
eq2emu/internal/alt_advancement/interfaces.go:325.67,327.2 1 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:330.62,332.2 1 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:335.69,337.2 1 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:340.59,342.2 1 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:345.42,347.2 1 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:355.57,357.2 1 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:360.48,362.2 1 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:365.52,367.2 1 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:370.45,372.2 1 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:375.45,377.2 1 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:380.54,382.2 1 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:385.44,387.2 1 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:390.46,392.2 1 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:395.67,397.2 1 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:405.57,407.2 1 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:410.48,412.2 1 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:415.52,417.2 1 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:420.48,422.2 1 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:425.59,427.2 1 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:430.54,432.2 1 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:446.53,453.2 1 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:456.69,460.46 3 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:460.46,463.3 2 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:465.2,466.19 2 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:470.69,474.39 3 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:474.39,476.27 1 0
|
||||
eq2emu/internal/alt_advancement/interfaces.go:476.27,478.9 2 0
|
||||
eq2emu/internal/alt_advancement/interfaces.go:482.2,482.34 1 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:486.52,491.2 3 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:494.82,498.58 3 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:498.58,501.3 2 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:503.2,504.19 2 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:508.87,512.45 3 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:512.45,514.33 1 0
|
||||
eq2emu/internal/alt_advancement/interfaces.go:514.33,516.9 2 0
|
||||
eq2emu/internal/alt_advancement/interfaces.go:520.2,520.43 1 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:524.66,529.2 3 0
|
||||
eq2emu/internal/alt_advancement/interfaces.go:532.73,536.49 3 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:536.49,540.3 3 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:542.2,543.19 2 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:547.75,551.42 3 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:551.42,553.30 1 0
|
||||
eq2emu/internal/alt_advancement/interfaces.go:553.30,555.9 2 0
|
||||
eq2emu/internal/alt_advancement/interfaces.go:559.2,560.33 2 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:564.58,569.2 3 0
|
||||
eq2emu/internal/alt_advancement/interfaces.go:572.33,579.2 5 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:582.59,594.2 3 1
|
||||
eq2emu/internal/alt_advancement/interfaces.go:597.51,602.2 3 1
|
||||
eq2emu/internal/alt_advancement/manager.go:9.54,19.2 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:22.36,24.40 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:24.40,26.3 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:29.2,29.34 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:29.34,32.3 2 1
|
||||
eq2emu/internal/alt_advancement/manager.go:34.2,34.54 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:34.54,37.3 2 1
|
||||
eq2emu/internal/alt_advancement/manager.go:39.2,39.12 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:43.35,48.24 3 1
|
||||
eq2emu/internal/alt_advancement/manager.go:48.24,50.3 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:52.2,52.12 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:56.39,57.9 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:58.21,59.15 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:60.10,61.14 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:66.41,67.24 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:67.24,69.3 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:71.2,74.58 2 1
|
||||
eq2emu/internal/alt_advancement/manager.go:74.58,76.3 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:79.2,79.52 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:79.52,81.3 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:84.2,94.12 8 1
|
||||
eq2emu/internal/alt_advancement/manager.go:98.43,110.16 7 1
|
||||
eq2emu/internal/alt_advancement/manager.go:110.16,112.3 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:114.2,114.12 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:118.78,122.2 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:125.90,126.24 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:126.24,128.3 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:130.2,131.16 2 1
|
||||
eq2emu/internal/alt_advancement/manager.go:131.16,133.3 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:135.2,135.25 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:139.60,140.24 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:140.24,142.3 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:145.2,146.24 2 1
|
||||
eq2emu/internal/alt_advancement/manager.go:146.24,148.3 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:151.2,151.46 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:155.82,158.65 2 1
|
||||
eq2emu/internal/alt_advancement/manager.go:158.65,161.3 2 1
|
||||
eq2emu/internal/alt_advancement/manager.go:162.2,169.65 4 1
|
||||
eq2emu/internal/alt_advancement/manager.go:169.65,171.3 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:174.2,175.16 2 1
|
||||
eq2emu/internal/alt_advancement/manager.go:175.16,177.3 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:180.2,185.25 3 1
|
||||
eq2emu/internal/alt_advancement/manager.go:189.89,192.16 2 1
|
||||
eq2emu/internal/alt_advancement/manager.go:192.16,194.3 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:197.2,198.19 2 1
|
||||
eq2emu/internal/alt_advancement/manager.go:198.19,200.3 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:203.2,203.25 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:203.25,204.90 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:204.90,207.4 2 0
|
||||
eq2emu/internal/alt_advancement/manager.go:211.2,212.16 2 1
|
||||
eq2emu/internal/alt_advancement/manager.go:212.16,214.3 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:217.2,221.24 3 1
|
||||
eq2emu/internal/alt_advancement/manager.go:221.24,223.3 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:226.2,226.26 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:226.26,228.3 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:230.2,230.12 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:234.70,237.24 2 1
|
||||
eq2emu/internal/alt_advancement/manager.go:237.24,239.3 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:242.2,243.19 2 0
|
||||
eq2emu/internal/alt_advancement/manager.go:243.19,245.3 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:248.2,249.42 2 0
|
||||
eq2emu/internal/alt_advancement/manager.go:249.42,251.3 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:254.2,268.24 9 0
|
||||
eq2emu/internal/alt_advancement/manager.go:268.24,270.3 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:273.2,273.26 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:273.26,275.3 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:277.2,277.12 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:281.96,284.24 2 1
|
||||
eq2emu/internal/alt_advancement/manager.go:284.24,286.3 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:289.2,292.28 3 0
|
||||
eq2emu/internal/alt_advancement/manager.go:292.28,294.40 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:294.40,296.4 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:299.2,299.26 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:303.81,306.24 2 1
|
||||
eq2emu/internal/alt_advancement/manager.go:306.24,308.3 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:311.2,311.25 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:311.25,312.86 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:312.86,314.4 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:318.2,327.12 7 0
|
||||
eq2emu/internal/alt_advancement/manager.go:331.92,334.24 2 1
|
||||
eq2emu/internal/alt_advancement/manager.go:334.24,336.3 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:339.2,340.21 2 0
|
||||
eq2emu/internal/alt_advancement/manager.go:340.21,343.3 2 0
|
||||
eq2emu/internal/alt_advancement/manager.go:343.8,346.3 2 0
|
||||
eq2emu/internal/alt_advancement/manager.go:348.2,355.12 5 0
|
||||
eq2emu/internal/alt_advancement/manager.go:359.86,362.24 2 1
|
||||
eq2emu/internal/alt_advancement/manager.go:362.24,364.3 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:367.2,369.50 3 1
|
||||
eq2emu/internal/alt_advancement/manager.go:369.50,371.3 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:372.2,374.23 2 1
|
||||
eq2emu/internal/alt_advancement/manager.go:378.90,381.16 2 1
|
||||
eq2emu/internal/alt_advancement/manager.go:381.16,383.3 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:386.2,396.24 9 1
|
||||
eq2emu/internal/alt_advancement/manager.go:396.24,398.3 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:401.2,403.12 2 1
|
||||
eq2emu/internal/alt_advancement/manager.go:407.82,410.24 2 1
|
||||
eq2emu/internal/alt_advancement/manager.go:410.24,412.3 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:414.2,417.91 3 1
|
||||
eq2emu/internal/alt_advancement/manager.go:421.67,423.19 2 1
|
||||
eq2emu/internal/alt_advancement/manager.go:423.19,425.3 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:426.2,426.20 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:430.77,432.19 2 1
|
||||
eq2emu/internal/alt_advancement/manager.go:432.19,434.3 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:435.2,435.20 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:439.75,441.2 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:444.77,446.2 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:449.55,456.2 4 1
|
||||
eq2emu/internal/alt_advancement/manager.go:459.79,461.24 2 1
|
||||
eq2emu/internal/alt_advancement/manager.go:461.24,463.3 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:465.2,478.3 3 1
|
||||
eq2emu/internal/alt_advancement/manager.go:482.62,485.2 2 0
|
||||
eq2emu/internal/alt_advancement/manager.go:488.50,490.2 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:495.49,497.2 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:500.64,502.2 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:505.62,510.2 3 1
|
||||
eq2emu/internal/alt_advancement/manager.go:513.58,515.2 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:518.55,520.2 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:523.56,525.2 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:528.46,530.2 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:535.71,540.2 3 1
|
||||
eq2emu/internal/alt_advancement/manager.go:543.115,552.46 4 1
|
||||
eq2emu/internal/alt_advancement/manager.go:552.46,554.3 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:557.2,558.21 2 1
|
||||
eq2emu/internal/alt_advancement/manager.go:558.21,570.3 2 1
|
||||
eq2emu/internal/alt_advancement/manager.go:573.2,582.12 7 1
|
||||
eq2emu/internal/alt_advancement/manager.go:586.93,596.29 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:596.29,598.64 2 0
|
||||
eq2emu/internal/alt_advancement/manager.go:598.64,600.4 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:603.2,603.13 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:609.40,615.6 4 1
|
||||
eq2emu/internal/alt_advancement/manager.go:615.6,616.10 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:617.19,618.25 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:619.22,620.10 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:626.37,632.6 4 1
|
||||
eq2emu/internal/alt_advancement/manager.go:632.6,633.10 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:634.19,635.28 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:636.22,637.10 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:643.41,653.46 7 1
|
||||
eq2emu/internal/alt_advancement/manager.go:653.46,658.3 4 0
|
||||
eq2emu/internal/alt_advancement/manager.go:659.2,664.32 4 1
|
||||
eq2emu/internal/alt_advancement/manager.go:664.32,666.3 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:668.2,668.39 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:672.44,673.24 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:673.24,675.3 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:677.2,680.46 3 1
|
||||
eq2emu/internal/alt_advancement/manager.go:680.46,681.28 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:681.28,682.64 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:682.64,684.13 2 0
|
||||
eq2emu/internal/alt_advancement/manager.go:686.4,686.33 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:692.57,696.19 3 0
|
||||
eq2emu/internal/alt_advancement/manager.go:697.27,698.30 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:699.25,700.28 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:701.23,702.26 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:709.72,713.43 3 1
|
||||
eq2emu/internal/alt_advancement/manager.go:713.43,715.3 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:719.46,723.43 3 1
|
||||
eq2emu/internal/alt_advancement/manager.go:723.43,725.3 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:729.93,733.43 3 1
|
||||
eq2emu/internal/alt_advancement/manager.go:733.43,735.3 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:739.109,743.43 3 1
|
||||
eq2emu/internal/alt_advancement/manager.go:743.43,745.3 1 1
|
||||
eq2emu/internal/alt_advancement/manager.go:749.111,753.43 3 0
|
||||
eq2emu/internal/alt_advancement/manager.go:753.43,755.3 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:759.97,763.43 3 0
|
||||
eq2emu/internal/alt_advancement/manager.go:763.43,765.3 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:769.96,773.43 3 0
|
||||
eq2emu/internal/alt_advancement/manager.go:773.43,775.3 1 0
|
||||
eq2emu/internal/alt_advancement/manager.go:779.100,783.43 3 1
|
||||
eq2emu/internal/alt_advancement/manager.go:783.43,785.3 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:10.38,19.2 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:22.72,23.17 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:23.17,25.3 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:27.2,27.21 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:27.21,29.3 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:31.2,35.56 3 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:35.56,37.3 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:39.2,39.54 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:39.54,41.3 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:44.2,51.38 4 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:51.38,53.3 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:54.2,58.12 3 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:62.75,66.54 3 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:66.54,68.3 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:70.2,70.12 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:74.82,78.52 3 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:78.52,80.3 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:82.2,82.12 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:86.70,90.52 3 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:90.52,93.29 2 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:93.29,95.4 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:96.3,96.16 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:99.2,99.28 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:103.72,109.32 4 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:109.32,111.49 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:111.49,113.4 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:116.2,116.15 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:120.70,126.32 4 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:126.32,127.27 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:127.27,129.4 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:132.2,132.15 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:136.37,141.2 3 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:144.56,149.32 4 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:149.32,151.3 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:153.2,153.15 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:157.51,166.2 7 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:169.43,173.35 3 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:173.35,174.56 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:174.56,179.26 3 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:179.26,181.5 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:182.4,182.28 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:188.46,193.2 3 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:196.45,201.35 4 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:201.35,203.3 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:205.2,205.41 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:205.41,207.3 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:209.2,209.15 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:213.51,219.32 4 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:219.32,220.20 1 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:220.20,222.4 1 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:225.3,225.26 1 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:225.26,226.61 1 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:226.61,228.5 1 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:232.3,232.49 1 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:232.49,234.4 1 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:236.3,236.49 1 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:236.49,238.4 1 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:241.3,241.65 1 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:241.65,243.4 1 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:245.3,245.61 1 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:245.61,247.4 1 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:250.2,250.15 1 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:254.60,265.43 8 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:265.43,267.3 1 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:268.2,270.14 2 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:274.46,282.2 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:285.69,286.17 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:286.17,288.3 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:290.2,294.56 3 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:294.56,296.3 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:299.2,305.44 3 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:305.44,307.3 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:308.2,312.12 3 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:316.62,322.37 4 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:322.37,325.3 2 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:327.2,327.15 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:331.82,335.60 3 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:335.60,338.33 2 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:338.33,341.4 2 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:342.3,342.16 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:345.2,345.26 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:349.71,353.54 3 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:353.54,356.3 2 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:358.2,358.12 1 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:362.42,367.2 3 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:370.50,378.2 6 1
|
||||
eq2emu/internal/alt_advancement/master_list.go:381.51,386.2 3 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:389.52,394.41 4 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:394.41,396.3 1 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:398.2,398.42 1 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:398.42,400.3 1 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:402.2,402.16 1 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:406.59,414.37 5 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:414.37,416.3 1 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:419.2,420.37 2 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:420.37,422.24 2 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:422.24,424.4 1 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:425.3,425.27 1 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:428.2,428.15 1 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:432.65,443.51 8 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:443.51,445.3 1 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:446.2,448.14 2 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:452.76,457.29 3 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:457.29,458.13 1 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:458.13,460.4 1 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:463.2,463.16 1 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:467.78,470.27 2 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:470.27,472.3 1 0
|
||||
eq2emu/internal/alt_advancement/master_list.go:474.2,474.10 1 0
|
||||
eq2emu/internal/alt_advancement/types.go:283.47,299.2 1 1
|
||||
eq2emu/internal/alt_advancement/types.go:302.57,316.2 1 1
|
||||
eq2emu/internal/alt_advancement/types.go:319.62,331.2 1 1
|
||||
eq2emu/internal/alt_advancement/types.go:334.54,347.2 1 0
|
||||
eq2emu/internal/alt_advancement/types.go:350.51,353.2 2 1
|
||||
eq2emu/internal/alt_advancement/types.go:356.43,362.2 1 1
|
||||
eq2emu/internal/alt_advancement/types.go:365.39,366.15 1 1
|
||||
eq2emu/internal/alt_advancement/types.go:367.16,368.22 1 1
|
||||
eq2emu/internal/alt_advancement/types.go:369.19,370.25 1 1
|
||||
eq2emu/internal/alt_advancement/types.go:371.17,372.24 1 1
|
||||
eq2emu/internal/alt_advancement/types.go:373.17,374.23 1 1
|
||||
eq2emu/internal/alt_advancement/types.go:375.21,376.27 1 1
|
||||
eq2emu/internal/alt_advancement/types.go:377.19,378.25 1 1
|
||||
eq2emu/internal/alt_advancement/types.go:379.30,380.36 1 1
|
||||
eq2emu/internal/alt_advancement/types.go:381.17,382.23 1 1
|
||||
eq2emu/internal/alt_advancement/types.go:383.22,384.28 1 1
|
||||
eq2emu/internal/alt_advancement/types.go:385.18,386.24 1 1
|
||||
eq2emu/internal/alt_advancement/types.go:387.10,388.13 1 1
|
||||
eq2emu/internal/alt_advancement/types.go:393.36,394.47 1 1
|
||||
eq2emu/internal/alt_advancement/types.go:394.47,396.3 1 1
|
||||
eq2emu/internal/alt_advancement/types.go:397.2,397.18 1 1
|
||||
eq2emu/internal/alt_advancement/types.go:401.46,402.57 1 1
|
||||
eq2emu/internal/alt_advancement/types.go:402.57,404.3 1 1
|
||||
eq2emu/internal/alt_advancement/types.go:405.2,405.18 1 1
|
||||
eq2emu/internal/alt_advancement/types.go:409.59,411.2 1 1
|
906
internal/chat/chat_test.go
Normal file
906
internal/chat/chat_test.go
Normal file
@ -0,0 +1,906 @@
|
||||
package chat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// EntityWithGetID helper type for testing
|
||||
type EntityWithGetID struct {
|
||||
id int32
|
||||
}
|
||||
|
||||
func (e *EntityWithGetID) GetID() int32 {
|
||||
return e.id
|
||||
}
|
||||
|
||||
// Mock implementations for testing
|
||||
type MockChannelDatabase struct {
|
||||
channels map[string]ChatChannelData
|
||||
mu sync.RWMutex
|
||||
loadErr error
|
||||
saveErr error
|
||||
delErr error
|
||||
}
|
||||
|
||||
func NewMockChannelDatabase() *MockChannelDatabase {
|
||||
return &MockChannelDatabase{
|
||||
channels: make(map[string]ChatChannelData),
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MockChannelDatabase) LoadWorldChannels(ctx context.Context) ([]ChatChannelData, error) {
|
||||
if m.loadErr != nil {
|
||||
return nil, m.loadErr
|
||||
}
|
||||
|
||||
m.mu.RLock()
|
||||
defer m.mu.RUnlock()
|
||||
|
||||
var channels []ChatChannelData
|
||||
for _, channel := range m.channels {
|
||||
channels = append(channels, channel)
|
||||
}
|
||||
return channels, nil
|
||||
}
|
||||
|
||||
func (m *MockChannelDatabase) SaveChannel(ctx context.Context, channel ChatChannelData) error {
|
||||
if m.saveErr != nil {
|
||||
return m.saveErr
|
||||
}
|
||||
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
m.channels[channel.Name] = channel
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockChannelDatabase) DeleteChannel(ctx context.Context, channelName string) error {
|
||||
if m.delErr != nil {
|
||||
return m.delErr
|
||||
}
|
||||
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
if _, exists := m.channels[channelName]; !exists {
|
||||
return fmt.Errorf("channel not found")
|
||||
}
|
||||
delete(m.channels, channelName)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockChannelDatabase) SetLoadError(err error) {
|
||||
m.loadErr = err
|
||||
}
|
||||
|
||||
func (m *MockChannelDatabase) SetSaveError(err error) {
|
||||
m.saveErr = err
|
||||
}
|
||||
|
||||
func (m *MockChannelDatabase) SetDeleteError(err error) {
|
||||
m.delErr = err
|
||||
}
|
||||
|
||||
type MockClientManager struct {
|
||||
sentMessages []ChannelMessage
|
||||
sentLists map[int32][]ChannelInfo
|
||||
sentUpdates []ChatUpdate
|
||||
sentUserLists map[int32][]ChannelMember
|
||||
connectedClients map[int32]bool
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
type ChatUpdate struct {
|
||||
CharacterID int32
|
||||
ChannelName string
|
||||
Action int
|
||||
CharacterName string
|
||||
}
|
||||
|
||||
func NewMockClientManager() *MockClientManager {
|
||||
return &MockClientManager{
|
||||
sentLists: make(map[int32][]ChannelInfo),
|
||||
sentUserLists: make(map[int32][]ChannelMember),
|
||||
connectedClients: make(map[int32]bool),
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MockClientManager) SendChannelList(characterID int32, channels []ChannelInfo) error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
m.sentLists[characterID] = channels
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockClientManager) SendChannelMessage(characterID int32, message ChannelMessage) error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
m.sentMessages = append(m.sentMessages, message)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockClientManager) SendChannelUpdate(characterID int32, channelName string, action int, characterName string) error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
m.sentUpdates = append(m.sentUpdates, ChatUpdate{
|
||||
CharacterID: characterID,
|
||||
ChannelName: channelName,
|
||||
Action: action,
|
||||
CharacterName: characterName,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockClientManager) SendChannelUserList(characterID int32, channelName string, members []ChannelMember) error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
m.sentUserLists[characterID] = members
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockClientManager) IsClientConnected(characterID int32) bool {
|
||||
m.mu.RLock()
|
||||
defer m.mu.RUnlock()
|
||||
return m.connectedClients[characterID]
|
||||
}
|
||||
|
||||
func (m *MockClientManager) SetClientConnected(characterID int32, connected bool) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
m.connectedClients[characterID] = connected
|
||||
}
|
||||
|
||||
func (m *MockClientManager) GetSentMessages() []ChannelMessage {
|
||||
m.mu.RLock()
|
||||
defer m.mu.RUnlock()
|
||||
return append([]ChannelMessage{}, m.sentMessages...)
|
||||
}
|
||||
|
||||
type MockPlayerManager struct {
|
||||
players map[int32]PlayerInfo
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
func NewMockPlayerManager() *MockPlayerManager {
|
||||
return &MockPlayerManager{
|
||||
players: make(map[int32]PlayerInfo),
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MockPlayerManager) GetPlayerInfo(characterID int32) (PlayerInfo, error) {
|
||||
m.mu.RLock()
|
||||
defer m.mu.RUnlock()
|
||||
|
||||
if player, exists := m.players[characterID]; exists {
|
||||
return player, nil
|
||||
}
|
||||
return PlayerInfo{}, fmt.Errorf("player not found")
|
||||
}
|
||||
|
||||
func (m *MockPlayerManager) ValidatePlayer(characterID int32, levelReq, raceReq, classReq int32) bool {
|
||||
player, err := m.GetPlayerInfo(characterID)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if levelReq > 0 && player.Level < levelReq {
|
||||
return false
|
||||
}
|
||||
if raceReq > 0 && (raceReq&(1<<player.Race)) == 0 {
|
||||
return false
|
||||
}
|
||||
if classReq > 0 && (classReq&(1<<player.Class)) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (m *MockPlayerManager) GetPlayerLanguages(characterID int32) ([]int32, error) {
|
||||
return []int32{0, 1}, nil // Default languages
|
||||
}
|
||||
|
||||
func (m *MockPlayerManager) AddPlayer(player PlayerInfo) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
m.players[player.CharacterID] = player
|
||||
}
|
||||
|
||||
type MockLanguageProcessor struct{}
|
||||
|
||||
func (m *MockLanguageProcessor) ProcessMessage(senderID, receiverID int32, message string, languageID int32) (string, error) {
|
||||
return message, nil // No scrambling for tests
|
||||
}
|
||||
|
||||
func (m *MockLanguageProcessor) CanUnderstand(senderID, receiverID int32, languageID int32) bool {
|
||||
return true // Everyone understands everything in tests
|
||||
}
|
||||
|
||||
func (m *MockLanguageProcessor) GetDefaultLanguage(characterID int32) int32 {
|
||||
return 0 // Common tongue
|
||||
}
|
||||
|
||||
// Channel tests
|
||||
func TestNewChannel(t *testing.T) {
|
||||
channel := NewChannel("test")
|
||||
|
||||
if channel == nil {
|
||||
t.Fatal("NewChannel returned nil")
|
||||
}
|
||||
|
||||
if channel.GetName() != "test" {
|
||||
t.Errorf("Channel name = %v, want test", channel.GetName())
|
||||
}
|
||||
|
||||
if channel.GetNumClients() != 0 {
|
||||
t.Errorf("New channel should have 0 clients, got %v", channel.GetNumClients())
|
||||
}
|
||||
}
|
||||
|
||||
func TestChannelSettersAndGetters(t *testing.T) {
|
||||
channel := NewChannel("test")
|
||||
|
||||
// Test name
|
||||
channel.SetName("newname")
|
||||
if channel.GetName() != "newname" {
|
||||
t.Errorf("SetName failed: got %v, want newname", channel.GetName())
|
||||
}
|
||||
|
||||
// Test password
|
||||
channel.SetPassword("secret")
|
||||
if !channel.HasPassword() {
|
||||
t.Error("HasPassword should return true after SetPassword")
|
||||
}
|
||||
|
||||
if !channel.PasswordMatches("secret") {
|
||||
t.Error("PasswordMatches should return true for correct password")
|
||||
}
|
||||
|
||||
if channel.PasswordMatches("wrong") {
|
||||
t.Error("PasswordMatches should return false for incorrect password")
|
||||
}
|
||||
|
||||
// Test type
|
||||
channel.SetType(ChannelTypeWorld)
|
||||
if channel.GetType() != ChannelTypeWorld {
|
||||
t.Errorf("SetType failed: got %v, want %v", channel.GetType(), ChannelTypeWorld)
|
||||
}
|
||||
|
||||
// Test restrictions
|
||||
channel.SetLevelRestriction(50)
|
||||
if !channel.CanJoinChannelByLevel(50) {
|
||||
t.Error("CanJoinChannelByLevel should allow level 50")
|
||||
}
|
||||
|
||||
if channel.CanJoinChannelByLevel(49) {
|
||||
t.Error("CanJoinChannelByLevel should not allow level 49")
|
||||
}
|
||||
|
||||
// Test race restriction (bitmask)
|
||||
channel.SetRacesAllowed(1 << 1) // Only race ID 1 allowed
|
||||
if !channel.CanJoinChannelByRace(1) {
|
||||
t.Error("CanJoinChannelByRace should allow race 1")
|
||||
}
|
||||
|
||||
if channel.CanJoinChannelByRace(2) {
|
||||
t.Error("CanJoinChannelByRace should not allow race 2")
|
||||
}
|
||||
|
||||
// Test class restriction (bitmask)
|
||||
channel.SetClassesAllowed(1 << 3) // Only class ID 3 allowed
|
||||
if !channel.CanJoinChannelByClass(3) {
|
||||
t.Error("CanJoinChannelByClass should allow class 3")
|
||||
}
|
||||
|
||||
if channel.CanJoinChannelByClass(4) {
|
||||
t.Error("CanJoinChannelByClass should not allow class 4")
|
||||
}
|
||||
}
|
||||
|
||||
func TestChannelMembership(t *testing.T) {
|
||||
channel := NewChannel("test")
|
||||
|
||||
// Test initial state
|
||||
if channel.IsInChannel(100) {
|
||||
t.Error("IsInChannel should return false for new channel")
|
||||
}
|
||||
|
||||
if !channel.IsEmpty() {
|
||||
t.Error("New channel should be empty")
|
||||
}
|
||||
|
||||
// Test joining
|
||||
err := channel.JoinChannel(100)
|
||||
if err != nil {
|
||||
t.Errorf("JoinChannel failed: %v", err)
|
||||
}
|
||||
|
||||
if !channel.IsInChannel(100) {
|
||||
t.Error("IsInChannel should return true after joining")
|
||||
}
|
||||
|
||||
if channel.GetNumClients() != 1 {
|
||||
t.Errorf("GetNumClients = %v, want 1", channel.GetNumClients())
|
||||
}
|
||||
|
||||
if channel.IsEmpty() {
|
||||
t.Error("Channel should not be empty after joining")
|
||||
}
|
||||
|
||||
// Test duplicate join
|
||||
err = channel.JoinChannel(100)
|
||||
if err == nil {
|
||||
t.Error("JoinChannel should fail for duplicate member")
|
||||
}
|
||||
|
||||
// Test multiple members
|
||||
err = channel.JoinChannel(200)
|
||||
if err != nil {
|
||||
t.Errorf("JoinChannel failed for second member: %v", err)
|
||||
}
|
||||
|
||||
if channel.GetNumClients() != 2 {
|
||||
t.Errorf("GetNumClients = %v, want 2", channel.GetNumClients())
|
||||
}
|
||||
|
||||
// Test GetMembers
|
||||
members := channel.GetMembers()
|
||||
if len(members) != 2 {
|
||||
t.Errorf("GetMembers returned %v members, want 2", len(members))
|
||||
}
|
||||
|
||||
// Verify members contains both IDs
|
||||
found100, found200 := false, false
|
||||
for _, id := range members {
|
||||
if id == 100 {
|
||||
found100 = true
|
||||
}
|
||||
if id == 200 {
|
||||
found200 = true
|
||||
}
|
||||
}
|
||||
|
||||
if !found100 || !found200 {
|
||||
t.Error("GetMembers should contain both member IDs")
|
||||
}
|
||||
|
||||
// Test leaving
|
||||
err = channel.LeaveChannel(100)
|
||||
if err != nil {
|
||||
t.Errorf("LeaveChannel failed: %v", err)
|
||||
}
|
||||
|
||||
if channel.IsInChannel(100) {
|
||||
t.Error("IsInChannel should return false after leaving")
|
||||
}
|
||||
|
||||
if channel.GetNumClients() != 1 {
|
||||
t.Errorf("GetNumClients = %v, want 1 after leaving", channel.GetNumClients())
|
||||
}
|
||||
|
||||
// Test leaving non-member
|
||||
err = channel.LeaveChannel(300)
|
||||
if err == nil {
|
||||
t.Error("LeaveChannel should fail for non-member")
|
||||
}
|
||||
|
||||
// Test leaving last member
|
||||
err = channel.LeaveChannel(200)
|
||||
if err != nil {
|
||||
t.Errorf("LeaveChannel failed for last member: %v", err)
|
||||
}
|
||||
|
||||
if !channel.IsEmpty() {
|
||||
t.Error("Channel should be empty after all members leave")
|
||||
}
|
||||
}
|
||||
|
||||
func TestChannelValidateJoin(t *testing.T) {
|
||||
channel := NewChannel("test")
|
||||
channel.SetPassword("secret")
|
||||
channel.SetLevelRestriction(10)
|
||||
channel.SetRacesAllowed(1 << 1) // Race 1 only
|
||||
channel.SetClassesAllowed(1 << 2) // Class 2 only
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
level int32
|
||||
race int32
|
||||
class int32
|
||||
password string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "valid join",
|
||||
level: 15,
|
||||
race: 1,
|
||||
class: 2,
|
||||
password: "secret",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "wrong password",
|
||||
level: 15,
|
||||
race: 1,
|
||||
class: 2,
|
||||
password: "wrong",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "level too low",
|
||||
level: 5,
|
||||
race: 1,
|
||||
class: 2,
|
||||
password: "secret",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "wrong race",
|
||||
level: 15,
|
||||
race: 2,
|
||||
class: 2,
|
||||
password: "secret",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "wrong class",
|
||||
level: 15,
|
||||
race: 1,
|
||||
class: 3,
|
||||
password: "secret",
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := channel.ValidateJoin(tt.level, tt.race, tt.class, tt.password)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("ValidateJoin() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestChannelGetChannelInfo(t *testing.T) {
|
||||
channel := NewChannel("testchannel")
|
||||
channel.SetType(ChannelTypeWorld)
|
||||
channel.SetPassword("secret")
|
||||
channel.SetLevelRestriction(20)
|
||||
channel.SetRacesAllowed(15) // Multiple races
|
||||
channel.SetClassesAllowed(31) // Multiple classes
|
||||
channel.JoinChannel(100)
|
||||
channel.JoinChannel(200)
|
||||
|
||||
info := channel.GetChannelInfo()
|
||||
|
||||
if info.Name != "testchannel" {
|
||||
t.Errorf("ChannelInfo Name = %v, want testchannel", info.Name)
|
||||
}
|
||||
|
||||
if !info.HasPassword {
|
||||
t.Error("ChannelInfo should indicate has password")
|
||||
}
|
||||
|
||||
if info.MemberCount != 2 {
|
||||
t.Errorf("ChannelInfo MemberCount = %v, want 2", info.MemberCount)
|
||||
}
|
||||
|
||||
if info.LevelRestriction != 20 {
|
||||
t.Errorf("ChannelInfo LevelRestriction = %v, want 20", info.LevelRestriction)
|
||||
}
|
||||
|
||||
if info.ChannelType != ChannelTypeWorld {
|
||||
t.Errorf("ChannelInfo ChannelType = %v, want %v", info.ChannelType, ChannelTypeWorld)
|
||||
}
|
||||
}
|
||||
|
||||
func TestChannelCopy(t *testing.T) {
|
||||
original := NewChannel("original")
|
||||
original.SetPassword("secret")
|
||||
original.SetType(ChannelTypeCustom)
|
||||
original.SetLevelRestriction(25)
|
||||
original.JoinChannel(100)
|
||||
original.JoinChannel(200)
|
||||
|
||||
copy := original.Copy()
|
||||
|
||||
if copy == original {
|
||||
t.Error("Copy should return different instance")
|
||||
}
|
||||
|
||||
if copy.GetName() != original.GetName() {
|
||||
t.Error("Copy should have same name")
|
||||
}
|
||||
|
||||
if copy.GetType() != original.GetType() {
|
||||
t.Error("Copy should have same type")
|
||||
}
|
||||
|
||||
if copy.GetNumClients() != original.GetNumClients() {
|
||||
t.Error("Copy should have same member count")
|
||||
}
|
||||
|
||||
// Test that modifying copy doesn't affect original
|
||||
copy.JoinChannel(300)
|
||||
if original.GetNumClients() == copy.GetNumClients() {
|
||||
t.Error("Modifying copy should not affect original")
|
||||
}
|
||||
}
|
||||
|
||||
// Database tests
|
||||
func TestMockChannelDatabase(t *testing.T) {
|
||||
db := NewMockChannelDatabase()
|
||||
ctx := context.Background()
|
||||
|
||||
// Test empty database
|
||||
channels, err := db.LoadWorldChannels(ctx)
|
||||
if err != nil {
|
||||
t.Errorf("LoadWorldChannels failed: %v", err)
|
||||
}
|
||||
|
||||
if len(channels) != 0 {
|
||||
t.Errorf("Expected 0 channels, got %v", len(channels))
|
||||
}
|
||||
|
||||
// Test saving channel
|
||||
testChannel := ChatChannelData{
|
||||
Name: "testchannel",
|
||||
Password: "secret",
|
||||
LevelRestriction: 10,
|
||||
ClassRestriction: 15,
|
||||
RaceRestriction: 7,
|
||||
}
|
||||
|
||||
err = db.SaveChannel(ctx, testChannel)
|
||||
if err != nil {
|
||||
t.Errorf("SaveChannel failed: %v", err)
|
||||
}
|
||||
|
||||
// Test loading after save
|
||||
channels, err = db.LoadWorldChannels(ctx)
|
||||
if err != nil {
|
||||
t.Errorf("LoadWorldChannels failed: %v", err)
|
||||
}
|
||||
|
||||
if len(channels) != 1 {
|
||||
t.Errorf("Expected 1 channel, got %v", len(channels))
|
||||
}
|
||||
|
||||
if channels[0].Name != testChannel.Name {
|
||||
t.Errorf("Channel name = %v, want %v", channels[0].Name, testChannel.Name)
|
||||
}
|
||||
|
||||
// Test delete
|
||||
err = db.DeleteChannel(ctx, "testchannel")
|
||||
if err != nil {
|
||||
t.Errorf("DeleteChannel failed: %v", err)
|
||||
}
|
||||
|
||||
// Test delete non-existent
|
||||
err = db.DeleteChannel(ctx, "nonexistent")
|
||||
if err == nil {
|
||||
t.Error("DeleteChannel should fail for non-existent channel")
|
||||
}
|
||||
|
||||
// Test error conditions
|
||||
db.SetLoadError(fmt.Errorf("load error"))
|
||||
_, err = db.LoadWorldChannels(ctx)
|
||||
if err == nil {
|
||||
t.Error("LoadWorldChannels should return error when set")
|
||||
}
|
||||
|
||||
db.SetSaveError(fmt.Errorf("save error"))
|
||||
err = db.SaveChannel(ctx, testChannel)
|
||||
if err == nil {
|
||||
t.Error("SaveChannel should return error when set")
|
||||
}
|
||||
|
||||
db.SetDeleteError(fmt.Errorf("delete error"))
|
||||
err = db.DeleteChannel(ctx, "test")
|
||||
if err == nil {
|
||||
t.Error("DeleteChannel should return error when set")
|
||||
}
|
||||
}
|
||||
|
||||
// Interface tests
|
||||
func TestEntityChatAdapter(t *testing.T) {
|
||||
playerManager := NewMockPlayerManager()
|
||||
playerManager.AddPlayer(PlayerInfo{
|
||||
CharacterID: 100,
|
||||
CharacterName: "TestPlayer",
|
||||
Level: 25,
|
||||
Race: 1,
|
||||
Class: 2,
|
||||
IsOnline: true,
|
||||
})
|
||||
|
||||
entityWithGetID := &EntityWithGetID{id: 100}
|
||||
|
||||
adapter := &EntityChatAdapter{
|
||||
entity: entityWithGetID,
|
||||
playerManager: playerManager,
|
||||
}
|
||||
|
||||
if adapter.GetCharacterID() != 100 {
|
||||
t.Errorf("GetCharacterID() = %v, want 100", adapter.GetCharacterID())
|
||||
}
|
||||
|
||||
if adapter.GetCharacterName() != "TestPlayer" {
|
||||
t.Errorf("GetCharacterName() = %v, want TestPlayer", adapter.GetCharacterName())
|
||||
}
|
||||
|
||||
if adapter.GetLevel() != 25 {
|
||||
t.Errorf("GetLevel() = %v, want 25", adapter.GetLevel())
|
||||
}
|
||||
|
||||
if adapter.GetRace() != 1 {
|
||||
t.Errorf("GetRace() = %v, want 1", adapter.GetRace())
|
||||
}
|
||||
|
||||
if adapter.GetClass() != 2 {
|
||||
t.Errorf("GetClass() = %v, want 2", adapter.GetClass())
|
||||
}
|
||||
|
||||
// Test with non-existent player
|
||||
entityWithGetID2 := &EntityWithGetID{id: 999}
|
||||
|
||||
adapter2 := &EntityChatAdapter{
|
||||
entity: entityWithGetID2,
|
||||
playerManager: playerManager,
|
||||
}
|
||||
|
||||
if adapter2.GetCharacterName() != "" {
|
||||
t.Error("GetCharacterName should return empty string for non-existent player")
|
||||
}
|
||||
|
||||
if adapter2.GetLevel() != 0 {
|
||||
t.Error("GetLevel should return 0 for non-existent player")
|
||||
}
|
||||
}
|
||||
|
||||
// Constants tests
|
||||
func TestConstants(t *testing.T) {
|
||||
// Test channel types
|
||||
if ChannelTypeNone != 0 {
|
||||
t.Errorf("ChannelTypeNone = %v, want 0", ChannelTypeNone)
|
||||
}
|
||||
|
||||
if ChannelTypeWorld != 1 {
|
||||
t.Errorf("ChannelTypeWorld = %v, want 1", ChannelTypeWorld)
|
||||
}
|
||||
|
||||
if ChannelTypeCustom != 2 {
|
||||
t.Errorf("ChannelTypeCustom = %v, want 2", ChannelTypeCustom)
|
||||
}
|
||||
|
||||
// Test chat actions
|
||||
if ChatChannelJoin != 0 {
|
||||
t.Errorf("ChatChannelJoin = %v, want 0", ChatChannelJoin)
|
||||
}
|
||||
|
||||
if ChatChannelLeave != 1 {
|
||||
t.Errorf("ChatChannelLeave = %v, want 1", ChatChannelLeave)
|
||||
}
|
||||
|
||||
// Test restrictions
|
||||
if NoLevelRestriction != 0 {
|
||||
t.Errorf("NoLevelRestriction = %v, want 0", NoLevelRestriction)
|
||||
}
|
||||
|
||||
if NoRaceRestriction != 0 {
|
||||
t.Errorf("NoRaceRestriction = %v, want 0", NoRaceRestriction)
|
||||
}
|
||||
|
||||
if NoClassRestriction != 0 {
|
||||
t.Errorf("NoClassRestriction = %v, want 0", NoClassRestriction)
|
||||
}
|
||||
}
|
||||
|
||||
// Concurrency tests
|
||||
func TestChannelConcurrency(t *testing.T) {
|
||||
channel := NewChannel("concurrent")
|
||||
var wg sync.WaitGroup
|
||||
|
||||
// Concurrent joins
|
||||
for i := range 100 {
|
||||
wg.Add(1)
|
||||
go func(id int32) {
|
||||
defer wg.Done()
|
||||
channel.JoinChannel(id)
|
||||
}(int32(i))
|
||||
}
|
||||
|
||||
// Concurrent reads
|
||||
for i := range 50 {
|
||||
wg.Add(1)
|
||||
go func(id int32) {
|
||||
defer wg.Done()
|
||||
channel.IsInChannel(id)
|
||||
channel.GetMembers()
|
||||
channel.GetChannelInfo()
|
||||
}(int32(i))
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
// Verify final state
|
||||
if channel.GetNumClients() != 100 {
|
||||
t.Errorf("After concurrent joins, got %v members, want 100", channel.GetNumClients())
|
||||
}
|
||||
|
||||
// Concurrent leaves
|
||||
for i := range 50 {
|
||||
wg.Add(1)
|
||||
go func(id int32) {
|
||||
defer wg.Done()
|
||||
channel.LeaveChannel(id)
|
||||
}(int32(i))
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
if channel.GetNumClients() != 50 {
|
||||
t.Errorf("After concurrent leaves, got %v members, want 50", channel.GetNumClients())
|
||||
}
|
||||
}
|
||||
|
||||
func TestMockClientManager(t *testing.T) {
|
||||
client := NewMockClientManager()
|
||||
|
||||
// Test client connection status
|
||||
if client.IsClientConnected(100) {
|
||||
t.Error("IsClientConnected should return false initially")
|
||||
}
|
||||
|
||||
client.SetClientConnected(100, true)
|
||||
if !client.IsClientConnected(100) {
|
||||
t.Error("IsClientConnected should return true after setting")
|
||||
}
|
||||
|
||||
// Test channel list
|
||||
channels := []ChannelInfo{
|
||||
{Name: "test1", MemberCount: 5},
|
||||
{Name: "test2", MemberCount: 10},
|
||||
}
|
||||
|
||||
err := client.SendChannelList(100, channels)
|
||||
if err != nil {
|
||||
t.Errorf("SendChannelList failed: %v", err)
|
||||
}
|
||||
|
||||
// Test channel message
|
||||
message := ChannelMessage{
|
||||
SenderID: 200,
|
||||
SenderName: "TestSender",
|
||||
Message: "Hello world",
|
||||
ChannelName: "test",
|
||||
Timestamp: time.Now(),
|
||||
}
|
||||
|
||||
err = client.SendChannelMessage(100, message)
|
||||
if err != nil {
|
||||
t.Errorf("SendChannelMessage failed: %v", err)
|
||||
}
|
||||
|
||||
sentMessages := client.GetSentMessages()
|
||||
if len(sentMessages) != 1 {
|
||||
t.Errorf("Expected 1 sent message, got %v", len(sentMessages))
|
||||
}
|
||||
|
||||
if sentMessages[0].Message != "Hello world" {
|
||||
t.Errorf("Sent message = %v, want Hello world", sentMessages[0].Message)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMockPlayerManager(t *testing.T) {
|
||||
playerMgr := NewMockPlayerManager()
|
||||
|
||||
// Test non-existent player
|
||||
_, err := playerMgr.GetPlayerInfo(999)
|
||||
if err == nil {
|
||||
t.Error("GetPlayerInfo should fail for non-existent player")
|
||||
}
|
||||
|
||||
// Add player
|
||||
player := PlayerInfo{
|
||||
CharacterID: 100,
|
||||
CharacterName: "TestPlayer",
|
||||
Level: 30,
|
||||
Race: 2,
|
||||
Class: 4,
|
||||
IsOnline: true,
|
||||
}
|
||||
|
||||
playerMgr.AddPlayer(player)
|
||||
|
||||
// Test existing player
|
||||
retrieved, err := playerMgr.GetPlayerInfo(100)
|
||||
if err != nil {
|
||||
t.Errorf("GetPlayerInfo failed: %v", err)
|
||||
}
|
||||
|
||||
if retrieved.CharacterName != "TestPlayer" {
|
||||
t.Errorf("Player name = %v, want TestPlayer", retrieved.CharacterName)
|
||||
}
|
||||
|
||||
// Test validation
|
||||
if !playerMgr.ValidatePlayer(100, 25, 0, 0) {
|
||||
t.Error("ValidatePlayer should pass for level requirement")
|
||||
}
|
||||
|
||||
if playerMgr.ValidatePlayer(100, 35, 0, 0) {
|
||||
t.Error("ValidatePlayer should fail for level requirement")
|
||||
}
|
||||
|
||||
// Test languages
|
||||
languages, err := playerMgr.GetPlayerLanguages(100)
|
||||
if err != nil {
|
||||
t.Errorf("GetPlayerLanguages failed: %v", err)
|
||||
}
|
||||
|
||||
if len(languages) == 0 {
|
||||
t.Error("GetPlayerLanguages should return some languages")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMockLanguageProcessor(t *testing.T) {
|
||||
processor := &MockLanguageProcessor{}
|
||||
|
||||
// Test message processing
|
||||
processed, err := processor.ProcessMessage(100, 200, "test message", 0)
|
||||
if err != nil {
|
||||
t.Errorf("ProcessMessage failed: %v", err)
|
||||
}
|
||||
|
||||
if processed != "test message" {
|
||||
t.Errorf("ProcessMessage = %v, want test message", processed)
|
||||
}
|
||||
|
||||
// Test understanding
|
||||
if !processor.CanUnderstand(100, 200, 0) {
|
||||
t.Error("CanUnderstand should return true in mock")
|
||||
}
|
||||
|
||||
// Test default language
|
||||
if processor.GetDefaultLanguage(100) != 0 {
|
||||
t.Error("GetDefaultLanguage should return 0 in mock")
|
||||
}
|
||||
}
|
||||
|
||||
// Benchmarks
|
||||
func BenchmarkChannelJoin(b *testing.B) {
|
||||
channel := NewChannel("benchmark")
|
||||
|
||||
for i := 0; b.Loop(); i++ {
|
||||
channel.JoinChannel(int32(i))
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkChannelIsInChannel(b *testing.B) {
|
||||
channel := NewChannel("benchmark")
|
||||
|
||||
for i := range 1000 {
|
||||
channel.JoinChannel(int32(i))
|
||||
}
|
||||
|
||||
for i := 0; b.Loop(); i++ {
|
||||
channel.IsInChannel(int32(i % 1000))
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkChannelGetMembers(b *testing.B) {
|
||||
channel := NewChannel("benchmark")
|
||||
|
||||
for i := range 1000 {
|
||||
channel.JoinChannel(int32(i))
|
||||
}
|
||||
|
||||
for b.Loop() {
|
||||
channel.GetMembers()
|
||||
}
|
||||
}
|
@ -7,12 +7,12 @@ import (
|
||||
"eq2emu/internal/database"
|
||||
)
|
||||
|
||||
// DatabaseChannelManager implements ChannelDatabase interface using the existing database wrapper
|
||||
// DatabaseChannelManager implements ChannelDatabase interface using the correct database wrapper
|
||||
type DatabaseChannelManager struct {
|
||||
db *database.DB
|
||||
}
|
||||
|
||||
// NewDatabaseChannelManager creates a new database channel manager
|
||||
// NewDatabaseChannelManager creates a new database channel manager using the correct wrapper
|
||||
func NewDatabaseChannelManager(db *database.DB) *DatabaseChannelManager {
|
||||
return &DatabaseChannelManager{
|
||||
db: db,
|
||||
@ -23,38 +23,25 @@ func NewDatabaseChannelManager(db *database.DB) *DatabaseChannelManager {
|
||||
func (dcm *DatabaseChannelManager) LoadWorldChannels(ctx context.Context) ([]ChatChannelData, error) {
|
||||
query := "SELECT `name`, `password`, `level_restriction`, `classes`, `races` FROM `channels`"
|
||||
|
||||
rows, err := dcm.db.QueryContext(ctx, query)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to query channels: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var channels []ChatChannelData
|
||||
for rows.Next() {
|
||||
|
||||
err := dcm.db.Query(query, func(row *database.Row) error {
|
||||
var channel ChatChannelData
|
||||
var password *string
|
||||
|
||||
err := rows.Scan(
|
||||
&channel.Name,
|
||||
&password,
|
||||
&channel.LevelRestriction,
|
||||
&channel.ClassRestriction,
|
||||
&channel.RaceRestriction,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to scan channel row: %w", err)
|
||||
}
|
||||
|
||||
// Handle nullable password field
|
||||
if password != nil {
|
||||
channel.Password = *password
|
||||
channel.Name = row.Text(0)
|
||||
if !row.IsNull(1) {
|
||||
channel.Password = row.Text(1)
|
||||
}
|
||||
channel.LevelRestriction = int32(row.Int64(2))
|
||||
channel.ClassRestriction = int32(row.Int64(3))
|
||||
channel.RaceRestriction = int32(row.Int64(4))
|
||||
|
||||
channels = append(channels, channel)
|
||||
}
|
||||
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, fmt.Errorf("error iterating channel rows: %w", err)
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to query channels: %w", err)
|
||||
}
|
||||
|
||||
return channels, nil
|
||||
@ -73,7 +60,7 @@ func (dcm *DatabaseChannelManager) SaveChannel(ctx context.Context, channel Chat
|
||||
password = &channel.Password
|
||||
}
|
||||
|
||||
_, err := dcm.db.ExecContext(ctx, query,
|
||||
err := dcm.db.Exec(query,
|
||||
channel.Name,
|
||||
password,
|
||||
channel.LevelRestriction,
|
||||
@ -91,20 +78,11 @@ func (dcm *DatabaseChannelManager) SaveChannel(ctx context.Context, channel Chat
|
||||
func (dcm *DatabaseChannelManager) DeleteChannel(ctx context.Context, channelName string) error {
|
||||
query := "DELETE FROM channels WHERE name = ?"
|
||||
|
||||
result, err := dcm.db.ExecContext(ctx, query, channelName)
|
||||
err := dcm.db.Exec(query, channelName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete channel %s: %w", channelName, err)
|
||||
}
|
||||
|
||||
rowsAffected, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to check rows affected for channel %s: %w", channelName, err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return fmt.Errorf("channel %s not found in database", channelName)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -121,7 +99,7 @@ func (dcm *DatabaseChannelManager) EnsureChannelsTable(ctx context.Context) erro
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
)`
|
||||
|
||||
_, err := dcm.db.ExecContext(ctx, query)
|
||||
err := dcm.db.Exec(query)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create channels table: %w", err)
|
||||
}
|
||||
@ -133,11 +111,16 @@ func (dcm *DatabaseChannelManager) EnsureChannelsTable(ctx context.Context) erro
|
||||
func (dcm *DatabaseChannelManager) GetChannelCount(ctx context.Context) (int, error) {
|
||||
query := "SELECT COUNT(*) FROM channels"
|
||||
|
||||
var count int
|
||||
err := dcm.db.QueryRowContext(ctx, query).Scan(&count)
|
||||
row, err := dcm.db.QueryRow(query)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("failed to get channel count: %w", err)
|
||||
return 0, fmt.Errorf("failed to query channel count: %w", err)
|
||||
}
|
||||
if row == nil {
|
||||
return 0, nil
|
||||
}
|
||||
defer row.Close()
|
||||
|
||||
count := row.Int(0)
|
||||
|
||||
return count, nil
|
||||
}
|
||||
@ -146,24 +129,24 @@ func (dcm *DatabaseChannelManager) GetChannelCount(ctx context.Context) (int, er
|
||||
func (dcm *DatabaseChannelManager) GetChannelByName(ctx context.Context, channelName string) (*ChatChannelData, error) {
|
||||
query := "SELECT `name`, `password`, `level_restriction`, `classes`, `races` FROM `channels` WHERE `name` = ?"
|
||||
|
||||
var channel ChatChannelData
|
||||
var password *string
|
||||
|
||||
err := dcm.db.QueryRowContext(ctx, query, channelName).Scan(
|
||||
&channel.Name,
|
||||
&password,
|
||||
&channel.LevelRestriction,
|
||||
&channel.ClassRestriction,
|
||||
&channel.RaceRestriction,
|
||||
)
|
||||
row, err := dcm.db.QueryRow(query, channelName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get channel %s: %w", channelName, err)
|
||||
return nil, fmt.Errorf("failed to query channel %s: %w", channelName, err)
|
||||
}
|
||||
if row == nil {
|
||||
return nil, fmt.Errorf("channel %s not found", channelName)
|
||||
}
|
||||
defer row.Close()
|
||||
|
||||
// Handle nullable password field
|
||||
if password != nil {
|
||||
channel.Password = *password
|
||||
var channel ChatChannelData
|
||||
|
||||
channel.Name = row.Text(0)
|
||||
if !row.IsNull(1) {
|
||||
channel.Password = row.Text(1)
|
||||
}
|
||||
channel.LevelRestriction = int32(row.Int64(2))
|
||||
channel.ClassRestriction = int32(row.Int64(3))
|
||||
channel.RaceRestriction = int32(row.Int64(4))
|
||||
|
||||
return &channel, nil
|
||||
}
|
||||
@ -172,24 +155,17 @@ func (dcm *DatabaseChannelManager) GetChannelByName(ctx context.Context, channel
|
||||
func (dcm *DatabaseChannelManager) ListChannelNames(ctx context.Context) ([]string, error) {
|
||||
query := "SELECT name FROM channels ORDER BY name"
|
||||
|
||||
rows, err := dcm.db.QueryContext(ctx, query)
|
||||
var names []string
|
||||
|
||||
err := dcm.db.Query(query, func(row *database.Row) error {
|
||||
name := row.Text(0)
|
||||
names = append(names, name)
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to query channel names: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var names []string
|
||||
for rows.Next() {
|
||||
var name string
|
||||
if err := rows.Scan(&name); err != nil {
|
||||
return nil, fmt.Errorf("failed to scan channel name: %w", err)
|
||||
}
|
||||
names = append(names, name)
|
||||
}
|
||||
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, fmt.Errorf("error iterating channel name rows: %w", err)
|
||||
}
|
||||
|
||||
return names, nil
|
||||
}
|
||||
@ -203,20 +179,11 @@ func (dcm *DatabaseChannelManager) UpdateChannelPassword(ctx context.Context, ch
|
||||
passwordParam = &password
|
||||
}
|
||||
|
||||
result, err := dcm.db.ExecContext(ctx, query, passwordParam, channelName)
|
||||
err := dcm.db.Exec(query, passwordParam, channelName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to update password for channel %s: %w", channelName, err)
|
||||
}
|
||||
|
||||
rowsAffected, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to check rows affected for channel %s: %w", channelName, err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return fmt.Errorf("channel %s not found in database", channelName)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -224,19 +191,10 @@ func (dcm *DatabaseChannelManager) UpdateChannelPassword(ctx context.Context, ch
|
||||
func (dcm *DatabaseChannelManager) UpdateChannelRestrictions(ctx context.Context, channelName string, levelRestriction, classRestriction, raceRestriction int32) error {
|
||||
query := "UPDATE channels SET level_restriction = ?, classes = ?, races = ?, updated_at = CURRENT_TIMESTAMP WHERE name = ?"
|
||||
|
||||
result, err := dcm.db.ExecContext(ctx, query, levelRestriction, classRestriction, raceRestriction, channelName)
|
||||
err := dcm.db.Exec(query, levelRestriction, classRestriction, raceRestriction, channelName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to update restrictions for channel %s: %w", channelName, err)
|
||||
}
|
||||
|
||||
rowsAffected, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to check rows affected for channel %s: %w", channelName, err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return fmt.Errorf("channel %s not found in database", channelName)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user