Skip to content

Commit

Permalink
feat: add file parsing test
Browse files Browse the repository at this point in the history
  • Loading branch information
nedpals committed Feb 2, 2024
1 parent 58fd022 commit b9b37f7
Show file tree
Hide file tree
Showing 2 changed files with 271 additions and 9 deletions.
21 changes: 12 additions & 9 deletions errgoengine.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func (e *ErrgoEngine) Analyze(workingPath, msg string) (*CompiledErrorTemplate,
contextData.TraceStack = template.ExtractStackTrace(contextData)

// open contents of the extracted stack file locations
if err := ParseFromStackTrace(contextData, template, e.FS); err != nil {
if err := ParseFromStackTrace(contextData, template.Language, e.FS); err != nil {
// return error template for bugbuddy to handle
// incomplete error messages
return template, nil, err
Expand Down Expand Up @@ -131,12 +131,14 @@ func (e *ErrgoEngine) Translate(template *CompiledErrorTemplate, contextData *Co
return expGen.mainExp.String(), output
}

func ParseFromStackTrace(contextData *ContextData, template *CompiledErrorTemplate, files *MultiReadFileFS) error {
func ParseFromStackTrace(contextData *ContextData, defaultLanguage *Language, files fs.ReadFileFS) error {
parser := sitter.NewParser()
analyzer := &SymbolAnalyzer{ContextData: contextData}

for _, node := range contextData.TraceStack {
contents, err := files.ReadFile(node.DocumentPath)
path := node.DocumentPath

contents, err := files.ReadFile(path)
if err != nil {
// return err
// Do not return error if file not found
Expand All @@ -148,24 +150,25 @@ func ParseFromStackTrace(contextData *ContextData, template *CompiledErrorTempla
continue
}

var selectedLanguage *Language
existingDoc, docExists := contextData.Documents[node.DocumentPath]
// check if document already exists
existingDoc, docExists := contextData.Documents[path]

// check matched languages
selectedLanguage := defaultLanguage
if docExists {
selectedLanguage = existingDoc.Language
} else {
selectedLanguage = template.Language
if !selectedLanguage.MatchPath(node.DocumentPath) {
return fmt.Errorf("no language found for %s", node.DocumentPath)
if !selectedLanguage.MatchPath(path) {
return fmt.Errorf("no language found for %s", path)
}

// compile language first (if not yet)
selectedLanguage.Compile()
}

// do semantic analysis
doc, err := ParseDocument(node.DocumentPath, bytes.NewReader(contents), parser, selectedLanguage, existingDoc)
contentReader := bytes.NewReader(contents)
doc, err := ParseDocument(path, contentReader, parser, selectedLanguage, existingDoc)
if err != nil {
return err
}
Expand Down
259 changes: 259 additions & 0 deletions errgoengine_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
package errgoengine_test

import (
"testing"
"testing/fstest"

lib "github.com/nedpals/errgoengine"
"github.com/nedpals/errgoengine/languages/java"
"github.com/nedpals/errgoengine/languages/python"
)

func Setup(lang *lib.Language, workingPath string, targetPos lib.Position) *lib.ContextData {
// setup context data
contextData := lib.NewContextData(lib.NewEmptyStore(), ".")
contextData.Analyzer = lang.AnalyzerFactory(contextData)
contextData.TraceStack = lib.TraceStack{}

// add dummy stack trace item
contextData.TraceStack.Add("main", lib.Location{
DocumentPath: workingPath,
StartPos: targetPos,
EndPos: targetPos,
})

return contextData
}

func TestParseFromStackTrace(t *testing.T) {
t.Run("Simple/Java", func(t *testing.T) {
currentLang := java.Language
contextData := Setup(currentLang, "Main.java", lib.Position{Line: 4})
files := fstest.MapFS{
"Main.java": &fstest.MapFile{
Data: []byte(`public class Main {
public static void main(String[] args) {
int a = 1;
System.out.println(a/0);
}
}`),
},
}

err := lib.ParseFromStackTrace(contextData, currentLang, files)
if err != nil {
t.Fatal(err)
}

// check if the document is parsed
doc, ok := contextData.Documents["Main.java"]
if !ok {
t.Error("Main.java document not found")
}

// check if doc language is same as currentLang
if doc.Language == nil {
t.Error("Language is nil")
}

if doc.Language != currentLang {
t.Errorf("expected language %s, got %s", currentLang.Name, doc.Language.Name)
}

// check if tree is present
if doc.Tree == nil {
t.Error("Tree is nil")
}

// check if the content is also present
if doc.Contents == "" {
t.Error("Content is empty")
}

// check if the tree is parsed
if doc.Tree.RootNode() == nil {
t.Error("Tree is not parsed")
}
})

t.Run("Simple/Python", func(t *testing.T) {
currentLang := python.Language
contextData := Setup(currentLang, "main.py", lib.Position{Line: 2})
files := fstest.MapFS{
"main.py": &fstest.MapFile{
Data: []byte(`def main():
a = 1
print(a/0)
`),
},
}

err := lib.ParseFromStackTrace(contextData, currentLang, files)
if err != nil {
t.Fatal(err)
}

// check if the document is parsed
doc, ok := contextData.Documents["main.py"]
if !ok {
t.Error("main.py document not found")
}

// check if doc language is same as currentLang
if doc.Language == nil {
t.Error("Language is nil")
}

if doc.Language != currentLang {
t.Errorf("expected language %s, got %s", currentLang.Name, doc.Language.Name)
}

// check if tree is present
if doc.Tree == nil {
t.Error("Tree is nil")
}

// check if the content is also present
if doc.Contents == "" {
t.Error("Content is empty")
}

// check if the tree is parsed
if doc.Tree.RootNode() == nil {
t.Error("Tree is not parsed")
}
})

t.Run("FileNotFound", func(t *testing.T) {
currentLang := python.Language
contextData := Setup(currentLang, "main.py", lib.Position{Line: 2})
files := fstest.MapFS{}

err := lib.ParseFromStackTrace(contextData, currentLang, files)
if err != nil {
t.Fatal(err)
}

// document should not be present
if _, ok := contextData.Documents["main.py"]; ok {
t.Error("main.py document is present")
}
})

t.Run("LanguageNotMatched", func(t *testing.T) {
currentLang := python.Language
contextData := Setup(currentLang, "main.java", lib.Position{Line: 2})
files := fstest.MapFS{
"main.java": &fstest.MapFile{
Data: []byte(`public class Main {
public static void main(String[] args) {
int a = 1;
System.out.println(a/0);
}
}`),
},
}

err := lib.ParseFromStackTrace(contextData, currentLang, files)
if err == nil {
t.Error("expected error, got nil")
}

if err.Error() != "no language found for main.java" {
t.Errorf("expected error message 'no language found for main.java', got %s", err.Error())
}

// check if the document is not parsed
if _, ok := contextData.Documents["main.java"]; ok {
t.Error("main.java document is parsed")
}
})

t.Run("ExistingDoc", func(t *testing.T) {
currentLang := python.Language
contextData := Setup(currentLang, "main.py", lib.Position{Line: 2})
files := fstest.MapFS{
"main.py": &fstest.MapFile{
Data: []byte(`def main():
a = 1
print(a/0)
`),
},
}

// parse the document first
err := lib.ParseFromStackTrace(contextData, currentLang, files)
if err != nil {
t.Fatal(err)
}

// check if the document is parsed
doc, ok := contextData.Documents["main.py"]
if !ok {
t.Error("main.py document not found")
}

// check if doc language is same as currentLang
if doc.Language == nil {
t.Error("Language is nil")
}

if doc.Language != currentLang {
t.Errorf("expected language %s, got %s", currentLang.Name, doc.Language.Name)
}

// check if tree is present
if doc.Tree == nil {
t.Error("Tree is nil")
}

// check if the content is also present
if doc.Contents == "" {
t.Error("Content is empty")
}

newFiles := fstest.MapFS{
"main.py": &fstest.MapFile{
Data: []byte(`def main():
print("Hello, World!")
`),

// change the file modification time
Mode: 0,
},
}

oldContent := doc.Contents

// parse the document again
err = lib.ParseFromStackTrace(contextData, currentLang, newFiles)
if err != nil {
t.Fatal(err)
}

// check if the document is parsed
doc, ok = contextData.Documents["main.py"]
if !ok {
t.Error("main.py document not found")
}

// check if doc language is same as currentLang
if doc.Language == nil {
t.Error("Language is nil")
}

if doc.Language != currentLang {
t.Errorf("expected language %s, got %s", currentLang.Name, doc.Language.Name)
}

// check if the content is also present
if doc.Contents == "" {
t.Error("Content is empty")
}

// check if the content is changed
if doc.Contents == oldContent {
t.Error("Content is not changed")
}
})
}

0 comments on commit b9b37f7

Please sign in to comment.