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

Port to Funogram #59

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from
Draft
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
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM mcr.microsoft.com/dotnet/sdk:8.0.302-jammy AS build-env
FROM mcr.microsoft.com/dotnet/sdk:8.0.402-jammy AS build-env

### workaround for testcontainers resource reaper issue
ARG RESOURCE_REAPER_SESSION_ID="00000000-0000-0000-0000-000000000000"
Expand Down
2 changes: 1 addition & 1 deletion global.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"sdk": {
"version": "8.0.302"
"version": "8.0.402"
}
}
33 changes: 17 additions & 16 deletions src/VahterBanBot.Tests/BanTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
open System.Net
open VahterBanBot.Tests.ContainerTestBase
open VahterBanBot.Tests.TgMessageUtils
open VahterBanBot.Utils
open Xunit
open Xunit.Extensions.AssemblyFixture

Expand All @@ -16,13 +17,13 @@

// send the ban message
let! banResp =
Tg.replyMsg(msgUpdate.Message, "/ban", fixture.Vahters[0])
Tg.replyMsg(msgUpdate.Message.Value, "/ban", fixture.Vahters[0])
|> fixture.SendMessage
Assert.Equal(HttpStatusCode.OK, banResp.StatusCode)

// assert that the message got banned
let! msgBanned = fixture.MessageBanned msgUpdate.Message
let! msgBanned = fixture.MessageBanned msgUpdate.Message.Value
Assert.True msgBanned

Check failure on line 26 in src/VahterBanBot.Tests/BanTests.fs

View workflow job for this annotation

GitHub Actions / Test results

VahterBanBot.Tests.BanTests+BanTests ► Vahter can ban on reply

Failed test found in: src/VahterBanBot.Tests/TestResults/test-results.trx Error: Assert.True() Failure Expected: True Actual: False
Raw output
Assert.True() Failure
Expected: True
Actual:   False
   at [email protected]() in /home/runner/work/vahter-bot/vahter-bot/src/VahterBanBot.Tests/BanTests.fs:line 26
--- End of stack trace from previous location ---
}

[<Fact>]
Expand All @@ -33,12 +34,12 @@

// send the ban message from a non-admin user
let! banResp =
Tg.replyMsg(msgUpdate.Message, "/ban", Tg.user())
Tg.replyMsg(msgUpdate.Message.Value, "/ban", Tg.user())
|> fixture.SendMessage
Assert.Equal(HttpStatusCode.OK, banResp.StatusCode)

// assert that the message NOT banned
let! msgNotBanned = fixture.MessageBanned msgUpdate.Message
let! msgNotBanned = fixture.MessageBanned msgUpdate.Message.Value
Assert.False msgNotBanned
}

Expand All @@ -50,12 +51,12 @@

// send the ban message
let! banResp =
Tg.replyMsg(msgUpdate.Message, "/ban", fixture.Vahters[0])
Tg.replyMsg(msgUpdate.Message.Value, "/ban", fixture.Vahters[0])
|> fixture.SendMessage
Assert.Equal(HttpStatusCode.OK, banResp.StatusCode)

// assert that the message NOT banned
let! msgNotBanned = fixture.MessageBanned msgUpdate.Message
let! msgNotBanned = fixture.MessageBanned msgUpdate.Message.Value
Assert.False msgNotBanned
}

Expand All @@ -67,12 +68,12 @@

// send the ban message
let! banResp =
Tg.replyMsg(msgUpdate.Message, "/ban", fixture.Vahters[1])
Tg.replyMsg(msgUpdate.Message.Value, "/ban", fixture.Vahters[1])
|> fixture.SendMessage
Assert.Equal(HttpStatusCode.OK, banResp.StatusCode)

// assert that the message NOT banned
let! msgNotBanned = fixture.MessageBanned msgUpdate.Message
let! msgNotBanned = fixture.MessageBanned msgUpdate.Message.Value
Assert.False msgNotBanned
}

Expand All @@ -84,22 +85,22 @@

// send the ban message
let! banResp =
Tg.replyMsg(msgUpdate.Message, "/ban", fixture.Vahters[0])
Tg.replyMsg(msgUpdate.Message.Value, "/ban", fixture.Vahters[0])
|> fixture.SendMessage
Assert.Equal(HttpStatusCode.OK, banResp.StatusCode)

