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 authored and Munsio committed Aug 28, 2024
1 parent ca03cfa commit e0abdaa
Show file tree
Hide file tree
Showing 3 changed files with 241 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
}
197 changes: 197 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,199 @@ 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{},

ExpectedError: func(err error) {
var errorMessage string
if osutil.IsWindows() {
errorMessage = "The system cannot find the file specified"
} else {
errorMessage = "no such file or directory"
}
assert.ErrorContains(t, err, errorMessage)
},
})
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{},

ExpectedError: func(err error) {
assert.ErrorContains(t, err, "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{},

ExpectedError: func(err error) {
assert.ErrorContains(t, err, "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{},

ExpectedError: func(err error) {
assert.ErrorContains(t, err, "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{},

ExpectedError: func(err error) {
assert.ErrorContains(t, err, "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{},

ExpectedError: func(err error) {
assert.ErrorContains(t, err, "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{},

ExpectedError: func(err error) {
assert.ErrorContains(t, err, "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{},

ExpectedError: func(err error) {
assert.ErrorContains(t, err, "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{},

ExpectedError: func(err error) {
assert.ErrorContains(t, err, "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 e0abdaa

Please sign in to comment.