<commit_before>package cmd

import (
	"fmt"
	"os"
	"path/filepath"
	"reflect"
	"syscall"
	"testing"

	"github.com/vlifesystems/rulehunter/internal"
	"github.com/vlifesystems/rulehunter/internal/testhelpers"
)

func TestRunRoot(t *testing.T) {
	wantEntries := []testhelpers.Entry{
		{Level: testhelpers.Error,
			Msg: "Can't load experiment: 0debt_broken.yaml, yaml: line 3: did not find expected key"},
		{Level: testhelpers.Info,
			Msg: "Processing experiment: debt.json"},
		{Level: testhelpers.Info,
			Msg: "Successfully processed experiment: debt.json"},
		{Level: testhelpers.Info,
			Msg: "Processing experiment: debt.yaml"},
		{Level: testhelpers.Info,
			Msg: "Successfully processed experiment: debt.yaml"},
		{Level: testhelpers.Info,
			Msg: "Processing experiment: debt2.json"},
		{Level: testhelpers.Info,
			Msg: "Successfully processed experiment: debt2.json"},
	}
	wantReportFiles := []string{
		// "debt2.json"
		internal.MakeBuildFilename(
			"",
			"What is most likely to indicate success (2)",
		),
		// "debt.yaml"
		internal.MakeBuildFilename(
			"testing",
			"What is most likely to indicate success",
		),
		// "debt.json"
		internal.MakeBuildFilename("", "What is most likely to indicate success"),
	}

	cfgDir := testhelpers.BuildConfigDirs(t, false)
	cfgFilename := filepath.Join(cfgDir, "config.yaml")
	defer os.RemoveAll(cfgDir)
	if testing.Short() {
		testhelpers.MustWriteConfig(t, cfgDir, 100)
	} else {
		testhelpers.MustWriteConfig(t, cfgDir, 2000)
	}

	experimentFiles := []string{
		"0debt_broken.yaml",
		"debt.json",
		"debt.yaml",
		"debt2.json",
		"debt.jso",
	}
	for _, f := range experimentFiles {
		testhelpers.CopyFile(
			t,
			filepath.Join("fixtures", f),
			filepath.Join(cfgDir, "experiments"),
		)
	}

	l := testhelpers.NewLogger()
	if err := runRoot(l, cfgFilename, ""); err != nil {
		t.Errorf("runRoot: %s", err)
	}
	gotReportFiles := testhelpers.GetFilesInDir(
		t,
		filepath.Join(cfgDir, "build", "reports"),
	)
	if !reflect.DeepEqual(gotReportFiles, wantReportFiles) {
		t.Errorf("GetFilesInDir - got: %v\n want: %v",
			gotReportFiles, wantReportFiles)
	}

	if !reflect.DeepEqual(l.GetEntries(), wantEntries) {
		t.Errorf("GetEntries() got: %v\n want: %v", l.GetEntries(), wantEntries)
	}
	// TODO: Test all files generated
}

func TestRunRoot_errors(t *testing.T) {
	tmpDir := testhelpers.BuildConfigDirs(t, false)
	defer os.RemoveAll(tmpDir)

	cases := []struct {
		configFilename string
		wantErr        error
	}{
		{
			configFilename: "config.yaml",
			wantErr: errConfigLoad{
				filename: "config.yaml",
				err:      &os.PathError{"open", "config.yaml", syscall.ENOENT},
			},
		},
		{
			configFilename: filepath.Join(tmpDir, "config.yaml"),
			wantErr: errConfigLoad{
				filename: filepath.Join(tmpDir, "config.yaml"),
				err: &os.PathError{
					"open",
					filepath.Join(tmpDir, "config.yaml"),
					syscall.ENOENT,
				},
			},
		},
	}

	for i, c := range cases {
		l := testhelpers.NewLogger()
		err := runRoot(l, c.configFilename, "")
		if err := checkErrorMatch(err, c.wantErr); err != nil {
			t.Errorf("(%d) runRoot: %s", i, err)
		}
		if len(l.GetEntries()) != 0 {
			t.Errorf("GetEntries() got: %s, want: {}", l.GetEntries())
		}
	}
}