// assert that the message got banned
let! msgBanned = fixture.MessageBanned msgUpdate.Message
let! msgBanned = fixture.MessageBanned msgUpdate.Message.Value
Assert.True msgBanned

Check failure on line 94 in src/VahterBanBot.Tests/BanTests.fs

View workflow job for this annotation

GitHub Actions / Test results

VahterBanBot.Tests.BanTests+BanTests ► Vahter can unban user

Failed test found in: src/VahterBanBot.Tests/TestResults/test-results.trx Error: Assert.True() Failure Expected: True Actual: False
Raw output
Assert.True() Failure
Expected: True
Actual:   False
   at [email protected]() in /home/runner/work/vahter-bot/vahter-bot/src/VahterBanBot.Tests/BanTests.fs:line 94
--- End of stack trace from previous location ---

// send the unban message from another vahter
let! banResp =
Tg.quickMsg($"/unban {msgUpdate.Message.From.Id}", chat = fixture.ChatsToMonitor[0], from = fixture.Vahters[1])
Tg.quickMsg($"/unban {msgUpdate.Message.Value.FromId}", chat = fixture.ChatsToMonitor[0], from = fixture.Vahters[1])
|> fixture.SendMessage
Assert.Equal(HttpStatusCode.OK, banResp.StatusCode)

// assert that the message no longer banned
let! msgBanned = fixture.MessageBanned msgUpdate.Message
let! msgBanned = fixture.MessageBanned msgUpdate.Message.Value
Assert.False msgBanned
}

Expand All @@ -111,22 +112,22 @@

// send the ban message
let! banResp =
Tg.replyMsg(msgUpdate.Message, "/ban", fixture.Vahters[0])
Tg.replyMsg(msgUpdate.Message.Value, "/ban", fixture.Vahters[0])
|> fixture.SendMessage
Assert.Equal(HttpStatusCode.OK, banResp.StatusCode)

// assert that the message got banned
let! msgBanned = fixture.MessageBanned msgUpdate.Message
let! msgBanned = fixture.MessageBanned msgUpdate.Message.Value
Assert.True msgBanned

Check failure on line 121 in src/VahterBanBot.Tests/BanTests.fs

View workflow job for this annotation

GitHub Actions / Test results

VahterBanBot.Tests.BanTests+BanTests ► Only Vahter can unban user

Failed test found in: src/VahterBanBot.Tests/TestResults/test-results.trx Error: Assert.True() Failure Expected: True Actual: False
Raw output
Assert.True() Failure
Expected: True
Actual:   False
   at [email protected]() in /home/runner/work/vahter-bot/vahter-bot/src/VahterBanBot.Tests/BanTests.fs:line 121
--- End of stack trace from previous location ---

// send the unban message from a random user
let! banResp =
Tg.quickMsg($"/unban {msgUpdate.Message.From.Id}", chat = fixture.ChatsToMonitor[0])
Tg.quickMsg($"/unban {msgUpdate.Message.Value.FromId}", chat = fixture.ChatsToMonitor[0])
|> fixture.SendMessage
Assert.Equal(HttpStatusCode.OK, banResp.StatusCode)

// assert that the message still banned
let! msgBanned = fixture.MessageBanned msgUpdate.Message
let! msgBanned = fixture.MessageBanned msgUpdate.Message.Value
Assert.True msgBanned
}

Expand Down
4 changes: 2 additions & 2 deletions src/VahterBanBot.Tests/BaseTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module BaseTests
open System
open System.Net.Http
open System.Text
open Telegram.Bot.Types
open Funogram.Telegram.Types
open VahterBanBot.Tests.ContainerTestBase
open Xunit
open Xunit.Extensions.AssemblyFixture
Expand All @@ -28,7 +28,7 @@ type BaseTests(fixture: VahterTestContainers) =

