Skip to content

Commit

Permalink
make some reloaded files optional, add test
Browse files Browse the repository at this point in the history
  • Loading branch information
umputun committed Dec 9, 2023
1 parent 8eed2b3 commit 55f201a
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 22 deletions.
45 changes: 23 additions & 22 deletions app/botnew/spam.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package bot

import (
"bytes"
"context"
"fmt"
"io"
Expand Down Expand Up @@ -147,42 +148,42 @@ func (s *SpamFilter) watch(ctx context.Context) error {
return nil
}

func (s *SpamFilter) reloadSamples() error {
func (s *SpamFilter) reloadSamples() (err error) {
log.Printf("[DEBUG] reloading samples")
// open all files we need to reload
exclReader, err := os.Open(s.params.ExcludedTokensFile)
if err != nil {
return fmt.Errorf("failed to open excluded tokens file %s: %w", s.params.ExcludedTokensFile, err)
}
defer exclReader.Close()

spamReader, err := os.Open(s.params.SpamSamplesFile)
if err != nil {
return fmt.Errorf("failed to open spam samples file %s: %w", s.params.SpamSamplesFile, err)
var exclReader, spamReader, hamReader, stopWordsReader, spamDynamicReader, hamDynamicReader io.ReadCloser

// open mandatory spam and ham samples files
if spamReader, err = os.Open(s.params.SpamSamplesFile); err != nil {
return fmt.Errorf("failed to open spam samples file %q: %w", s.params.SpamSamplesFile, err)
}
defer spamReader.Close()

hamReader, err := os.Open(s.params.HamSamplesFile)
if err != nil {
return fmt.Errorf("failed to open ham samples file %s: %w", s.params.HamSamplesFile, err)
if hamReader, err = os.Open(s.params.HamSamplesFile); err != nil {
return fmt.Errorf("failed to open ham samples file %q: %w", s.params.HamSamplesFile, err)
}
defer hamReader.Close()

stopWordsReader, err := os.Open(s.params.StopWordsFile)
if err != nil {
return fmt.Errorf("failed to open stop words file %s: %w", s.params.StopWordsFile, err)
// stop-words are optional
if stopWordsReader, err = os.Open(s.params.StopWordsFile); err != nil {
stopWordsReader = io.NopCloser(bytes.NewReader([]byte("")))
}
defer stopWordsReader.Close()

spamDynamicReader, err := os.Open(s.params.SpamDynamicFile)
if err != nil {
return fmt.Errorf("failed to open spam dynamic file %s: %w", s.params.SpamDynamicFile, err)
// excluded tokens are optional
if exclReader, err = os.Open(s.params.ExcludedTokensFile); err != nil {
exclReader = io.NopCloser(bytes.NewReader([]byte("")))
}
defer exclReader.Close()

// dynamic samples are optional
if spamDynamicReader, err = os.Open(s.params.SpamDynamicFile); err != nil {
spamDynamicReader = io.NopCloser(bytes.NewReader([]byte("")))
}
defer spamDynamicReader.Close()

hamDynamicReader, err := os.Open(s.params.HamDynamicFile)
if err != nil {
return fmt.Errorf("failed to open ham dynamic file %s: %w", s.params.HamDynamicFile, err)
if hamDynamicReader, err = os.Open(s.params.HamDynamicFile); err != nil {
hamDynamicReader = io.NopCloser(bytes.NewReader([]byte("")))
}
defer hamDynamicReader.Close()

Expand Down
116 changes: 116 additions & 0 deletions app/botnew/spam_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package bot

import (
"errors"
"io"
"os"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/umputun/tg-spam/app/botnew/mocks"
"github.com/umputun/tg-spam/lib"
Expand Down Expand Up @@ -41,3 +45,115 @@ func TestSpamFilter_OnMessage(t *testing.T) {
})

}

func TestSpamFilter_reloadSamples(t *testing.T) {
var osOpen = os.Open // Mock for os.Open function

// Mock os.Open
openOriginal := osOpen
defer func() { osOpen = openOriginal }()
osOpen = func(name string) (*os.File, error) {
if name == "fail" {
return nil, errors.New("open error")
}
if name == "notfound" {
return nil, os.ErrNotExist
}
return os.Open(os.DevNull) // Open a harmless file for other cases
}

mockDirector := &mocks.DetectorMock{
LoadSamplesFunc: func(exclReader io.Reader, spamReaders []io.Reader, hamReaders []io.Reader) (lib.LoadResult, error) {
return lib.LoadResult{}, nil
},
LoadStopWordsFunc: func(readers ...io.Reader) (lib.LoadResult, error) {
return lib.LoadResult{}, nil
},
}

s := NewSpamFilter(mockDirector, SpamParams{
SpamSamplesFile: "/dev/null",
HamSamplesFile: "/dev/null",
StopWordsFile: "optional",
ExcludedTokensFile: "optional",
SpamDynamicFile: "optional",
HamDynamicFile: "optional",
})

tests := []struct {
name string
modify func()
expectedErr error
}{
{
name: "Successful execution",
modify: func() {},
expectedErr: nil,
},
{
name: "Spam samples file open failure",
modify: func() {
s.params.SpamSamplesFile = "fail"
},
expectedErr: errors.New("failed to open spam samples file \"fail\": open fail: no such file or directory"),
},
{
name: "Ham samples file open failure",
modify: func() {
s.params.HamSamplesFile = "fail"
},
expectedErr: errors.New("failed to open ham samples file \"fail\": open fail: no such file or directory"),
},
{
name: "Stop words file not found",
modify: func() {
s.params.StopWordsFile = "notfound"
},
expectedErr: nil,
},
{
name: "Excluded tokens file not found",
modify: func() {
s.params.ExcludedTokensFile = "notfound"
},
expectedErr: nil,
},
{
name: "Spam dynamic file not found",
modify: func() {
s.params.SpamDynamicFile = "notfound"
},
expectedErr: nil,
},
{
name: "Ham dynamic file not found",
modify: func() {
s.params.HamDynamicFile = "notfound"
},
expectedErr: nil,
},
}

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
// Reset to default values before each test
s = NewSpamFilter(mockDirector, SpamParams{
SpamSamplesFile: "/dev/null",
HamSamplesFile: "/dev/null",
StopWordsFile: "optional",
ExcludedTokensFile: "optional",
SpamDynamicFile: "optional",
HamDynamicFile: "optional",
})
tc.modify()
err := s.reloadSamples()

if tc.expectedErr != nil {
require.Error(t, err)
assert.Equal(t, tc.expectedErr.Error(), err.Error())
} else {
assert.NoError(t, err)
}
})
}
}

0 comments on commit 55f201a

Please sign in to comment.