gitea源码

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. import {readFile} from 'node:fs/promises';
  2. import * as path from 'node:path';
  3. import {globCompile} from './glob.ts';
  4. async function loadGlobTestData(): Promise<{caseNames: string[], caseDataMap: Record<string, string>}> {
  5. const fileContent = await readFile(path.join(import.meta.dirname, 'glob.test.txt'), 'utf8');
  6. const fileLines = fileContent.split('\n');
  7. const caseDataMap: Record<string, string> = {};
  8. const caseNameMap: Record<string, boolean> = {};
  9. for (let line of fileLines) {
  10. line = line.trim();
  11. if (!line || line.startsWith('#')) continue;
  12. const parts = line.split('=', 2);
  13. if (parts.length !== 2) throw new Error(`Invalid test case line: ${line}`);
  14. const key = parts[0].trim();
  15. let value = parts[1].trim();
  16. value = value.substring(1, value.length - 1); // remove quotes
  17. value = value.replace(/\\\//g, '/').replace(/\\\\/g, '\\');
  18. caseDataMap[key] = value;
  19. if (key.startsWith('pattern_')) caseNameMap[key.substring('pattern_'.length)] = true;
  20. }
  21. return {caseNames: Object.keys(caseNameMap), caseDataMap};
  22. }
  23. function loadGlobGolangCases() {
  24. // https://github.com/gobwas/glob/blob/master/glob_test.go
  25. function glob(matched: boolean, pattern: string, input: string, separators: string = '') {
  26. return {matched, pattern, input, separators};
  27. }
  28. return [
  29. glob(true, '* ?at * eyes', 'my cat has very bright eyes'),
  30. glob(true, '', ''),
  31. glob(false, '', 'b'),
  32. glob(true, '*ä', 'åä'),
  33. glob(true, 'abc', 'abc'),
  34. glob(true, 'a*c', 'abc'),
  35. glob(true, 'a*c', 'a12345c'),
  36. glob(true, 'a?c', 'a1c'),
  37. glob(true, 'a.b', 'a.b', '.'),
  38. glob(true, 'a.*', 'a.b', '.'),
  39. glob(true, 'a.**', 'a.b.c', '.'),
  40. glob(true, 'a.?.c', 'a.b.c', '.'),
  41. glob(true, 'a.?.?', 'a.b.c', '.'),
  42. glob(true, '?at', 'cat'),
  43. glob(true, '?at', 'fat'),
  44. glob(true, '*', 'abc'),
  45. glob(true, `\\*`, '*'),
  46. glob(true, '**', 'a.b.c', '.'),
  47. glob(false, '?at', 'at'),
  48. glob(false, '?at', 'fat', 'f'),
  49. glob(false, 'a.*', 'a.b.c', '.'),
  50. glob(false, 'a.?.c', 'a.bb.c', '.'),
  51. glob(false, '*', 'a.b.c', '.'),
  52. glob(true, '*test', 'this is a test'),
  53. glob(true, 'this*', 'this is a test'),
  54. glob(true, '*is *', 'this is a test'),
  55. glob(true, '*is*a*', 'this is a test'),
  56. glob(true, '**test**', 'this is a test'),
  57. glob(true, '**is**a***test*', 'this is a test'),
  58. glob(false, '*is', 'this is a test'),
  59. glob(false, '*no*', 'this is a test'),
  60. glob(true, '[!a]*', 'this is a test3'),
  61. glob(true, '*abc', 'abcabc'),
  62. glob(true, '**abc', 'abcabc'),
  63. glob(true, '???', 'abc'),
  64. glob(true, '?*?', 'abc'),
  65. glob(true, '?*?', 'ac'),
  66. glob(false, 'sta', 'stagnation'),
  67. glob(true, 'sta*', 'stagnation'),
  68. glob(false, 'sta?', 'stagnation'),
  69. glob(false, 'sta?n', 'stagnation'),
  70. glob(true, '{abc,def}ghi', 'defghi'),
  71. glob(true, '{abc,abcd}a', 'abcda'),
  72. glob(true, '{a,ab}{bc,f}', 'abc'),
  73. glob(true, '{*,**}{a,b}', 'ab'),
  74. glob(false, '{*,**}{a,b}', 'ac'),
  75. glob(true, '/{rate,[a-z][a-z][a-z]}*', '/rate'),
  76. glob(true, '/{rate,[0-9][0-9][0-9]}*', '/rate'),
  77. glob(true, '/{rate,[a-z][a-z][a-z]}*', '/usd'),
  78. glob(true, '{*.google.*,*.yandex.*}', 'www.google.com', '.'),
  79. glob(true, '{*.google.*,*.yandex.*}', 'www.yandex.com', '.'),
  80. glob(false, '{*.google.*,*.yandex.*}', 'yandex.com', '.'),
  81. glob(false, '{*.google.*,*.yandex.*}', 'google.com', '.'),
  82. glob(true, '{*.google.*,yandex.*}', 'www.google.com', '.'),
  83. glob(true, '{*.google.*,yandex.*}', 'yandex.com', '.'),
  84. glob(false, '{*.google.*,yandex.*}', 'www.yandex.com', '.'),
  85. glob(false, '{*.google.*,yandex.*}', 'google.com', '.'),
  86. glob(true, '*//{,*.}example.com', 'https://www.example.com'),
  87. glob(true, '*//{,*.}example.com', 'http://example.com'),
  88. glob(false, '*//{,*.}example.com', 'http://example.com.net'),
  89. ];
  90. }
  91. test('GlobCompiler', async () => {
  92. const {caseNames, caseDataMap} = await loadGlobTestData();
  93. expect(caseNames.length).toBe(10); // should have 10 test cases
  94. for (const caseName of caseNames) {
  95. const pattern = caseDataMap[`pattern_${caseName}`];
  96. const regexp = caseDataMap[`regexp_${caseName}`];
  97. expect(globCompile(pattern).regexpPattern).toBe(regexp);
  98. }
  99. const golangCases = loadGlobGolangCases();
  100. expect(golangCases.length).toBe(60);
  101. for (const c of golangCases) {
  102. const compiled = globCompile(c.pattern, c.separators);
  103. const msg = `pattern: ${c.pattern}, input: ${c.input}, separators: ${c.separators || '(none)'}, compiled: ${compiled.regexpPattern}`;
  104. // eslint-disable-next-line vitest/valid-expect -- Unlike Jest, Vitest supports a message as the second argument
  105. expect(compiled.regexp.test(c.input), msg).toBe(c.matched);
  106. }
  107. // then our cases
  108. expect(globCompile('*/**/x').regexpPattern).toBe('^.*/.*/x$');
  109. expect(globCompile('*/**/x', '/').regexpPattern).toBe('^[^/]*/.*/x$');
  110. expect(globCompile('[a-b][^-\\]]', '/').regexpPattern).toBe('^[a-b][^-\\]]$');
  111. expect(globCompile('.+^$()|', '/').regexpPattern).toBe('^\\.\\+\\^\\$\\(\\)\\|$');
  112. });