[<Fact>]
let ``Should be possible to interact with the bot`` () = task {
let! resp = Update(Id = 123) |> fixture.SendMessage
let! resp = Update.Create(updateId = 123) |> fixture.SendMessage
let! body = resp.Content.ReadAsStringAsync()
Assert.Equal(System.Net.HttpStatusCode.OK, resp.StatusCode)
Assert.Equal("null", body)
Expand Down
38 changes: 26 additions & 12 deletions src/VahterBanBot.Tests/ContainerTestBase.fs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ open System.Threading.Tasks
open DotNet.Testcontainers.Builders
open DotNet.Testcontainers.Configurations
open DotNet.Testcontainers.Containers
open Funogram.Telegram.Types
open Npgsql
open Telegram.Bot.Types
open Testcontainers.PostgreSql
open VahterBanBot.Tests.TgMessageUtils
open VahterBanBot.Types
Expand All @@ -30,6 +30,7 @@ type VahterTestContainers() =
let mutable publicConnectionString: string = null

// base image for the app, we'll build exactly how we build it in Azure
let buildLogger = StringLogger()
let image =
ImageFromDockerfileBuilder()
.WithDockerfileDirectory(solutionDir, String.Empty)
Expand All @@ -39,6 +40,8 @@ type VahterTestContainers() =
.WithBuildArgument("RESOURCE_REAPER_SESSION_ID", ResourceReaper.DefaultSessionId.ToString("D"))
// it might speed up the process to not clean up the base image
.WithCleanUp(false)
.WithDeleteIfExists(true)
.WithLogger(buildLogger)
.Build()

// private network for the containers
Expand Down Expand Up @@ -113,17 +116,27 @@ type VahterTestContainers() =
.DependsOn(flywayContainer)
.WithWaitStrategy(Wait.ForUnixContainer().UntilPortIsAvailable(80))
.Build()

let startContainers() = task {
try
// start building the image and spin up db at the same time
let imageTask = image.CreateAsync()
let dbTask = dbContainer.StartAsync()

// wait for both to finish
do! imageTask
do! dbTask
with
| e ->
let logs = buildLogger.ExtractMessages()
let errorMessage = "Container startup failure, logs:\n" + if String.IsNullOrWhiteSpace logs then "<no logs provided>" else logs
raise <| Exception(errorMessage, e)
}

interface IAsyncLifetime with
member this.InitializeAsync() = task {
try
// start building the image and spin up db at the same time
let imageTask = image.CreateAsync()
let dbTask = dbContainer.StartAsync()

// wait for both to finish
do! imageTask
do! dbTask
do! startContainers()
publicConnectionString <- $"Server=127.0.0.1;Database=vahter_bot_ban;Port={dbContainer.GetMappedPublicPort(5432)};User Id=vahter_bot_ban_service;Password=vahter_bot_ban_service;Include Error Detail=true;Minimum Pool Size=1;Maximum Pool Size=20;Max Auto Prepare=100;Auto Prepare Min Usages=1;Trust Server Certificate=true;"

// initialize DB with the schema, database and a DB user
Expand Down Expand Up @@ -158,9 +171,10 @@ type VahterTestContainers() =
httpClient.BaseAddress <- uri
httpClient.DefaultRequestHeaders.Add("X-Telegram-Bot-Api-Secret-Token", "OUR_SECRET")
finally
let struct (_, err) = appContainer.GetLogsAsync().Result
if err <> "" then
failwith err
if appContainer.State <> TestcontainersStates.Undefined then
let struct (_stdout, err) = appContainer.GetLogsAsync().Result
if err <> "" then
failwith err
}
member this.DisposeAsync() = task {
// stop all the containers, flyway might be dead already
Expand Down Expand Up @@ -246,7 +260,7 @@ WHERE data ->> 'Case' = @caseName
SELECT COUNT(*) FROM false_positive_messages
WHERE text = @text
"""
let! result = conn.QuerySingleAsync<int>(sql, {| text = msg.Text |})
let! result = conn.QuerySingleAsync<int>(sql, {| text = msg.Text.Value |})
return result > 0
}

Expand Down
16 changes: 16 additions & 0 deletions src/VahterBanBot.Tests/Logging.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace VahterBanBot.Tests

open System
open Microsoft.Extensions.Logging

type StringLogger() =
let lockObj = obj()
let messages = ResizeArray<string>()
interface ILogger with
member this.BeginScope _ = null
member this.IsEnabled _ = true
member this.Log(logLevel, _eventId, state, ex, formatter) =
lock lockObj (fun() ->
messages.Add($"[{logLevel}] {formatter.Invoke(state, ex)}"))

member _.ExtractMessages(): string = lock lockObj (fun() -> String.Join("\n", messages))
Loading
Loading