Skip to content

Commit

Permalink
Check if the repository for the transpile task is valid before runnin…
Browse files Browse the repository at this point in the history
…g the evaluation, so it is checked just once

Closes #263
  • Loading branch information
ruiAzevedo19 committed Aug 1, 2024
1 parent 7aa855b commit 45a79a7
Show file tree
Hide file tree
Showing 3 changed files with 217 additions and 5 deletions.
2 changes: 2 additions & 0 deletions evaluate/task/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ func (r *Repository) Validate(logger *log.Logger, language language.Language) (e
switch taskIdentifier {
case IdentifierCodeRepair:
return validateCodeRepairRepository(logger, r.DataPath(), language)
case IdentifierTranspile:
return validateTranspileRepository(logger, r.DataPath(), language)
case IdentifierWriteTests:
return validateWriteTestsRepository(logger, r.DataPath(), language)
}
Expand Down
47 changes: 42 additions & 5 deletions evaluate/task/task-transpile.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,14 +173,10 @@ func (t *TaskTranspile) Run(ctx evaltask.Context) (repositoryAssessment map[eval
// unpackTranspilerPackage checks if the testdata repository for the transpilation task is well-formed and returns the path to the implementation file and also the path to the file that holds the stub.
func (t *TaskTranspile) unpackTranspilerPackage(ctx evaltask.Context, fileLogger *log.Logger, originLanguage language.Language, packagePath string) (originFilePath string, stubFilePath string, err error) {
packagePathAbsolute := filepath.Join(ctx.Repository.DataPath(), packagePath)
// Check if the package path has a directory called "implementation" with a source file in the language to transpile from.

files, err := originLanguage.Files(fileLogger, filepath.Join(packagePathAbsolute, "implementation"))
if err != nil {
return "", "", pkgerrors.WithStack(err)
} else if len(files) != 1 {
return "", "", pkgerrors.Errorf("package %q in repository %q must have an \"implementation\" directory with just one %s source file to transpile", packagePath, ctx.Repository.Name(), originLanguage.Name())
} else if strings.HasSuffix(files[0], originLanguage.DefaultTestFileSuffix()) {
return "", "", pkgerrors.Errorf("package %q in repository %q must have an \"implementation\" directory with only a %s source file, but found a test file %q", packagePath, ctx.Repository.Name(), originLanguage.Name(), originFilePath)
}
originFilePath = filepath.Join("implementation", files[0])

Expand All @@ -191,3 +187,44 @@ func (t *TaskTranspile) unpackTranspilerPackage(ctx evaltask.Context, fileLogger

return originFilePath, stubFilePath, nil
}

// validateTranspileRepository checks if the repository for the "transpile" task is well-formed.
func validateTranspileRepository(logger *log.Logger, repositoryPath string, destinationLanguage language.Language) (err error) {
logger.Printf("validating repository %q", repositoryPath)

var originLanguage language.Language
if _, ok := destinationLanguage.(*golang.Language); ok {
originLanguage = &java.Language{}
} else {
originLanguage = &golang.Language{}
}

packagePaths, err := repositoryOnlyHasPackages(repositoryPath)
if err != nil {
return err
}

for _, packagePath := range packagePaths {
// Validate the implementation folder.
files, err := originLanguage.Files(logger, filepath.Join(packagePath, "implementation"))
if err != nil {
return pkgerrors.WithStack(err)
} else if len(files) != 1 {
return pkgerrors.Errorf("package %q must have an \"implementation\" directory with just one %s source file to transpile", packagePath, originLanguage.Name())
} else if strings.HasSuffix(files[0], originLanguage.DefaultTestFileSuffix()) {
return pkgerrors.Errorf("package %q must have an \"implementation\" directory with only a %s source file, but found a test file %q", packagePath, originLanguage.Name(), files[0])
}

// Check if the package as one source file and one test file in the language we want to transpile to.
sourceFiles, testFiles, err := packagesSourceAndTestFiles(logger, packagePath, destinationLanguage)
if err != nil {
return err
} else if len(sourceFiles) != 1 {
return pkgerrors.Errorf("package %q must contain exactly one %s source file, but found %+v", packagePath, destinationLanguage.Name(), sourceFiles)
} else if len(testFiles) != 1 {
return pkgerrors.Errorf("package %q must contain exactly one %s test file, but found %+v", packagePath, destinationLanguage.Name(), testFiles)
}
}

return nil
}
173 changes: 173 additions & 0 deletions evaluate/task/task-transpile_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package task

import (
"os"
"path/filepath"
"testing"

Expand Down Expand Up @@ -349,3 +350,175 @@ func TestTaskTranspileRun(t *testing.T) {
}
})
}

func TestValidateTranspileRepository(t *testing.T) {
validate := func(t *testing.T, tc *tasktesting.TestCaseValidateRepository) {
tc.Validate(t, validateTranspileRepository)
}

validate(t, &tasktesting.TestCaseValidateRepository{
Name: "Package does not contain implementation folder",

Before: func(repositoryPath string) {
require.NoError(t, os.MkdirAll(filepath.Join(repositoryPath, "somePackage"), 0700))
},

TestdataPath: filepath.Join("..", "..", "testdata"),
RepositoryPath: filepath.Join("golang", "transpile"),
Language: &golang.Language{},

ExpectedErrorContains: "no such file or directory",
})
t.Run("Go", func(t *testing.T) {
validate(t, &tasktesting.TestCaseValidateRepository{
Name: "Implementation folder contains multiple files",

Before: func(repositoryPath string) {
implementationPath := filepath.Join(repositoryPath, "somePackage", "implementation")
require.NoError(t, os.MkdirAll(implementationPath, 0700))
require.NoError(t, os.WriteFile(filepath.Join(implementationPath, "ClassA.java"), []byte(`content`), 0700))
require.NoError(t, os.WriteFile(filepath.Join(implementationPath, "ClassB.java"), []byte(`content`), 0700))
},

TestdataPath: filepath.Join("..", "..", "testdata"),
RepositoryPath: filepath.Join("golang", "transpile"),
Language: &golang.Language{},

ExpectedErrorContains: "must have an \"implementation\" directory with just one Java source file to transpile",
})
validate(t, &tasktesting.TestCaseValidateRepository{
Name: "Implementation folder contains a test file",

Before: func(repositoryPath string) {
implementationPath := filepath.Join(repositoryPath, "somePackage", "implementation")
require.NoError(t, os.MkdirAll(implementationPath, 0700))
require.NoError(t, os.WriteFile(filepath.Join(implementationPath, "ClassTest.java"), []byte(`content`), 0700))
},

TestdataPath: filepath.Join("..", "..", "testdata"),
RepositoryPath: filepath.Join("golang", "transpile"),
Language: &golang.Language{},

ExpectedErrorContains: "must have an \"implementation\" directory with only a Java source file, but found a test file",
})
validate(t, &tasktesting.TestCaseValidateRepository{
Name: "Package without source file",

Before: func(repositoryPath string) {
implementationPath := filepath.Join(repositoryPath, "somePackage", "implementation")
require.NoError(t, os.MkdirAll(implementationPath, 0700))
require.NoError(t, os.WriteFile(filepath.Join(implementationPath, "Class.java"), []byte(`content`), 0700))
},

TestdataPath: filepath.Join("..", "..", "testdata"),
RepositoryPath: filepath.Join("golang", "transpile"),
Language: &golang.Language{},

ExpectedErrorContains: " must contain exactly one Go source file",
})
validate(t, &tasktesting.TestCaseValidateRepository{
Name: "Package without test file",

Before: func(repositoryPath string) {
implementationPath := filepath.Join(repositoryPath, "somePackage", "implementation")
require.NoError(t, os.MkdirAll(implementationPath, 0700))
require.NoError(t, os.WriteFile(filepath.Join(implementationPath, "Class.java"), []byte(`content`), 0700))
require.NoError(t, os.WriteFile(filepath.Join(repositoryPath, "somePackage", "file.go"), []byte(`content`), 0700))
},

TestdataPath: filepath.Join("..", "..", "testdata"),
RepositoryPath: filepath.Join("golang", "transpile"),
Language: &golang.Language{},

ExpectedErrorContains: " must contain exactly one Go test file",
})
validate(t, &tasktesting.TestCaseValidateRepository{
Name: "Well-formed",

Before: func(repositoryPath string) {
require.NoError(t, osutil.MkdirAll(filepath.Join(repositoryPath, ".git")))
require.NoError(t, os.WriteFile(filepath.Join(repositoryPath, ".git", "index"), []byte(`content`), 0700))
},

TestdataPath: filepath.Join("..", "..", "testdata"),
RepositoryPath: filepath.Join("golang", "transpile"),
Language: &golang.Language{},
})
})
t.Run("Java", func(t *testing.T) {
validate(t, &tasktesting.TestCaseValidateRepository{
Name: "Implementation folder contains multiple files",

Before: func(repositoryPath string) {
implementationPath := filepath.Join(repositoryPath, "somePackage", "implementation")
require.NoError(t, os.MkdirAll(implementationPath, 0700))
require.NoError(t, os.WriteFile(filepath.Join(implementationPath, "fileA.go"), []byte(`content`), 0700))
require.NoError(t, os.WriteFile(filepath.Join(implementationPath, "fileB.go"), []byte(`content`), 0700))
},

TestdataPath: filepath.Join("..", "..", "testdata"),
RepositoryPath: filepath.Join("java", "transpile"),
Language: &java.Language{},

ExpectedErrorContains: "must have an \"implementation\" directory with just one Go source file to transpile",
})
validate(t, &tasktesting.TestCaseValidateRepository{
Name: "Implementation folder contains a test file",

Before: func(repositoryPath string) {
implementationPath := filepath.Join(repositoryPath, "somePackage", "implementation")
require.NoError(t, os.MkdirAll(implementationPath, 0700))
require.NoError(t, os.WriteFile(filepath.Join(implementationPath, "file_test.go"), []byte(`content`), 0700))
},

TestdataPath: filepath.Join("..", "..", "testdata"),
RepositoryPath: filepath.Join("java", "transpile"),
Language: &java.Language{},

ExpectedErrorContains: "must have an \"implementation\" directory with only a Go source file, but found a test file",
})
validate(t, &tasktesting.TestCaseValidateRepository{
Name: "Package without source file",

Before: func(repositoryPath string) {
implementationPath := filepath.Join(repositoryPath, "somePackage", "implementation")
require.NoError(t, os.MkdirAll(implementationPath, 0700))
require.NoError(t, os.WriteFile(filepath.Join(implementationPath, "file.go"), []byte(`content`), 0700))
},

TestdataPath: filepath.Join("..", "..", "testdata"),
RepositoryPath: filepath.Join("java", "transpile"),
Language: &java.Language{},

ExpectedErrorContains: " must contain exactly one Java source file",
})
validate(t, &tasktesting.TestCaseValidateRepository{
Name: "Package without test file",

Before: func(repositoryPath string) {
implementationPath := filepath.Join(repositoryPath, "somePackage", "implementation")
require.NoError(t, os.MkdirAll(implementationPath, 0700))
require.NoError(t, os.WriteFile(filepath.Join(implementationPath, "file.go"), []byte(`content`), 0700))
require.NoError(t, os.WriteFile(filepath.Join(repositoryPath, "somePackage", "Class.java"), []byte(`content`), 0700))
},

TestdataPath: filepath.Join("..", "..", "testdata"),
RepositoryPath: filepath.Join("java", "transpile"),
Language: &java.Language{},

ExpectedErrorContains: " must contain exactly one Java test file",
})
validate(t, &tasktesting.TestCaseValidateRepository{
Name: "Well-formed",

Before: func(repositoryPath string) {
require.NoError(t, osutil.MkdirAll(filepath.Join(repositoryPath, ".git")))
require.NoError(t, os.WriteFile(filepath.Join(repositoryPath, ".git", "index"), []byte(`content`), 0700))
},

TestdataPath: filepath.Join("..", "..", "testdata"),
RepositoryPath: filepath.Join("java", "transpile"),
Language: &java.Language{},
})
})
}

0 comments on commit 45a79a7

Please sign in to comment.