mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-23 11:34:44 -07:00
test: fix Windows CI execution and resolve exposed platform failures (#24476)
This commit is contained in:
@@ -53,16 +53,16 @@ afterEach(() => {
|
||||
});
|
||||
|
||||
describe('createPolicyEngineConfig', () => {
|
||||
const MOCK_DEFAULT_DIR = '/tmp/mock/default/policies';
|
||||
const MOCK_DEFAULT_DIR = nodePath.resolve('/tmp/mock/default/policies');
|
||||
|
||||
beforeEach(async () => {
|
||||
clearEmittedPolicyWarnings();
|
||||
// Mock Storage to avoid host environment contamination
|
||||
vi.spyOn(Storage, 'getUserPoliciesDir').mockReturnValue(
|
||||
'/non/existent/user/policies',
|
||||
nodePath.resolve('/non/existent/user/policies'),
|
||||
);
|
||||
vi.spyOn(Storage, 'getSystemPoliciesDir').mockReturnValue(
|
||||
'/non/existent/system/policies',
|
||||
nodePath.resolve('/non/existent/system/policies'),
|
||||
);
|
||||
vi.mocked(isDirectorySecure).mockResolvedValue({ secure: true });
|
||||
});
|
||||
@@ -71,13 +71,14 @@ describe('createPolicyEngineConfig', () => {
|
||||
* Helper to mock a policy file in the filesystem.
|
||||
*/
|
||||
function mockPolicyFile(path: string, content: string) {
|
||||
const resolvedPath = nodePath.resolve(path);
|
||||
vi.mocked(
|
||||
fs.readdir as (path: PathLike) => Promise<string[] | Dirent[]>,
|
||||
).mockImplementation(async (p) => {
|
||||
if (nodePath.resolve(p.toString()) === nodePath.dirname(path)) {
|
||||
if (nodePath.resolve(p.toString()) === nodePath.dirname(resolvedPath)) {
|
||||
return [
|
||||
{
|
||||
name: nodePath.basename(path),
|
||||
name: nodePath.basename(resolvedPath),
|
||||
isFile: () => true,
|
||||
isDirectory: () => false,
|
||||
} as unknown as Dirent,
|
||||
@@ -91,13 +92,13 @@ describe('createPolicyEngineConfig', () => {
|
||||
});
|
||||
|
||||
vi.mocked(fs.stat).mockImplementation(async (p) => {
|
||||
if (nodePath.resolve(p.toString()) === nodePath.dirname(path)) {
|
||||
if (nodePath.resolve(p.toString()) === nodePath.dirname(resolvedPath)) {
|
||||
return {
|
||||
isDirectory: () => true,
|
||||
isFile: () => false,
|
||||
} as unknown as Stats;
|
||||
}
|
||||
if (nodePath.resolve(p.toString()) === path) {
|
||||
if (nodePath.resolve(p.toString()) === resolvedPath) {
|
||||
return {
|
||||
isDirectory: () => false,
|
||||
isFile: () => true,
|
||||
@@ -111,7 +112,7 @@ describe('createPolicyEngineConfig', () => {
|
||||
});
|
||||
|
||||
vi.mocked(fs.readFile).mockImplementation(async (p) => {
|
||||
if (nodePath.resolve(p.toString()) === path) {
|
||||
if (nodePath.resolve(p.toString()) === resolvedPath) {
|
||||
return content;
|
||||
}
|
||||
return (
|
||||
@@ -137,23 +138,21 @@ describe('createPolicyEngineConfig', () => {
|
||||
.spyOn(tomlLoader, 'loadPoliciesFromToml')
|
||||
.mockResolvedValue({ rules: [], checkers: [], errors: [] });
|
||||
|
||||
await createPolicyEngineConfig(
|
||||
{},
|
||||
ApprovalMode.DEFAULT,
|
||||
'/tmp/mock/default/policies',
|
||||
);
|
||||
await createPolicyEngineConfig({}, ApprovalMode.DEFAULT, MOCK_DEFAULT_DIR);
|
||||
|
||||
expect(loadPoliciesSpy).toHaveBeenCalled();
|
||||
const calledDirs = loadPoliciesSpy.mock.calls[0][0];
|
||||
expect(calledDirs).not.toContain(systemPolicyDir);
|
||||
expect(calledDirs).toContain('/non/existent/user/policies');
|
||||
expect(calledDirs).toContain('/tmp/mock/default/policies');
|
||||
expect(calledDirs).not.toContain(nodePath.resolve(systemPolicyDir));
|
||||
expect(calledDirs).toContain(
|
||||
nodePath.resolve('/non/existent/user/policies'),
|
||||
);
|
||||
expect(calledDirs).toContain(MOCK_DEFAULT_DIR);
|
||||
});
|
||||
|
||||
it('should NOT filter out insecure supplemental admin policy directories', async () => {
|
||||
const adminPolicyDir = '/insecure/admin/policies';
|
||||
const adminPolicyDir = nodePath.resolve('/insecure/admin/policies');
|
||||
vi.mocked(isDirectorySecure).mockImplementation(async (path: string) => {
|
||||
if (nodePath.resolve(path) === nodePath.resolve(adminPolicyDir)) {
|
||||
if (nodePath.resolve(path) === adminPolicyDir) {
|
||||
return { secure: false, reason: 'Insecure directory' };
|
||||
}
|
||||
return { secure: true };
|
||||
@@ -166,14 +165,18 @@ describe('createPolicyEngineConfig', () => {
|
||||
await createPolicyEngineConfig(
|
||||
{ adminPolicyPaths: [adminPolicyDir] },
|
||||
ApprovalMode.DEFAULT,
|
||||
'/tmp/mock/default/policies',
|
||||
MOCK_DEFAULT_DIR,
|
||||
);
|
||||
|
||||
const calledDirs = loadPoliciesSpy.mock.calls[0][0];
|
||||
expect(calledDirs).toContain(adminPolicyDir);
|
||||
expect(calledDirs).toContain('/non/existent/system/policies');
|
||||
expect(calledDirs).toContain('/non/existent/user/policies');
|
||||
expect(calledDirs).toContain('/tmp/mock/default/policies');
|
||||
expect(calledDirs).toContain(
|
||||
nodePath.resolve('/non/existent/system/policies'),
|
||||
);
|
||||
expect(calledDirs).toContain(
|
||||
nodePath.resolve('/non/existent/user/policies'),
|
||||
);
|
||||
expect(calledDirs).toContain(MOCK_DEFAULT_DIR);
|
||||
});
|
||||
|
||||
it('should return ASK_USER for write tools and ALLOW for read-only tools by default', async () => {
|
||||
@@ -736,7 +739,9 @@ modes = ["plan"]
|
||||
});
|
||||
|
||||
it('should deduplicate security warnings when called multiple times', async () => {
|
||||
const systemPoliciesDir = '/tmp/gemini-cli-test/system/policies';
|
||||
const systemPoliciesDir = nodePath.resolve(
|
||||
'/tmp/gemini-cli-test/system/policies',
|
||||
);
|
||||
vi.spyOn(Storage, 'getSystemPoliciesDir').mockReturnValue(
|
||||
systemPoliciesDir,
|
||||
);
|
||||
@@ -756,7 +761,7 @@ modes = ["plan"]
|
||||
|
||||
// First call
|
||||
await createPolicyEngineConfig(
|
||||
{ adminPolicyPaths: ['/tmp/other/admin/policies'] },
|
||||
{ adminPolicyPaths: [nodePath.resolve('/tmp/other/admin/policies')] },
|
||||
ApprovalMode.DEFAULT,
|
||||
);
|
||||
expect(feedbackSpy).toHaveBeenCalledWith(
|
||||
|
||||
@@ -19,10 +19,10 @@ describe('Workspace-Level Policies', () => {
|
||||
vi.resetModules();
|
||||
const { Storage } = await import('../config/storage.js');
|
||||
vi.spyOn(Storage, 'getUserPoliciesDir').mockReturnValue(
|
||||
'/mock/user/policies',
|
||||
nodePath.resolve('/mock/user/policies'),
|
||||
);
|
||||
vi.spyOn(Storage, 'getSystemPoliciesDir').mockReturnValue(
|
||||
'/mock/system/policies',
|
||||
nodePath.resolve('/mock/system/policies'),
|
||||
);
|
||||
// Ensure security check always returns secure
|
||||
vi.mocked(isDirectorySecure).mockResolvedValue({ secure: true });
|
||||
@@ -35,8 +35,8 @@ describe('Workspace-Level Policies', () => {
|
||||
});
|
||||
|
||||
it('should load workspace policies with correct priority (Tier 3)', async () => {
|
||||
const workspacePoliciesDir = '/mock/workspace/policies';
|
||||
const defaultPoliciesDir = '/mock/default/policies';
|
||||
const workspacePoliciesDir = nodePath.resolve('/mock/workspace/policies');
|
||||
const defaultPoliciesDir = nodePath.resolve('/mock/default/policies');
|
||||
|
||||
// Mock FS
|
||||
const actualFs =
|
||||
@@ -44,8 +44,9 @@ describe('Workspace-Level Policies', () => {
|
||||
'node:fs/promises',
|
||||
);
|
||||
|
||||
const mockRoot = nodePath.resolve('/mock/');
|
||||
const mockStat = vi.fn(async (path: string) => {
|
||||
if (typeof path === 'string' && path.startsWith('/mock/')) {
|
||||
if (typeof path === 'string' && path.startsWith(mockRoot)) {
|
||||
return {
|
||||
isDirectory: () => true,
|
||||
isFile: () => false,
|
||||
@@ -57,7 +58,7 @@ describe('Workspace-Level Policies', () => {
|
||||
// Mock readdir to return a policy file for each tier
|
||||
const mockReaddir = vi.fn(async (path: string) => {
|
||||
const normalizedPath = nodePath.normalize(path);
|
||||
if (normalizedPath.endsWith('default/policies'))
|
||||
if (normalizedPath.endsWith(nodePath.normalize('default/policies')))
|
||||
return [
|
||||
{
|
||||
name: 'default.toml',
|
||||
@@ -65,11 +66,11 @@ describe('Workspace-Level Policies', () => {
|
||||
isDirectory: () => false,
|
||||
},
|
||||
] as unknown as Awaited<ReturnType<typeof actualFs.readdir>>;
|
||||
if (normalizedPath.endsWith('user/policies'))
|
||||
if (normalizedPath.endsWith(nodePath.normalize('user/policies')))
|
||||
return [
|
||||
{ name: 'user.toml', isFile: () => true, isDirectory: () => false },
|
||||
] as unknown as Awaited<ReturnType<typeof actualFs.readdir>>;
|
||||
if (normalizedPath.endsWith('workspace/policies'))
|
||||
if (normalizedPath.endsWith(nodePath.normalize('workspace/policies')))
|
||||
return [
|
||||
{
|
||||
name: 'workspace.toml',
|
||||
@@ -77,7 +78,7 @@ describe('Workspace-Level Policies', () => {
|
||||
isDirectory: () => false,
|
||||
},
|
||||
] as unknown as Awaited<ReturnType<typeof actualFs.readdir>>;
|
||||
if (normalizedPath.endsWith('system/policies'))
|
||||
if (normalizedPath.endsWith(nodePath.normalize('system/policies')))
|
||||
return [
|
||||
{ name: 'admin.toml', isFile: () => true, isDirectory: () => false },
|
||||
] as unknown as Awaited<ReturnType<typeof actualFs.readdir>>;
|
||||
@@ -160,7 +161,7 @@ priority = 10
|
||||
});
|
||||
|
||||
it('should ignore workspace policies if workspacePoliciesDir is undefined', async () => {
|
||||
const defaultPoliciesDir = '/mock/default/policies';
|
||||
const defaultPoliciesDir = nodePath.resolve('/mock/default/policies');
|
||||
|
||||
// Mock FS (simplified)
|
||||
const actualFs =
|
||||
@@ -168,8 +169,9 @@ priority = 10
|
||||
'node:fs/promises',
|
||||
);
|
||||
|
||||
const mockRoot = nodePath.resolve('/mock/');
|
||||
const mockStat = vi.fn(async (path: string) => {
|
||||
if (typeof path === 'string' && path.startsWith('/mock/')) {
|
||||
if (typeof path === 'string' && path.startsWith(mockRoot)) {
|
||||
return {
|
||||
isDirectory: () => true,
|
||||
isFile: () => false,
|
||||
@@ -180,7 +182,7 @@ priority = 10
|
||||
|
||||
const mockReaddir = vi.fn(async (path: string) => {
|
||||
const normalizedPath = nodePath.normalize(path);
|
||||
if (normalizedPath.endsWith('default/policies'))
|
||||
if (normalizedPath.endsWith(nodePath.normalize('default/policies')))
|
||||
return [
|
||||
{
|
||||
name: 'default.toml',
|
||||
@@ -225,7 +227,7 @@ priority=10`,
|
||||
});
|
||||
|
||||
it('should load workspace policies and correctly transform to Tier 3', async () => {
|
||||
const workspacePoliciesDir = '/mock/workspace/policies';
|
||||
const workspacePoliciesDir = nodePath.resolve('/mock/workspace/policies');
|
||||
|
||||
// Mock FS
|
||||
const actualFs =
|
||||
@@ -233,8 +235,9 @@ priority=10`,
|
||||
'node:fs/promises',
|
||||
);
|
||||
|
||||
const mockRoot = nodePath.resolve('/mock/');
|
||||
const mockStat = vi.fn(async (path: string) => {
|
||||
if (typeof path === 'string' && path.startsWith('/mock/')) {
|
||||
if (typeof path === 'string' && path.startsWith(mockRoot)) {
|
||||
return {
|
||||
isDirectory: () => true,
|
||||
isFile: () => false,
|
||||
@@ -245,7 +248,7 @@ priority=10`,
|
||||
|
||||
const mockReaddir = vi.fn(async (path: string) => {
|
||||
const normalizedPath = nodePath.normalize(path);
|
||||
if (normalizedPath.endsWith('workspace/policies'))
|
||||
if (normalizedPath.endsWith(nodePath.normalize('workspace/policies')))
|
||||
return [
|
||||
{
|
||||
name: 'workspace.toml',
|
||||
|
||||
Reference in New Issue
Block a user