Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add test bottlenecks due to DI #4

Merged
merged 1 commit into from
Mar 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 84 additions & 17 deletions cmd/example/main.go
Original file line number Diff line number Diff line change
@@ -1,34 +1,101 @@
package main

import (
"bufio"
"flag"
"fmt"

lab2 "github.com/roman-mazur/architecture-lab-2"
lab2 "github.com/KPI-kujo205/2course-golang-lab2"
"io"
"os"
"strings"
)

var (
inputExpression = flag.String("e", "", "Expression to compute")
inputExpresionFile = flag.String("f", "", "Path to input expression file")
outputFile = flag.String("o", "", "Path to output file")
inputExpression = flag.String("e", "", "Expression to compute")
inputExpressionFile = flag.String("f", "", "Path to input expression file")
outputFile = flag.String("o", "", "Path to output file")
)

func main() {
flag.Parse()

if *inputExpression != "" && *inputExpresionFile != "" {
panic("Only one flag available: -e or -f")
if err := validateFlags(); err != nil {
exitWithError(err)
}

input, err := getInputReader()
if err != nil {
exitWithError(err)
}
defer func() {
if closer, ok := input.(io.Closer); ok {
if err := closer.Close(); err != nil {
fmt.Fprintf(os.Stderr, "error closing input: %v\n", err)
}
}
}()

output, err := getOutputWriter()
if err != nil {
exitWithError(err)
}
defer func() {
if closer, ok := output.(io.Closer); ok {
if err := closer.Close(); err != nil {
fmt.Fprintf(os.Stderr, "error closing output: %v\n", err)
}
}
}()

fmt.Println(*inputExpression, *inputExpresionFile, *outputFile) // test
// TODO: Change this to accept input from the command line arguments as described in the task and
// output the results using the ComputeHandler instance.
// handler := &lab2.ComputeHandler{
// Input: {construct io.Reader according the command line parameters},
// Output: {construct io.Writer according the command line parameters},
// }
// err := handler.Compute()
handler := &lab2.ComputeHandler{
Input: input,
Output: output,
}
if err := handler.Compute(); err != nil {
exitWithError(err)
}

if writer, ok := output.(*bufio.Writer); ok {
if err := writer.Flush(); err != nil {
fmt.Fprintln(os.Stderr, "error flushing output writer:", err)
}
}
}

func validateFlags() error {
if *inputExpression == "" && *inputExpressionFile == "" {
return fmt.Errorf("input expression or input file path must be provided")
} else if *inputExpression != "" && *inputExpressionFile != "" {
return fmt.Errorf("only one flag available: -e or -f")
}
return nil
}

func getInputReader() (io.Reader, error) {
if *inputExpression != "" {
return strings.NewReader(*inputExpression), nil
} else if *inputExpressionFile != "" {
file, err := os.Open(*inputExpressionFile)
if err != nil {
return nil, fmt.Errorf("error opening input file: %v", err)
}
return bufio.NewReader(file), nil
}
return nil, nil
}

func getOutputWriter() (io.Writer, error) {
if *outputFile != "" {
file, err := os.Create(*outputFile)
if err != nil {
return nil, fmt.Errorf("error creating output file: %v", err)
}
return bufio.NewWriter(file), nil
}
return os.Stdout, nil
}

res, _ := lab2.PrefixToPostfix("+ 2 2")
fmt.Println(res)
func exitWithError(err error) {
fmt.Fprintln(os.Stderr, "error:", err)
os.Exit(1)
}
10 changes: 2 additions & 8 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
// TODO: Переіменуйте на власний модуль.
module github.com/roman-mazur/architecture-lab-2
module github.com/KPI-kujo205/2course-golang-lab2

go 1.22

// TODO: Змініть, якщо вам потрібно використовувати іншу бібліотеку.
require github.com/stretchr/testify v1.8.4
require gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rogpeppe/go-internal v1.12.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
8 changes: 0 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,26 +1,18 @@
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
36 changes: 32 additions & 4 deletions handler.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,40 @@
package lab2

// ComputeHandler should be constructed with input io.Reader and output io.Writer.
// Its Compute() method should read the expression from input and write the computed result to the output.
import (
"bytes"
"fmt"
"io"
"strings"
)

// ComputeHandler is constructed with input io.Reader and output io.Writer.
// Its Compute() method reads the expression from input and write the computed result to the output.
type ComputeHandler struct {
// TODO: Add necessary fields.
Input io.Reader
Output io.Writer
}

func (ch *ComputeHandler) Compute() error {
// TODO: Implement.
buffer := new(bytes.Buffer)
_, err := buffer.ReadFrom(ch.Input)
if err != nil {
return err
}

lines := strings.Split(buffer.String(), "\n")
for _, line := range lines {
inputString := strings.TrimSpace(line)

postfixExpr, err := PrefixToPostfix(inputString)
if err != nil {
return err
}

_, err = fmt.Fprintln(ch.Output, postfixExpr)
if err != nil {
return err
}
}

return nil
}
48 changes: 48 additions & 0 deletions handler_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package lab2

import (
"bytes"
"gopkg.in/check.v1"
"strings"
)

type ComputeHandlerSuite struct{}

var _ = check.Suite(&ComputeHandlerSuite{})

func (s *ComputeHandlerSuite) TestValidExpression(c *check.C) {
validExpression := "+ + 1 * 2 3 9"
expectedExpression := "1 2 3 * + 9 +\n"
outputBuffer := bytes.NewBuffer(nil)
handler := ComputeHandler{
Input: strings.NewReader(validExpression),
Output: outputBuffer,
}

err := handler.Compute()
c.Assert(err, check.IsNil)
c.Assert(outputBuffer.String(), check.Equals, expectedExpression)
}

func (s *ComputeHandlerSuite) TestInvalidCharactersInput(c *check.C) {
invalidCharactersInput := "wrong characters"
outputBuffer := bytes.NewBuffer(nil)
handler := ComputeHandler{
Input: strings.NewReader(invalidCharactersInput),
Output: outputBuffer,
}

err := handler.Compute()
c.Assert(err, check.NotNil)
}

func (s *ComputeHandlerSuite) TestInvalidExpression(c *check.C) {
outputBuffer := bytes.NewBuffer(nil)
handler := ComputeHandler{
Input: strings.NewReader("+ + 1"),
Output: outputBuffer,
}
err := handler.Compute()

c.Assert(err, check.NotNil)
}
Empty file removed implementation
Empty file.
14 changes: 8 additions & 6 deletions implementation.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,28 @@ package lab2

import (
"errors"
"strings"
"regexp"
"strings"
)

// PrefixToPostfix function takes an input string representing a prefix expression and converts it to a postfix expression.
// The function splits the input string into tokens and then iterates through those tokens in reverse order.
// If the token is an operand, it is added to the stack.
// If the token is an operator, it pops two operands from the stack, applies the operator to those operands, and pushes the result back onto the stack.
// At the end of the process, only one element remains on the stack - the result of the postfix expression.
func PrefixToPostfix(input string) (string, error) {
trimmedInput := strings.TrimSpace(input)
if trimmedInput == "" {
return "", errors.New("input string contains only whitespace characters")
}

stack := []string{}
var stack []string
tokens := strings.Fields(input)

for i := len(tokens) - 1; i >= 0; i-- {
token := tokens[i]


if(!isNumber(token) && !isOperator(token[0])){
if !isNumber(token) && !isOperator(token[0]) {
return "", errors.New("invalid character")
}

Expand All @@ -41,7 +45,6 @@ func PrefixToPostfix(input string) (string, error) {
return stack[0], nil
}


func isNumber(input string) bool {
pattern := `^[+-]?\d*\.?\d+$`
re := regexp.MustCompile(pattern)
Expand All @@ -52,4 +55,3 @@ func isNumber(input string) bool {
func isOperator(ch byte) bool {
return ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '^'
}

32 changes: 26 additions & 6 deletions implementation_test.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package lab2

import (
"testing"
"fmt"
. "gopkg.in/check.v1"
"testing"
)

func Test(t *testing.T) { TestingT(t) }
Expand All @@ -16,15 +17,12 @@ func (s *MySuite) TestPrefixToPostfix(c *C) {
prefixExpression string
expectedResult string
}{
{"+ 5 5","5 5 +"},
{"+ 5 5", "5 5 +"},
{"+ + 1 * 2 3 9", "1 2 3 * + 9 +"},
{"+ 2 4", "2 4 +"},
{"* - 3 4 + 3 4", "3 4 - 3 4 + *"},
{"/ - - / 8 3 1 + - 3 2 4 4", "8 3 / 1 - 3 2 - 4 + - 4 /"},
{"+ + + - - + - * 32 42 / 4 12 3 12 44 5 90 12","32 42 * 4 12 / - 3 + 12 - 44 - 5 + 90 + 12 +"},

// {"",""}, ERROR CASE
// {"% 3 3","3 3 %"}, ERROR CASE
{"+ + + - - + - * 32 42 / 4 12 3 12 44 5 90 12", "32 42 * 4 12 / - 3 + 12 - 44 - 5 + 90 + 12 +"},
}

for _, tc := range testCases {
Expand All @@ -34,3 +32,25 @@ func (s *MySuite) TestPrefixToPostfix(c *C) {
}
}

func (s *MySuite) TestPrefixToPostfixWithEmptyLine(c *C) {
emptyInput := ""
expectedError := "input string contains only whitespace characters"

_, err := PrefixToPostfix(emptyInput)
c.Assert(err, ErrorMatches, expectedError)
}

func (s *MySuite) TestPrefixToPostfixWithInvalidCharacter(c *C) {
invalidCharacter := "+ ! 1 * 2 3 9"
expectedError := "invalid character"

_, err := PrefixToPostfix(invalidCharacter)
c.Assert(err, ErrorMatches, expectedError)
}

func ExamplePrefixToPostfix() {
expression := "+ 5 5"
postfix, _ := PrefixToPostfix(expression)
fmt.Println(postfix)
// Output: 5 5 +
}
Loading