blob: 72f0eab5cb41e4b04b6e220a0589dc0950509230 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package utils
import (
"errors"
"fmt"
"github.com/google/uuid"
"os"
"path/filepath"
"reflect"
"regexp"
"strings"
"testing"
)
const (
sourceDir = "sourceDir"
fileName = "file.txt"
fileContent = "content"
testDataDir = "test_data"
javaFileName = "JavaFileName.java"
emptyFileName = "emptyFile.java"
pythonExampleName = "wordcount.py"
filePermission = 0600
fullPermission = 0755
)
func TestMain(m *testing.M) {
err := setup()
if err != nil {
panic(fmt.Errorf("error during test setup: %s", err.Error()))
}
defer teardown()
m.Run()
}
func setup() error {
err := os.Mkdir(sourceDir, fullPermission)
if err != nil {
return err
}
filePath := filepath.Join(sourceDir, fileName)
err = os.WriteFile(filePath, []byte(fileContent), filePermission)
if err != nil {
return err
}
sourceJavaFilePath := filepath.Join(testDataDir, javaFileName)
javaFilePath := filepath.Join(sourceDir, javaFileName)
err = CopyFile(sourceJavaFilePath, javaFilePath)
if err != nil {
return err
}
emptyFilePath := filepath.Join(sourceDir, emptyFileName)
err = os.WriteFile(emptyFilePath, []byte(""), filePermission)
if err != nil {
return err
}
sourceWordCountPythonPath := filepath.Join(testDataDir, pythonExampleName)
wordCountPythonPath := filepath.Join(sourceDir, pythonExampleName)
err = CopyFile(sourceWordCountPythonPath, wordCountPythonPath)
return err
}
func teardown() error {
return os.RemoveAll(sourceDir)
}
func TestSpacesToEqualsOption(t *testing.T) {
type args struct {
pipelineOptions string
}
tests := []struct {
name string
args args
want string
}{
{
name: "Args is empty string",
args: args{pipelineOptions: ""},
want: "",
},
{
name: "Args with one option",
args: args{pipelineOptions: "--opt1 valOpt"},
want: "--opt1=valOpt",
},
{
name: "Args with some options",
args: args{pipelineOptions: "--opt1 valOpt --opt2 valOpt --opt3 valOpt"},
want: "--opt1=valOpt --opt2=valOpt --opt3=valOpt",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := ReplaceSpacesWithEquals(tt.args.pipelineOptions); got != tt.want {
t.Errorf("ReplaceSpacesWithEquals() = %v, want %v", got, tt.want)
}
})
}
}
func TestInitVars(t *testing.T) {
tests := []struct {
name string
want []interface{}
}{
{
name: "Create empty variables",
want: []interface{}{EmptyLine, EmptyLine, errors.New(EmptyLine), false, RegularDefinition},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, got1, got2, got3, got4 := InitVars()
variables := append([]interface{}{}, got, got1, got2, got3, got4)
if !reflect.DeepEqual(variables, tt.want) {
t.Errorf("InitVars() variables = %v, want %v", variables, tt.want)
}
})
}
}
func TestAddGraphToEndOfFile(t *testing.T) {
txtFilePath := filepath.Join(sourceDir, fileName)
txtFile, err := os.OpenFile(txtFilePath, os.O_APPEND|os.O_WRONLY, os.ModeAppend)
if err != nil {
panic(err)
}
defer txtFile.Close()
incorrectFile, err := os.Open(txtFilePath)
if err != nil {
panic(err)
}
defer incorrectFile.Close()
type args struct {
spaces string
err error
tempFile *os.File
pipelineName string
}
type fields struct {
fileContent string
filePath string
}
tests := []struct {
name string
args args
fields fields
wantErr bool
}{
{
name: "Add graph to the end of an existing file",
args: args{
spaces: "",
err: nil,
tempFile: txtFile,
pipelineName: uuid.New().String(),
},
fields: fields{
fileContent: fileContent,
filePath: txtFilePath,
},
wantErr: false,
},
{
name: "Error during write data to file",
args: args{
spaces: "",
err: nil,
tempFile: incorrectFile,
pipelineName: uuid.New().String(),
},
fields: fields{
fileContent: fileContent,
filePath: txtFilePath,
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
AddGraphToEndOfFile(tt.args.spaces, tt.args.err, tt.args.tempFile, tt.args.pipelineName)
data, err := os.ReadFile(tt.fields.filePath)
if err != nil {
t.Errorf("AddGraphToEndOfFile() error during reading from a file = %v", err)
}
graphCode := fmt.Sprintf(pythonGraphCodePattern, tt.args.pipelineName, GraphFileName)
graphCodeWithIndentation := strings.ReplaceAll(graphCode, indentationReplacement, tt.args.spaces)
fileContentWithGraph := fileContent + "\n" + graphCodeWithIndentation
if (string(data) != fileContentWithGraph) != tt.wantErr {
t.Error("AddGraphToEndOfFile() wrong graph addition")
}
})
}
}
func TestGetPublicClassName(t *testing.T) {
javaPublicClassNamePattern := "public class (.*?) [{|implements(.*)]"
type args struct {
filePath string
pattern string
}
tests := []struct {
name string
args args
want string
wantErr bool
}{
{
name: "Get public class name from existing java file",
args: args{
filePath: filepath.Join(sourceDir, javaFileName),
pattern: javaPublicClassNamePattern,
},
want: "MinimalWordCount",
wantErr: false,
},
{
name: "Get public class name from empty file",
args: args{
filePath: filepath.Join(sourceDir, emptyFileName),
pattern: javaPublicClassNamePattern,
},
want: "",
wantErr: true,
},
{
name: "Get public class name from non-existent file",
args: args{
filePath: filepath.Join(sourceDir, "file1.java"),
pattern: javaPublicClassNamePattern,
},
want: "",
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := GetPublicClassName(tt.args.filePath, tt.args.pattern)
if (err != nil) != tt.wantErr {
t.Errorf("GetPublicClassName() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("GetPublicClassName() got = %v, want %v", got, tt.want)
}
})
}
}
func TestAddNewLine(t *testing.T) {
javaFile, err := os.OpenFile(filepath.Join(sourceDir, javaFileName), os.O_APPEND|os.O_WRONLY, os.ModeAppend)
if err != nil {
panic(err)
}
defer javaFile.Close()
txtFile, err := os.Open(filepath.Join(sourceDir, fileName))
if err != nil {
panic(err)
}
defer txtFile.Close()
type args struct {
newLine bool
file *os.File
}
tests := []struct {
name string
args args
wantErr bool
}{
{
name: "No line added to file",
args: args{
newLine: false,
file: nil,
},
wantErr: false,
},
{
name: "Add a new line to an existing javaFile",
args: args{
newLine: true,
file: javaFile,
},
wantErr: false,
},
{
name: "Error during write data to file",
args: args{
newLine: true,
file: txtFile,
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := AddNewLine(tt.args.newLine, tt.args.file); (err != nil) != tt.wantErr {
t.Errorf("AddNewLine() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func TestProcessLine(t *testing.T) {
pipelineName := uuid.New().String()
pythonExample, err := os.OpenFile(filepath.Join(sourceDir, pythonExampleName), os.O_RDWR, fullPermission)
if err != nil {
panic(err)
}
defer pythonExample.Close()
findPipelinePattern := `^(\s*)(.+) = beam.Pipeline`
findWithPipelinePattern := `(\s*)with.+Pipeline.+as (.+):`
emptyLine := EmptyLine
type args struct {
curLine string
pipelineName *string
spaces *string
regs *[]*regexp.Regexp
tempFile *os.File
err error
}
tests := []struct {
name string
args args
want bool
wantDefType PipelineDefinitionType
wantErr bool
}{
{
name: "Empty current line",
args: args{
curLine: "",
pipelineName: &pipelineName,
spaces: &emptyLine,
regs: &[]*regexp.Regexp{
regexp.MustCompile(findPipelinePattern),
regexp.MustCompile(findWithPipelinePattern),
},
tempFile: pythonExample,
err: errors.New(EmptyLine),
},
want: false,
wantDefType: RegularDefinition,
wantErr: false,
},
{
name: "With correct line",
args: args{
curLine: "with beam.Pipeline(options=pipeline_options) as p:",
pipelineName: &pipelineName,
spaces: &emptyLine,
regs: &[]*regexp.Regexp{
regexp.MustCompile(findPipelinePattern),
regexp.MustCompile(findWithPipelinePattern),
},
tempFile: pythonExample,
err: errors.New(EmptyLine),
},
want: true,
wantDefType: RegularDefinition,
wantErr: false,
},
{
name: "With empty pipelineId",
args: args{
curLine: "with beam.Pipeline(options=pipeline_options) as p:",
pipelineName: &emptyLine,
spaces: &emptyLine,
regs: &[]*regexp.Regexp{
regexp.MustCompile(findPipelinePattern),
regexp.MustCompile(findWithPipelinePattern),
},
tempFile: pythonExample,
err: errors.New(EmptyLine),
},
want: false,
wantDefType: WithDefinition,
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, gotDefType, err := ProcessLine(tt.args.curLine, tt.args.pipelineName, tt.args.spaces, tt.args.regs, tt.args.tempFile, tt.args.err)
if (err != nil) != tt.wantErr {
t.Errorf("ProcessLine() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("ProcessLine() got = %v, want %v", got, tt.want)
}
if gotDefType != tt.wantDefType {
t.Errorf("ProcessLine() gotDefType = %v, want %v", gotDefType, tt.wantDefType)
}
})
}
}
func TestRenameSourceCodeFile(t *testing.T) {
type args struct {
filePath string
className string
}
tests := []struct {
name string
args args
wantErr bool
}{
{
name: "Rename an existing file",
args: args{
filePath: filepath.Join(sourceDir, fileName),
className: "MOCK_CLASS_NAME",
},
wantErr: false,
},
{
name: "Rename non-existent file",
args: args{
filePath: filepath.Join(sourceDir, "file1.txt"),
className: "MOCK_CLASS_NAME",
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := RenameSourceCodeFile(tt.args.filePath, tt.args.className); (err != nil) != tt.wantErr {
t.Errorf("RenameSourceCodeFile() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}