probo/store/file/file_test.go

299 lines
8.4 KiB
Go
Raw Normal View History

2023-06-28 17:21:59 +02:00
package file
import (
"fmt"
"os"
"reflect"
"testing"
"git.andreafazzi.eu/andrea/probo/client"
2023-07-10 13:23:46 +02:00
"git.andreafazzi.eu/andrea/probo/hasher/sha256"
2023-06-28 17:21:59 +02:00
"git.andreafazzi.eu/andrea/probo/models"
2023-07-10 13:23:46 +02:00
"git.andreafazzi.eu/andrea/probo/store/memory"
2023-06-28 17:21:59 +02:00
"github.com/remogatto/prettytest"
)
2023-10-07 11:43:12 +02:00
var testdataDir = "./testdata"
type quizTestSuite struct {
2023-06-28 17:21:59 +02:00
prettytest.Suite
}
func TestRunner(t *testing.T) {
prettytest.Run(
t,
2023-10-07 11:43:12 +02:00
new(quizTestSuite),
new(collectionTestSuite),
2023-06-28 17:21:59 +02:00
)
}
2023-10-07 11:43:12 +02:00
func (t *quizTestSuite) TestQuizFromMarkdown() {
2023-06-28 17:21:59 +02:00
markdown := `Question text (1).
Question text (2).
2023-10-02 12:55:03 +02:00
Question text with #tag1 #tag2 (3).
2023-06-28 17:21:59 +02:00
* Answer 1
* Answer 2
* Answer 3
* Answer 4`
expectedQuiz := &client.Quiz{
2023-10-02 12:55:03 +02:00
Question: &client.Question{Text: "Question text (1).\n\nQuestion text (2).\n\nQuestion text with #tag1 #tag2 (3)."},
2023-06-28 17:21:59 +02:00
Answers: []*client.Answer{
{Text: "Answer 1", Correct: true},
{Text: "Answer 2", Correct: false},
{Text: "Answer 3", Correct: false},
{Text: "Answer 4", Correct: false},
},
}
2023-09-22 10:29:10 +02:00
quiz, _, err := QuizFromMarkdown(markdown)
2023-06-28 17:21:59 +02:00
t.Nil(err, fmt.Sprintf("Quiz should be parsed without errors: %v", err))
if !t.Failed() {
t.True(reflect.DeepEqual(quiz, expectedQuiz), fmt.Sprintf("Expected %+v, got %+v", expectedQuiz, quiz))
2023-10-02 12:55:03 +02:00
2023-06-28 17:21:59 +02:00
}
}
2023-10-07 11:43:12 +02:00
func (t *quizTestSuite) TestReadAllQuizzes() {
store, err := NewFileProboCollectorStore("./testdata/")
2023-06-28 17:21:59 +02:00
t.True(err == nil, fmt.Sprintf("A file store should be initialized without problems but an error occurred: %v", err))
if !t.Failed() {
result, err := store.ReadAllQuizzes()
t.True(err == nil, fmt.Sprintf("Quizzes should be returned without errors: %v", err))
if !t.Failed() {
t.Equal(
2023-09-22 10:29:10 +02:00
4,
2023-06-28 17:21:59 +02:00
len(result),
2023-09-22 10:29:10 +02:00
fmt.Sprintf("The store contains 5 files but only 4 should be parsed (duplicated quiz). Total of parsed quizzes are instead %v", len(result)),
2023-06-28 17:21:59 +02:00
)
}
}
}
2023-10-07 11:43:12 +02:00
func (t *quizTestSuite) TestMarkdownFromQuiz() {
2023-07-10 13:23:46 +02:00
store := memory.NewMemoryProboCollectorStore(sha256.NewDefault256Hasher(sha256.DefaultSHA256HashingFn))
quiz, err := store.CreateQuiz(
2023-06-28 17:21:59 +02:00
&client.CreateUpdateQuizRequest{
Quiz: &client.Quiz{
Question: &client.Question{Text: "Newly created question text."},
Answers: []*client.Answer{
{Text: "Answer 1", Correct: true},
{Text: "Answer 2", Correct: false},
{Text: "Answer 3", Correct: false},
{Text: "Answer 4", Correct: false},
},
},
})
2023-07-10 13:23:46 +02:00
md, err := MarkdownFromQuiz(quiz)
t.Nil(err, "Conversion to markdown should not raise an error")
if !t.Failed() {
t.Equal(`Newly created question text.
* Answer 1
* Answer 2
* Answer 3
* Answer 4
`, md)
}
}
2023-06-28 17:21:59 +02:00
2023-10-07 11:43:12 +02:00
func (t *quizTestSuite) TestCreateQuiz() {
store, err := NewFileProboCollectorStore(testdataDir)
2023-06-28 17:21:59 +02:00
2023-07-10 13:23:46 +02:00
t.True(err == nil, fmt.Sprintf("A file store should be initialized without problems but an error occurred: %v", err))
2023-06-28 17:21:59 +02:00
if !t.Failed() {
2023-07-10 13:23:46 +02:00
clientQuiz := &client.Quiz{
Question: &client.Question{Text: "Newly created question text."},
Answers: []*client.Answer{
{Text: "Answer 1", Correct: true},
{Text: "Answer 2", Correct: false},
{Text: "Answer 3", Correct: false},
{Text: "Answer 4", Correct: false},
},
}
quiz, err := store.CreateQuiz(
&client.CreateUpdateQuizRequest{
Quiz: clientQuiz,
},
)
t.Nil(err, fmt.Sprintf("An error was raised when saving the quiz on disk: %v", err))
if !t.Failed() {
2023-10-07 11:43:12 +02:00
path, err := store.GetQuizPath(quiz)
2023-07-10 13:23:46 +02:00
t.Nil(err, "GetPath should not raise an error.")
if !t.Failed() {
exists, err := os.Stat(path)
t.Nil(err, "Stat should not return an error")
if !t.Failed() {
t.True(exists != nil, "The new quiz file was not created.")
if !t.Failed() {
2023-09-22 10:29:10 +02:00
quizFromDisk, _, err := readQuizFromDisk(path)
2023-07-10 13:23:46 +02:00
t.Nil(err, "Quiz should be read from disk without errors.")
if !t.Failed() {
t.True(reflect.DeepEqual(quizFromDisk, clientQuiz), "Quiz read from disk and stored in memory should be equal.")
err := os.Remove(path)
t.Nil(err, "Test file should be removed without errors.")
}
}
}
}
}
2023-06-28 17:21:59 +02:00
}
}
2023-10-07 11:43:12 +02:00
func (t *quizTestSuite) TestDeleteQuiz() {
store, err := NewFileProboCollectorStore(testdataDir)
2023-09-01 11:48:09 +02:00
t.True(err == nil, fmt.Sprintf("A file store should be initialized without problems but an error occurred: %v", err))
if !t.Failed() {
quiz, err := createQuizOnDisk(store, &client.CreateUpdateQuizRequest{
Quiz: &client.Quiz{
Question: &client.Question{Text: "This quiz should be deleted."},
Answers: []*client.Answer{
{Text: "Answer 1", Correct: true},
{Text: "Answer 2", Correct: false},
{Text: "Answer 3", Correct: false},
{Text: "Answer 4", Correct: false},
},
},
})
t.Nil(err, "The quiz to be deleted should be created without issue")
2023-10-07 11:43:12 +02:00
path, err := store.GetQuizPath(quiz)
2023-09-01 11:48:09 +02:00
t.True(path != "", "Quiz path should be obtained without errors")
if !t.Failed() {
deletedQuiz, err := store.DeleteQuiz(&client.DeleteQuizRequest{ID: quiz.ID})
t.Nil(err, fmt.Sprintf("Quiz should be deleted without errors: %v", err))
t.True(reflect.DeepEqual(quiz, deletedQuiz), "Quiz should be updateEd.")
}
}
}
2023-10-07 11:43:12 +02:00
func (t *quizTestSuite) TestUpdateQuiz() {
store, err := NewFileProboCollectorStore(testdataDir)
t.True(err == nil, fmt.Sprintf("A file store should be initialized without problems but an error occurred: %v", err))
if !t.Failed() {
quiz, err := createQuizOnDisk(store, &client.CreateUpdateQuizRequest{
Quiz: &client.Quiz{
Question: &client.Question{Text: "Newly created question text."},
Answers: []*client.Answer{
{Text: "Answer 1", Correct: true},
{Text: "Answer 2", Correct: false},
{Text: "Answer 3", Correct: false},
{Text: "Answer 4", Correct: false},
},
},
})
2023-07-07 18:15:09 +02:00
t.Nil(err, "The quiz to be updated should be created without issue")
if !t.Failed() {
2023-07-10 13:23:46 +02:00
clientQuiz := &client.Quiz{
2023-10-02 12:55:03 +02:00
Question: &client.Question{Text: "Updated question text with #tag."},
2023-07-10 13:23:46 +02:00
Answers: []*client.Answer{
{Text: "Answer 1", Correct: true},
{Text: "Answer 2", Correct: false},
{Text: "Answer 3", Correct: false},
{Text: "Answer 4", Correct: false},
},
}
updatedQuiz, err := store.UpdateQuiz(
&client.CreateUpdateQuizRequest{
2023-07-10 13:23:46 +02:00
Quiz: clientQuiz,
}, quiz.ID)
2023-07-10 13:23:46 +02:00
t.Nil(err, fmt.Sprintf("Quiz should be updated without errors: %v", err))
2023-09-22 10:29:10 +02:00
t.Equal(updatedQuiz.ID, quiz.ID, fmt.Sprintf("IDs should remain the same after an update: updated ID %v original ID %v", updatedQuiz.ID, quiz.ID))
2023-10-02 12:55:03 +02:00
t.True(len(updatedQuiz.Tags) == 1, "Length of tags array should be 1")
2023-07-10 13:23:46 +02:00
if !t.Failed() {
2023-10-07 11:43:12 +02:00
path, err := store.GetQuizPath(updatedQuiz)
2023-07-10 13:23:46 +02:00
if !t.Failed() {
t.Nil(err, "GetPath should not raise an error.")
if !t.Failed() {
2023-09-22 10:29:10 +02:00
quizFromDisk, _, err := readQuizFromDisk(path)
2023-07-10 13:23:46 +02:00
t.Nil(err, "Quiz should be read from disk without errors.")
if !t.Failed() {
t.True(reflect.DeepEqual(clientQuiz, quizFromDisk), "Quiz should be updated.")
err := os.Remove(path)
t.Nil(err, "Stat should not return an error")
}
}
}
}
}
}
2023-07-07 18:15:09 +02:00
}
2023-10-07 11:43:12 +02:00
func (t *quizTestSuite) TestReadMetaHeaderFromFile() {
store, err := NewFileProboCollectorStore(testdataDir)
2023-09-22 10:29:10 +02:00
t.True(err == nil, fmt.Sprintf("A file store should be initialized without problems but an error occurred: %v", err))
meta, err := store.ReadMetaHeaderFromFile("quiz_4.md")
t.True(err == nil, fmt.Sprintf("An error occurred: %v", err))
if !t.Failed() {
t.True(meta.ID != "")
t.True(meta.CreatedAt.String() != "")
}
}
2023-10-07 11:43:12 +02:00
func (t *quizTestSuite) TestWriteMetaHeaderToFile() {
store, err := NewFileProboCollectorStore(testdataDir)
2023-09-22 10:29:10 +02:00
t.True(err == nil, fmt.Sprintf("A file store should be initialized without problems but an error occurred: %v", err))
if !t.Failed() {
meta, err := store.ReadMetaHeaderFromFile("quiz_5.md")
2023-10-02 12:55:03 +02:00
t.True(err == nil, fmt.Sprintf("Reading the header returns the following error: %v", err))
2023-09-22 10:29:10 +02:00
if !t.Failed() {
t.True(meta != nil, "Meta header should not be nil")
if !t.Failed() {
t.True(meta.ID != "", "ID should not be empty")
if !t.Failed() {
_, err = store.removeMetaFromFile("quiz_5.md")
t.True(err == nil)
}
}
}
}
}
func createQuizOnDisk(store *FileProboCollectorStore, req *client.CreateUpdateQuizRequest) (*models.Quiz, error) {
return store.CreateQuiz(req)
}
2023-09-22 10:29:10 +02:00
func readQuizFromDisk(path string) (*client.Quiz, *models.Meta, error) {
2023-07-10 13:23:46 +02:00
content, err := os.ReadFile(path)
if err != nil {
2023-09-22 10:29:10 +02:00
return nil, nil, err
2023-07-10 13:23:46 +02:00
}
return QuizFromMarkdown(string(content))
}
2023-06-28 17:21:59 +02:00
func testsAreEqual(got, want []*models.Quiz) bool {
return reflect.DeepEqual(got, want)
}