Skip to content

Commit

Permalink
Fixed improperly merged sections and added unit tests (#134)
Browse files Browse the repository at this point in the history
* Fixed improperly merged sections, added unit tests for testable functions, and translated French comments to English.

* Add error handling for last evaluation is unknown scenario.

* Update situation_history_querier.go

remove spaces

* Update situation_history_querier.go

* Update fact_history_builder_test.go

remove \n
  • Loading branch information
Ismail731404 authored Oct 25, 2023
1 parent 01a4adb commit 1f2073c
Show file tree
Hide file tree
Showing 14 changed files with 200 additions and 82 deletions.
3 changes: 0 additions & 3 deletions internals/history/fact_history_builder.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package history

import (
"time"

sq "github.com/Masterminds/squirrel"
)

Expand Down Expand Up @@ -78,4 +76,3 @@ func (builder HistoryFactsBuilder) GetTodaysFactResultByParameters(param ParamGe
Where(sq.Expr("ts >= ?::timestamptz", todayStart)).
Where(sq.Expr("ts < ?::timestamptz", tomorrowStart))
}

99 changes: 67 additions & 32 deletions internals/history/fact_history_builder_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package history

import (
"reflect"
"testing"
"time"

Expand Down Expand Up @@ -31,7 +32,7 @@ func TestGetHistoryFacts(t *testing.T) {

func initialiseDB() (*sqlx.DB, error) {

credentials := postgres.Credentials{
credentials := postgres.Credentials{
URL: "localhost",
Port: "5432",
DbName: "postgres",
Expand All @@ -46,12 +47,12 @@ func initialiseDB() (*sqlx.DB, error) {
return db, nil
}
func TestGetByCriteria(t *testing.T) {

// Initiate DB connection
db, err := initialiseDB()

if err != nil {
t.Fatalf("Error initializing DB: %s",err)
t.Fatalf("Error initializing DB: %s", err)
}

defer db.Close()
Expand All @@ -61,53 +62,87 @@ func TestGetByCriteria(t *testing.T) {
conn: db,
}

param := ParamGetFactHistory {
FactID: 10000000,
SituationID: 10000000,
param := ParamGetFactHistory{
FactID: 10000000,
SituationID: 10000000,
SituationInstanceID: 10000000,
}

value := 44
historyItem := HistoryFactsV4{
FactID: param.FactID,
SituationID: param.SituationID,
SituationInstanceID: param.SituationInstanceID,
Ts: time.Now(),
historyItem := HistoryFactsV4{
FactID: param.FactID,
SituationID: param.SituationID,
SituationInstanceID: param.SituationInstanceID,
Ts: time.Now(),
Result: reader.Item{
Aggs: map[string]*reader.ItemAgg{
"count": {
Value: value,
Value: value,
},
},
},
}

insertedID, err := querier.Insert(historyItem)
if err != nil {
t.Fatalf("Error inserting: %s", err)
}
if insertedID <= 0 {
t.Fatalf("Invalid ID returned after insert")
}
}

insertedID, err := querier.Insert(historyItem)
if err != nil {
t.Fatalf("Error inserting: %s", err)
}
if insertedID <= 0 {
t.Fatalf("Invalid ID returned after insert")
}

defer func() {
err := querier.Delete(insertedID)
if err != nil {
t.Fatalf("Error cleaning up: %s", err)
}
}()
err := querier.Delete(insertedID)
if err != nil {
t.Fatalf("Error cleaning up: %s", err)
}
}()

results, err := querier.GetTodaysFactResultByParameters(param)
if err != nil {
t.Fatalf("Error retrieving: %s", err)
}

if len(results.Results) != 1 {
t.Fatalf("Expected 1 result, got %d and resulat : %v ", len(results.Results),results)
}
t.Fatalf("Expected 1 result, got %d and resulat : %v ", len(results.Results), results)
}

if results.Results[0].Value != int64(value) {
t.Fatalf("Retrieved ID does not match inserted ID")
}
if results.Results[0].Value != int64(value) {
t.Fatalf("Retrieved ID does not match inserted ID")
}
}

func TestGetTodaysFactResultByParameters(t *testing.T) {
builder := HistoryFactsBuilder{}

param := ParamGetFactHistory{
FactID: 123,
SituationID: 456,
SituationInstanceID: 789,
}

expectedSQL := `SELECT result, ts FROM fact_history_v5 WHERE fact_id = $1 AND situation_id = $2 AND situation_instance_id = $3 AND ts >= $4::timestamptz AND ts < $5::timestamptz`

todayStart, tomorrowStart := getTodayTimeRange()

expectedArgs := []interface{}{
param.FactID,
param.SituationID,
param.SituationInstanceID,
todayStart,
tomorrowStart,
}

sql, args, err := builder.GetTodaysFactResultByParameters(param).ToSql()
if err != nil {
t.Fatalf("Failed to build SQL: %v", err)
}

if expectedSQL != sql {
t.Errorf("Expected SQL to be %s but got %s", expectedSQL, sql)
}

if !reflect.DeepEqual(expectedArgs, args) {
t.Errorf("Expected args to be %v, but got %v", expectedArgs, args)
}
}
58 changes: 28 additions & 30 deletions internals/history/fact_history_querier.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ type GetFactHistory struct {
}

type FactResult struct {
Value int64 `json:"value"`
Time time.Duration `json:"time"`
Value int64 `json:"value"`
Time time.Duration `json:"time"`
}

type ParamGetFactHistory struct {
Expand Down Expand Up @@ -117,7 +117,6 @@ func (querier HistoryFactsQuerier) ExecDelete(builder sq.DeleteBuilder) error {
return nil
}


func (querier HistoryFactsQuerier) QueryReturning(builder sq.InsertBuilder) (int64, error) {
rows, err := builder.RunWith(querier.conn.DB).Query()
if err != nil {
Expand Down Expand Up @@ -201,30 +200,30 @@ func (querier HistoryFactsQuerier) scanFirst(rows *sql.Rows) (HistoryFactsV4, er
}

func (querier *HistoryFactsQuerier) QueryGetSpecificFields(builder sq.SelectBuilder) (GetFactHistory, error) {
rows, err := builder.RunWith(querier.conn).Query()
if err != nil {
return GetFactHistory{}, err
}
defer rows.Close()

var results []FactResult

for rows.Next() {
var resultBytes []byte
var ts time.Time
err = rows.Scan(&resultBytes, &ts)
if err != nil {
return GetFactHistory{}, err
}

var parsedResult map[string]map[string]map[string]int64
err = json.Unmarshal(resultBytes, &parsedResult)
if err != nil {
return GetFactHistory{}, err
}

duration := time.Duration(ts.Hour())*time.Hour + time.Duration(ts.Minute())*time.Minute + time.Duration(ts.Second())*time.Second
factRes := FactResult{Time: duration}
rows, err := builder.RunWith(querier.conn).Query()
if err != nil {
return GetFactHistory{}, err
}
defer rows.Close()

var results []FactResult

for rows.Next() {
var resultBytes []byte
var ts time.Time
err = rows.Scan(&resultBytes, &ts)
if err != nil {
return GetFactHistory{}, err
}

var parsedResult map[string]map[string]map[string]int64
err = json.Unmarshal(resultBytes, &parsedResult)
if err != nil {
return GetFactHistory{}, err
}

duration := time.Duration(ts.Hour())*time.Hour + time.Duration(ts.Minute())*time.Minute + time.Duration(ts.Second())*time.Second
factRes := FactResult{Time: duration}

if aggs, ok := parsedResult["aggs"]; ok {
for key := range aggs {
Expand All @@ -239,12 +238,11 @@ func (querier *HistoryFactsQuerier) QueryGetSpecificFields(builder sq.SelectBuil
}
}
results = append(results, factRes)
}
}

return GetFactHistory{Results: results}, nil
return GetFactHistory{Results: results}, nil
}


func (querier HistoryFactsQuerier) GetTodaysFactResultByParameters(param ParamGetFactHistory) (GetFactHistory, error) {
builder := querier.Builder.GetTodaysFactResultByParameters(param)
return querier.QueryGetSpecificFields(builder)
Expand Down
4 changes: 2 additions & 2 deletions internals/history/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (

sq "github.com/Masterminds/squirrel"
"github.com/jmoiron/sqlx"
"github.com/myrteametrics/myrtea-engine-api/v5/internals/explainer/issues"
"github.com/myrteametrics/myrtea-engine-api/v5/internals/explainer/draft"
"github.com/myrteametrics/myrtea-engine-api/v5/internals/explainer/issues"
)

var (
Expand Down Expand Up @@ -123,7 +123,7 @@ func (service HistoryService) GetHistoryFactsFromSituationIds(historySituationsI

func (service HistoryService) PurgeHistory(options GetHistorySituationsOptions) error {
return service.deleteHistoryPurge(
service.HistorySituationsQuerier.Builder.GetHistorySituationsIdsBase(options), options ,
service.HistorySituationsQuerier.Builder.GetHistorySituationsIdsBase(options), options,
)
}

Expand Down
25 changes: 25 additions & 0 deletions internals/history/situation_history_builder_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package history

import (
"reflect"
"testing"
"time"
)
Expand Down Expand Up @@ -78,3 +79,27 @@ func TestGetHistorySituationsDetails(t *testing.T) {
t.Fail()
t.Log(builder.ToSql())
}

func TestGetLatestHistorySituation(t *testing.T) {
builder := HistorySituationsBuilder{}

expectedSQL := "SELECT ts, metadatas FROM situation_history_v5 WHERE situation_id = $1 AND situation_instance_id = $2 AND ts >= $3::timestamptz ORDER BY ts DESC LIMIT 1"
expectedArgs := []interface{}{
int64(1),
int64(12345678),
getStartDate30DaysAgo(),
}

sql, args, err := builder.GetLatestHistorySituation(1, 12345678).ToSql()
if err != nil {
t.Fatalf("Failed to build SQL: %v", err)
}

if expectedSQL != sql {
t.Errorf("Expected SQL to be \n%s\n but got \n%s", expectedSQL, sql)
}

if !reflect.DeepEqual(expectedArgs, args) {
t.Errorf("Expected args to be %v, but got %v", expectedArgs, args)
}
}
19 changes: 12 additions & 7 deletions internals/history/situation_history_querier.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,16 +275,21 @@ func (querier *HistorySituationsQuerier) QueryGetFieldsTsMetadatas(ctx context.C
var metadatas []models.MetaData
var ts time.Time
var metadataBytes []byte
err = rows.Scan(&ts, &metadataBytes)

err = rows.Scan(&ts, &metadataBytes)
if err != nil {
return HistorySituationsV4{}, fmt.Errorf("row scanning failed: %w", err)
} else {
err = json.Unmarshal(metadataBytes, &metadatas)
if err != nil {
return HistorySituationsV4{}, fmt.Errorf("Warning: unable to unmarshal metadatas JSON: %v\n", err)
}
}

err = json.Unmarshal(metadataBytes, &metadatas)
if err != nil {
return HistorySituationsV4{}, fmt.Errorf("Warning: unable to unmarshal metadatas JSON: %v", err)
}

if len(metadatas) == 0 {
return HistorySituationsV4{}, fmt.Errorf("The latest evaluation of the situation is unknown.")
}

result = HistorySituationsV4{Metadatas: metadatas, Ts: ts}
break //LIMIT 1
}
Expand All @@ -303,7 +308,7 @@ func (querier HistorySituationsQuerier) GetLatestHistory(situationID int64, situ
results, err := querier.QueryGetFieldsTsMetadatas(ctx, selectBuilder)
if err != nil {
if errors.Is(err, context.DeadlineExceeded) {
return HistorySituationsV4{}, errors.New("Timeout Error: The request targeting the 'situation_history_v5' table timed out after 1 minute.")
return HistorySituationsV4{}, errors.New("Timeout Error: The request targeting the 'situation_history_v5' table timed out after 10 seconds.")
}
return HistorySituationsV4{}, err
}
Expand Down
1 change: 1 addition & 0 deletions internals/history/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ func getTodayTimeRange() (string, string) {
todayStart := todayStartDate.Format("2006-01-02 15:04:05")
tomorrowStart := todayStartDate.Add(24 * time.Hour).Format("2006-01-02 15:04:05")
return todayStart, tomorrowStart
}

func getStartDate30DaysAgo() string {
now := time.Now().UTC()
Expand Down
27 changes: 27 additions & 0 deletions internals/history/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package history

import (
"testing"
"time"

"github.com/myrteametrics/myrtea-engine-api/v5/internals/situation"
"github.com/myrteametrics/myrtea-sdk/v4/expression"
Expand Down Expand Up @@ -39,3 +40,29 @@ func TestEvaluateExpressionFactsChain(t *testing.T) {
t.Log(expressionFactsEvaluated)
}
}

func TestGetTodayTimeRange(t *testing.T) {
todayStart, tomorrowStart := getTodayTimeRange()

now := time.Now().UTC().Truncate(24 * time.Hour)
expectedTodayStart := now.Format("2006-01-02 15:04:05")
expectedTomorrowStart := now.Add(24 * time.Hour).Format("2006-01-02 15:04:05")

if todayStart != expectedTodayStart {
t.Errorf("Expected today's start to be %s, but got %s", expectedTodayStart, todayStart)
}

if tomorrowStart != expectedTomorrowStart {
t.Errorf("Expected tomorrow's start to be %s, but got %s", expectedTomorrowStart, tomorrowStart)
}
}

func TestGetStartDate30DaysAgo(t *testing.T) {
date30DaysAgo := getStartDate30DaysAgo()

expectedDate := time.Now().UTC().AddDate(0, 0, -30).Format("2006-01-02 15:04:05")

if date30DaysAgo != expectedDate {
t.Errorf("Expected date 30 days ago to be %s, but got %s", expectedDate, date30DaysAgo)
}
}
Loading

0 comments on commit 1f2073c

Please sign in to comment.