func TestRunRoot_file(t *testing.T) {
	wantEntries := []testhelpers.Entry{
		{Level: testhelpers.Info,
			Msg: "Processing experiment: debt.json"},
		{Level: testhelpers.Info,
			Msg: "Successfully processed experiment: debt.json"},
	}
	wantReportFiles := []string{
		// "debt.json"
		internal.MakeBuildFilename("", "What is most likely to indicate success"),
	}

	cfgDir := testhelpers.BuildConfigDirs(t, false)
	cfgFilename := filepath.Join(cfgDir, "config.yaml")
	defer os.RemoveAll(cfgDir)
	if testing.Short() {
		testhelpers.MustWriteConfig(t, cfgDir, 100)
	} else {
		testhelpers.MustWriteConfig(t, cfgDir, 2000)
	}

	experimentFiles := []string{
		"0debt_broken.yaml",
		"debt.json",
		"debt.yaml",
	}
	for _, f := range experimentFiles {
		testhelpers.CopyFile(
			t,
			filepath.Join("fixtures", f),
			filepath.Join(cfgDir, "experiments"),
		)
	}
	experimentFilename := filepath.Join(cfgDir, "experiments", "debt.json")

	l := testhelpers.NewLogger()
	if err := runRoot(l, cfgFilename, experimentFilename); err != nil {
		t.Errorf("runRoot: %s", err)
	}
	gotReportFiles := testhelpers.GetFilesInDir(
		t,
		filepath.Join(cfgDir, "build", "reports"),
	)
	if !reflect.DeepEqual(gotReportFiles, wantReportFiles) {
		t.Errorf("GetFilesInDir - got: %v\n want: %v",
			gotReportFiles, wantReportFiles)
	}

	if !reflect.DeepEqual(l.GetEntries(), wantEntries) {
		t.Errorf("GetEntries() got: %v\n want: %v", l.GetEntries(), wantEntries)
	}
	// TODO: Test all files generated
}

