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  }