Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package com.bentahsin.antiafk.behavior;

import com.bentahsin.antiafk.AntiAFKPlugin;
import com.bentahsin.antiafk.api.enums.DetectionType;
import com.bentahsin.antiafk.managers.AFKManager;
import com.bentahsin.antiafk.managers.BotDetectionManager;
import com.bentahsin.antiafk.managers.ConfigManager;
import com.bentahsin.antiafk.managers.DebugManager;
import com.bentahsin.antiafk.managers.PlayerStateManager;
import com.google.inject.Provider;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.MockitoAnnotations;

import java.util.Collections;

import static org.mockito.Mockito.*;

class BehaviorAnalysisLogicTest {

private BehaviorAnalysisTask task;
private MockedStatic<Bukkit> bukkitMock;

@Mock private AntiAFKPlugin plugin;
@Mock private Provider<BehaviorAnalysisManager> behaviorManagerProvider;
@Mock private BehaviorAnalysisManager behaviorManager;
@Mock private ConfigManager configManager;
@Mock private DebugManager debugManager;
@Mock private Provider<AFKManager> afkManagerProvider;
@Mock private AFKManager afkManager;
@Mock private BotDetectionManager botDetectionManager;
@Mock private PlayerStateManager stateManager;
@Mock private Player player;
@Mock private PlayerBehaviorData playerData;
@Mock private org.bukkit.configuration.file.FileConfiguration mockConfig;
@Mock private org.bukkit.scheduler.BukkitScheduler mockScheduler;

@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);

when(plugin.getConfig()).thenReturn(mockConfig);

when(mockConfig.getInt(anyString(), anyInt())).thenAnswer(i -> i.getArgument(1));
when(mockConfig.getDouble(anyString(), anyDouble())).thenAnswer(i -> i.getArgument(1));
when(mockConfig.getBoolean(anyString(), anyBoolean())).thenAnswer(i -> i.getArgument(1));

bukkitMock = mockStatic(Bukkit.class);
bukkitMock.when(Bukkit::getOnlinePlayers).thenReturn(Collections.singletonList(player));

bukkitMock.when(Bukkit::getScheduler).thenReturn(mockScheduler);

when(mockScheduler.runTask(eq(plugin), any(Runnable.class))).thenAnswer(invocation -> {
Runnable runnable = invocation.getArgument(1);
runnable.run();
return null;
});

when(behaviorManagerProvider.get()).thenReturn(behaviorManager);
when(afkManagerProvider.get()).thenReturn(afkManager);
when(afkManager.getBotDetectionManager()).thenReturn(botDetectionManager);
when(afkManager.getStateManager()).thenReturn(stateManager);

when(behaviorManager.getPlayerData(player)).thenReturn(playerData);
when(player.isOnline()).thenReturn(true);
when(stateManager.isEffectivelyAfk(player)).thenReturn(false);

task = new BehaviorAnalysisTask(plugin, behaviorManagerProvider, configManager, debugManager, afkManagerProvider);
}

@AfterEach
void tearDown() {
bukkitMock.close();
}

@Test
@DisplayName("Hapsedilme TESPİTİ: Süre + Mesafe aşılırsa challenge tetiklenmeli ve veri sıfırlanmalı")
void testConfinementViolation() {
when(configManager.isConfinementCheckEnabled()).thenReturn(true);
when(configManager.getConfinementCheckDurationMillis()).thenReturn(1200000L); // 20m
when(configManager.getConfinementMinDistance()).thenReturn(100.0);

when(playerData.getConfinementDuration()).thenReturn(1300000L);
when(playerData.getTotalDistanceTraveled()).thenReturn(500.0);

task.run();
verify(botDetectionManager, times(1)).triggerSuspicionAndChallenge(
eq(player),
eq("behavior.afk_pool_detected"),
eq(DetectionType.POINTLESS_ACTIVITY)
);
verify(playerData, times(1)).reset();
}

@Test
@DisplayName("Fresh Tracking: Süre dolsa bile mesafe düşükse ceza verme ama veriyi sıfırla")
void testConfinementFreshTracking() {
when(configManager.isConfinementCheckEnabled()).thenReturn(true);
when(configManager.getConfinementCheckDurationMillis()).thenReturn(1200000L);
when(configManager.getConfinementMinDistance()).thenReturn(100.0);

when(playerData.getConfinementDuration()).thenReturn(1300000L);
when(playerData.getTotalDistanceTraveled()).thenReturn(5.0);

task.run();
verify(botDetectionManager, never()).triggerSuspicionAndChallenge(any(), any(), any());
verify(playerData, times(1)).reset();
}

@Test
@DisplayName("Bypass Kontrolü: Oyuncu zaten AFK ise analiz atlanmalı")
void testSkipIfAlreadyAfk() {
when(stateManager.isEffectivelyAfk(player)).thenReturn(true);

task.run();

verify(playerData, never()).getConfinementDuration();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.bentahsin.antiafk.behavior;

import org.bukkit.Location;
import org.bukkit.World;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;

class PlayerBehaviorDataTest {

private PlayerBehaviorData behaviorData;
@Mock private World world;
@Mock private Location baseLoc;
@Mock private Location moveLoc;

@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
behaviorData = new PlayerBehaviorData();
when(baseLoc.getWorld()).thenReturn(world);
when(moveLoc.getWorld()).thenReturn(world);
}

@Test
@DisplayName("Mesafe Birikimi: Dar alanda hareket mesafe toplamalı")
void testDistanceAccumulation() {
behaviorData.processMovement(baseLoc, 5.0);

when(moveLoc.distance(any())).thenReturn(2.0);
when(moveLoc.distanceSquared(any())).thenReturn(4.0);

behaviorData.processMovement(moveLoc, 5.0);
assertEquals(2.0, behaviorData.getTotalDistanceTraveled(), 0.001);
}

@Test
@DisplayName("Radius İhlali: Alan dışına çıkınca her şey sıfırlanmalı")
void testResetOnRadiusExit() {
behaviorData.processMovement(baseLoc, 5.0);
when(moveLoc.distance(baseLoc)).thenReturn(10.0);
when(moveLoc.distanceSquared(baseLoc)).thenReturn(100.0);

behaviorData.processMovement(moveLoc, 5.0);

assertEquals(0.0, behaviorData.getTotalDistanceTraveled(), 0.001, "Alan dışına çıkınca mesafe SIFIRLANMALI.");
assertTrue(behaviorData.getConfinementDuration() >= 0, "Takip süresi sıfırlanmış ve yeniden başlamış olmalı.");
}

@Test
@DisplayName("Tam Sıfırlama: Reset metodu tüm alanları temizlemeli")
void testFullReset() {
behaviorData.processMovement(baseLoc, 5.0);
behaviorData.setConsecutiveRepeatCount(5);

behaviorData.reset();

assertEquals(0.0, behaviorData.getTotalDistanceTraveled());
assertEquals(0, behaviorData.getConsecutiveRepeatCount());
assertEquals(0, behaviorData.getConfinementDuration());
}
}