func TestRunRoot_file_errors(t *testing.T) {
	wantEntries := []testhelpers.Entry{
		{Level: testhelpers.Error,
			Msg: "Can't load experiment: 0debt_broken.yaml, yaml: line 3: did not find expected key"},
		{Level: testhelpers.Error,
			Msg: "Can't load experiment: nonexistant.json, no such file or directory"},
	}
	wantReportFiles := []string{}

	cfgDir := testhelpers.BuildConfigDirs(t, false)
	cfgFilename := filepath.Join(cfgDir, "config.yaml")
	defer os.RemoveAll(cfgDir)
	if testing.Short() {
		testhelpers.MustWriteConfig(t, cfgDir, 100)
	} else {
		testhelpers.MustWriteConfig(t, cfgDir, 2000)
	}

	experimentFiles := []string{
		"0debt_broken.yaml",
		"debt.json",
		"debt.yaml",
	}
	for _, f := range experimentFiles {
		testhelpers.CopyFile(
			t,
			filepath.Join("fixtures", f),
			filepath.Join(cfgDir, "experiments"),<commit_msg>Make TestRunRoot_file_errors log entries portable<commit_after>package cmd

import (
	"fmt"
	"os"
	"path/filepath"
	"reflect"
	"syscall"
	"testing"

	"github.com/vlifesystems/rulehunter/internal"
	"github.com/vlifesystems/rulehunter/internal/testhelpers"
)

func TestRunRoot(t *testing.T) {
	wantEntries := []testhelpers.Entry{
		{Level: testhelpers.Error,
			Msg: "Can't load experiment: 0debt_broken.yaml, yaml: line 3: did not find expected key"},
		{Level: testhelpers.Info,
			Msg: "Processing experiment: debt.json"},
		{Level: testhelpers.Info,
			Msg: "Successfully processed experiment: debt.json"},
		{Level: testhelpers.Info,
			Msg: "Processing experiment: debt.yaml"},
		{Level: testhelpers.Info,
			Msg: "Successfully processed experiment: debt.yaml"},
		{Level: testhelpers.Info,
			Msg: "Processing experiment: debt2.json"},
		{Level: testhelpers.Info,
			Msg: "Successfully processed experiment: debt2.json"},
	}
	wantReportFiles := []string{
		// "debt2.json"
		internal.MakeBuildFilename(
			"",
			"What is most likely to indicate success (2)",
		),
		// "debt.yaml"
		internal.MakeBuildFilename(
			"testing",
			"What is most likely to indicate success",
		),
		// "debt.json"
		internal.MakeBuildFilename("", "What is most likely to indicate success"),
	}

	cfgDir := testhelpers.BuildConfigDirs(t, false)
	cfgFilename := filepath.Join(cfgDir, "config.yaml")
	defer os.RemoveAll(cfgDir)
	if testing.Short() {
		testhelpers.MustWriteConfig(t, cfgDir, 100)
	} else {
		testhelpers.MustWriteConfig(t, cfgDir, 2000)
	}

	experimentFiles := []string{
		"0debt_broken.yaml",
		"debt.json",
		"debt.yaml",
		"debt2.json",
		"debt.jso",
	}
	for _, f := range experimentFiles {
		testhelpers.CopyFile(
			t,
			filepath.Join("fixtures", f),
			filepath.Join(cfgDir, "experiments"),
		)
	}

	l := testhelpers.NewLogger()
	if err := runRoot(l, cfgFilename, ""); err != nil {
		t.Errorf("runRoot: %s", err)
	}
	gotReportFiles := testhelpers.GetFilesInDir(
		t,
		filepath.Join(cfgDir, "build", "reports"),
	)
	if !reflect.DeepEqual(gotReportFiles, wantReportFiles) {
		t.Errorf("GetFilesInDir - got: %v\n want: %v",
			gotReportFiles, wantReportFiles)
	}

	if !reflect.DeepEqual(l.GetEntries(), wantEntries) {
		t.Errorf("GetEntries() got: %v\n want: %v", l.GetEntries(), wantEntries)
	}
	// TODO: Test all files generated
}

func TestRunRoot_errors(t *testing.T) {
	tmpDir := testhelpers.BuildConfigDirs(t, false)
	defer os.RemoveAll(tmpDir)

	cases := []struct {
		configFilename string
		wantErr        error
	}{
		{
			configFilename: "config.yaml",
			wantErr: errConfigLoad{
				filename: "config.yaml",
				err:      &os.PathError{"open", "config.yaml", syscall.ENOENT},
			},
		},
		{
			configFilename: filepath.Join(tmpDir, "config.yaml"),
			wantErr: errConfigLoad{
				filename: filepath.Join(tmpDir, "config.yaml"),
				err: &os.PathError{
					"open",
					filepath.Join(tmpDir, "config.yaml"),
					syscall.ENOENT,
				},
			},
		},
	}

	for i, c := range cases {
		l := testhelpers.NewLogger()
		err := runRoot(l, c.configFilename, "")
		if err := checkErrorMatch(err, c.wantErr); err != nil {
			t.Errorf("(%d) runRoot: %s", i, err)
		}
		if len(l.GetEntries()) != 0 {
			t.Errorf("GetEntries() got: %s, want: {}", l.GetEntries())
		}
	}
}

func TestRunRoot_file(t *testing.T) {
	wantEntries := []testhelpers.Entry{
		{Level: testhelpers.Info,
			Msg: "Processing experiment: debt.json"},
		{Level: testhelpers.Info,
			Msg: "Successfully processed experiment: debt.json"},
	}
	wantReportFiles := []string{
		// "debt.json"
		internal.MakeBuildFilename("", "What is most likely to indicate success"),
	}

	cfgDir := testhelpers.BuildConfigDirs(t, false)
	cfgFilename := filepath.Join(cfgDir, "config.yaml")
	defer os.RemoveAll(cfgDir)
	if testing.Short() {
		testhelpers.MustWriteConfig(t, cfgDir, 100)
	} else {
		testhelpers.MustWriteConfig(t, cfgDir, 2000)
	}

	experimentFiles := []string{
		"0debt_broken.yaml",
		"debt.json",
		"debt.yaml",
	}
	for _, f := range experimentFiles {
		testhelpers.CopyFile(
			t,
			filepath.Join("fixtures", f),
			filepath.Join(cfgDir, "experiments"),
		)
	}
	experimentFilename := filepath.Join(cfgDir, "experiments", "debt.json")

	l := testhelpers.NewLogger()
	if err := runRoot(l, cfgFilename, experimentFilename); err != nil {
		t.Errorf("runRoot: %s", err)
	}
	gotReportFiles := testhelpers.GetFilesInDir(
		t,
		filepath.Join(cfgDir, "build", "reports"),
	)
	if !reflect.DeepEqual(gotReportFiles, wantReportFiles) {
		t.Errorf("GetFilesInDir - got: %v\n want: %v",
			gotReportFiles, wantReportFiles)
	}

	if !reflect.DeepEqual(l.GetEntries(), wantEntries) {
		t.Errorf("GetEntries() got: %v\n want: %v", l.GetEntries(), wantEntries)
	}
	// TODO: Test all files generated
}

func TestRunRoot_file_errors(t *testing.T) {
	wantEntries := []testhelpers.Entry{
		{Level: testhelpers.Error,
			Msg: "Can't load experiment: 0debt_broken.yaml, yaml: line 3: did not find expected key"},
		{Level: testhelpers.Error,
			Msg: "Can't load experiment: nonexistant.json, " + syscall.ENOENT.Error()},
	}
	wantReportFiles := []string{}

	cfgDir := testhelpers.BuildConfigDirs(t, false)
	cfgFilename := filepath.Join(cfgDir, "config.yaml")
	defer os.RemoveAll(cfgDir)
	if testing.Short() {
		testhelpers.MustWriteConfig(t, cfgDir, 100)
	} else {
		testhelpers.MustWriteConfig(t, cfgDir, 2000)
	}

	experimentFiles := []string{
		"0debt_broken.yaml",
		"debt.json",
		"debt.yaml",
	}
	for _, f := range experimentFiles {
		testhelpers.CopyFile(
			t,
			filepath.Join("fixtures", f),
			filepath.Join(cfgDir, "experiments"),
{'fraction_non_alphanumeric': 0.15717109992810926, 'fraction_numerical': 0.006110711718188354, 'mean_word_length': 4.247053276756247, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3343651', 'n_tokens_mistral': 4385, 'n_tokens_neox': 3976, 'n_words': 835}