code-intelligence.com/cifuzz@v0.40.0/internal/cmd/integrate/integrate_test.go (about) 1 package integrate 2 3 import ( 4 "bytes" 5 "io" 6 "os" 7 "path/filepath" 8 "runtime" 9 "strings" 10 "testing" 11 12 "github.com/stretchr/testify/assert" 13 "github.com/stretchr/testify/require" 14 15 builderPkg "code-intelligence.com/cifuzz/internal/builder" 16 initCmd "code-intelligence.com/cifuzz/internal/cmd/init" 17 "code-intelligence.com/cifuzz/internal/cmdutils" 18 "code-intelligence.com/cifuzz/internal/config" 19 "code-intelligence.com/cifuzz/internal/testutil" 20 "code-intelligence.com/cifuzz/pkg/log" 21 "code-intelligence.com/cifuzz/pkg/mocks" 22 "code-intelligence.com/cifuzz/util/fileutil" 23 "code-intelligence.com/cifuzz/util/stringutil" 24 ) 25 26 var logOutput io.ReadWriter 27 28 func TestMain(m *testing.M) { 29 logOutput = bytes.NewBuffer([]byte{}) 30 log.Output = logOutput 31 32 m.Run() 33 } 34 35 func TestMissingCIFuzzProject(t *testing.T) { 36 // Create an empty project directory and change working directory to it 37 testDir, cleanup := testutil.ChdirToTempDir("integrate-cmd-test") 38 defer cleanup() 39 40 // Check that the command produces the expected error when not 41 // called below a cifuzz project directory. 42 _, err := cmdutils.ExecuteCommand(t, New(), os.Stdin, "git") 43 require.Error(t, err) 44 testutil.CheckOutput(t, logOutput, "cifuzz.yaml file does not exist") 45 46 // Initialize a cifuzz project 47 err = fileutil.Touch(filepath.Join(testDir, "CMakeLists.txt")) 48 require.NoError(t, err) 49 _, err = cmdutils.ExecuteCommand(t, initCmd.New(), os.Stdin) 50 require.NoError(t, err) 51 52 // Check that command produces no error when called below a cifuzz 53 // project directory 54 _, err = cmdutils.ExecuteCommand(t, New(), os.Stdin, "git") 55 require.NoError(t, err) 56 } 57 58 func TestSetupGitIgnore(t *testing.T) { 59 testDir, cleanup := testutil.BootstrapExampleProjectForTest("integrate-cmd-test", config.BuildSystemCMake) 60 defer cleanup() 61 62 gitIgnorePath := filepath.Join(testDir, ".gitignore") 63 cmakeListsPath := filepath.Join(testDir, "CMakeLists.txt") 64 // Remove existing .gitignore and CMakeLists.txt from example project 65 os.Remove(gitIgnorePath) 66 os.Remove(cmakeListsPath) 67 68 // Check that a new .gitignore file is created 69 err := setupGitIgnore(testDir) 70 require.NoError(t, err) 71 content, err := os.ReadFile(gitIgnorePath) 72 require.NoError(t, err) 73 assert.Equal(t, 2, len(getNonEmptyLines(content))) 74 75 // Check that only nonexistent entries are added 76 fileToIgnore := "/.cifuzz-corpus/\n" 77 err = os.WriteFile(gitIgnorePath, []byte(fileToIgnore), 0644) 78 require.NoError(t, err) 79 err = setupGitIgnore(testDir) 80 require.NoError(t, err) 81 content, err = os.ReadFile(gitIgnorePath) 82 require.NoError(t, err) 83 assert.Equal(t, 2, len(getNonEmptyLines(content))) 84 85 // Check that two additional entries are added for cmake projects 86 err = fileutil.Touch(cmakeListsPath) 87 require.NoError(t, err) 88 err = setupGitIgnore(testDir) 89 require.NoError(t, err) 90 content, err = os.ReadFile(gitIgnorePath) 91 require.NoError(t, err) 92 assert.Equal(t, 4, len(getNonEmptyLines(content))) 93 } 94 95 func TestSetupCMakePresets(t *testing.T) { 96 testDir, cleanup := testutil.BootstrapExampleProjectForTest("integrate-cmd-test", config.BuildSystemCMake) 97 defer cleanup() 98 99 sourceDir := getRootSourceDirectory(t, testDir) 100 cmakePresets := filepath.Join(sourceDir, "share", "integration", "CMakePresets.json") 101 finder := &mocks.RunfilesFinderMock{} 102 finder.On("CMakePresetsPath").Return(cmakePresets, nil) 103 104 err := setupCMakePresets(testDir, finder) 105 require.NoError(t, err) 106 107 // Check that CMakeUserPresets.json has been created 108 presetsPath := filepath.Join(testDir, "CMakeUserPresets.json") 109 presetsExists, err := fileutil.Exists(presetsPath) 110 require.NoError(t, err) 111 require.True(t, presetsExists) 112 113 err = setupCMakePresets(testDir, finder) 114 require.NoError(t, err) 115 116 // Check that presets are logged if CMakeUserPresets.json already exists 117 content, err := os.ReadFile(cmakePresets) 118 require.NoError(t, err) 119 testutil.CheckOutput(t, logOutput, string(content)) 120 } 121 122 func TestSetupVSCodeTasks(t *testing.T) { 123 testDir, cleanup := testutil.BootstrapExampleProjectForTest("integrate-cmd-test", config.BuildSystemCMake) 124 defer cleanup() 125 126 sourceDir := getRootSourceDirectory(t, testDir) 127 vscodeTasks := filepath.Join(sourceDir, "share", "integration", "tasks.json") 128 finder := &mocks.RunfilesFinderMock{} 129 finder.On("VSCodeTasksPath").Return(vscodeTasks, nil) 130 131 err := setupVSCodeTasks(testDir, finder) 132 require.NoError(t, err) 133 134 // Check that tasks.json has been created 135 presetsPath := filepath.Join(testDir, ".vscode", "tasks.json") 136 presetsExists, err := fileutil.Exists(presetsPath) 137 require.NoError(t, err) 138 require.True(t, presetsExists) 139 140 err = setupVSCodeTasks(testDir, finder) 141 require.NoError(t, err) 142 143 // Check that tasks are logged if tasks.json already exists 144 content, err := os.ReadFile(vscodeTasks) 145 require.NoError(t, err) 146 testutil.CheckOutput(t, logOutput, strings.TrimSpace(string(content))) 147 } 148 149 func getNonEmptyLines(content []byte) []string { 150 return stringutil.NonEmpty(strings.Split(string(content), "\n")) 151 } 152 153 func getRootSourceDirectory(t *testing.T, testDir string) string { 154 // Change to source file directory 155 _, file, _, _ := runtime.Caller(0) 156 err := os.Chdir(filepath.Dir(file)) 157 require.NoError(t, err) 158 159 // Find root source directory 160 sourceDir, err := builderPkg.FindProjectDir() 161 require.NoError(t, err) 162 163 // Change back to test directory 164 err = os.Chdir(testDir) 165 require.NoError(t, err) 166 167 return sourceDir 168 }