import { describe, it, expect } from 'vitest'; import { matchPattern, matchRules, parseCommand, generateAskPattern } from '../../../src/permission/wildcard.js'; describe('matchPattern - 通配符模式匹配', () => { describe('* 通配符', () => { it('匹配任意字符', () => { expect(matchPattern('git diff', 'git diff*')).toBe(true); expect(matchPattern('git diff --staged', 'git diff*')).toBe(true); expect(matchPattern('git diff HEAD~1', 'git diff*')).toBe(true); }); it('不匹配不同前缀', () => { expect(matchPattern('git status', 'git diff*')).toBe(false); expect(matchPattern('git pull', 'git diff*')).toBe(false); }); it('匹配危险命令模式 rm -rf*', () => { expect(matchPattern('rm -rf /', 'rm -rf*')).toBe(true); expect(matchPattern('rm -rf /home', 'rm -rf*')).toBe(true); expect(matchPattern('rm -rf .', 'rm -rf*')).toBe(true); }); it('rm 普通命令不匹配 rm -rf*', () => { expect(matchPattern('rm file.txt', 'rm -rf*')).toBe(false); expect(matchPattern('rm -r dir', 'rm -rf*')).toBe(false); }); it('中间位置的通配符', () => { expect(matchPattern('git push origin main', 'git push * main')).toBe(true); expect(matchPattern('git push upstream main', 'git push * main')).toBe(true); }); it('多个通配符', () => { expect(matchPattern('git push origin main', 'git * origin *')).toBe(true); expect(matchPattern('git pull origin main', 'git * origin *')).toBe(true); }); }); describe('? 通配符', () => { it('匹配单个字符', () => { expect(matchPattern('ls -a', 'ls -?')).toBe(true); expect(matchPattern('ls -l', 'ls -?')).toBe(true); }); it('不匹配多个字符', () => { expect(matchPattern('ls -la', 'ls -?')).toBe(false); }); }); describe('精确匹配', () => { it('完全相同的字符串', () => { expect(matchPattern('ls', 'ls')).toBe(true); expect(matchPattern('pwd', 'pwd')).toBe(true); }); it('不匹配带参数的命令', () => { expect(matchPattern('ls -la', 'ls')).toBe(false); expect(matchPattern('pwd /home', 'pwd')).toBe(false); }); }); describe('大小写不敏感', () => { it('匹配不同大小写', () => { expect(matchPattern('GIT DIFF', 'git diff*')).toBe(true); expect(matchPattern('Git Diff', 'git diff*')).toBe(true); }); }); describe('特殊字符转义', () => { it('正确处理点号', () => { expect(matchPattern('file.txt', 'file.txt')).toBe(true); expect(matchPattern('fileatxt', 'file.txt')).toBe(false); }); it('正确处理括号', () => { expect(matchPattern('echo (test)', 'echo (test)')).toBe(true); }); }); }); describe('matchRules - 规则匹配', () => { const rules = [ { pattern: 'ls *', action: 'allow' as const }, { pattern: 'rm -rf*', action: 'deny' as const }, { pattern: 'git *', action: 'ask' as const }, ]; it('匹配 allow 规则', () => { const result = matchRules('ls -la', rules, 'ask'); expect(result.action).toBe('allow'); }); it('匹配 deny 规则', () => { const result = matchRules('rm -rf /', rules, 'ask'); expect(result.action).toBe('deny'); }); it('匹配 ask 规则', () => { const result = matchRules('git push', rules, 'deny'); expect(result.action).toBe('ask'); }); it('无匹配时返回默认动作', () => { const result = matchRules('npm install', rules, 'ask'); expect(result.action).toBe('ask'); }); it('返回匹配的模式', () => { const result = matchRules('rm -rf /home', rules, 'ask'); expect(result.matchedPattern).toBe('rm -rf*'); }); it('空规则列表返回默认动作', () => { const result = matchRules('any command', [], 'allow'); expect(result.action).toBe('allow'); }); }); describe('parseCommand - 命令解析', () => { it('解析简单命令', () => { const result = parseCommand('ls'); expect(result.head).toBe('ls'); expect(result.sub).toBeUndefined(); }); it('解析带子命令的命令', () => { const result = parseCommand('git push'); expect(result.head).toBe('git'); expect(result.sub).toBe('push'); }); it('解析带参数的命令', () => { const result = parseCommand('git push origin main'); expect(result.head).toBe('git'); expect(result.sub).toBe('push'); expect(result.args).toContain('origin'); expect(result.args).toContain('main'); }); }); describe('generateAskPattern - 生成询问模式', () => { it('简单命令生成 cmd *', () => { const pattern = generateAskPattern('ls -la'); expect(pattern).toBe('ls *'); }); it('带子命令生成 cmd sub *', () => { const pattern = generateAskPattern('git push origin'); expect(pattern).toBe('git push *'); }); it('npm install 生成 npm install *', () => { const pattern = generateAskPattern('npm install lodash'); expect(pattern).toBe('npm install *'); }); });