How Linux Net Core 3.1 daemon (in VB.NET) can read/write data from/to ancient MS SQL 2005
- 1. Foundation of solution, external circumstances.
- 2. Solution architecture.
- 3. Deploy NET CORE application as Linux daemon.
- 4. WCF server (NET 4.0) in Windows 2003.
- 5. Create raw reference to WCF service in C# and without tuning.
- 6. Modify raw reference to add client config and compile it to dedicated library.
- 7. Include library with WCF reference to NET CORE VB project.
- 8. Create Authentication layer inside WCF communication to protect WCF server from rogue WCF client.
- 9. Text test WCF client configuration and raw WCF communication (MS Unit test).
- 10. Inject WCF client with Authentication layer to Core DI container as Singleton service.
- 11. Test my WCF client with AU layer with Mock and Real log (Nunit).
- 12. Add memory cache layer (EF db definition).
- 13. Add memory cache layer (add InMemoryDB service).
- 14. Add memory cache layer.
- 15. TestController code to call cache layer.
- 16. Test memory cache layer (Nunit).
- 17. Integration test to write data to remote SQL2005.
- 18. Remote debugging and monitoring.
1. Foundation of solution, external circumstances.
As start point I have huge DB in MS SQL 2005 with six terabyte data in Windows 2003.
In other side I need to communicate with modern Linux server by TSL 1.2.
How Is possible to solve this problem? There are some additional condition as secure communication with SQL server and finally I have so few time for this project therefore it will be VB program.
2. Solution architecture.
As a result of thinking I figure out a solution and realized it successfully.
3. Deploy NET CORE application as Linux daemon.
This is deployment process Deploy ASP.NET Core application from scratch (install and tune SSH/VNC/FTP/NGINX/Daemon). And below is my Net Core application, as you can see on library set this is WCF client
And this is a lot of scanning message from inet
4. WCF server (NET 4.0) in Windows 2003.
How I rich this result? As first step I write ordinary WCF service in NET Framework 4.0, because Windows 2003 not support more modern framework. I don't want describe this project, because it bored for me, its my liked type of projects, I done a lot of similar projects.
5. Create raw reference to WCF service in C# and without tuning.
So, what I done next? I take simple MS client for WCF service from VS2019. Unfortunately, MS Vilified Visual Basic (Why Microsoft vilified Visual Basic ?)and this client not support scaffolding to VB.
Than I must be create separate project with WCF reference in C#
6. Modify raw reference to add client config and compile it to dedicated library.
This project with WCF-client was be stupid, because IP-address if my server was be hard set in code. How can I deploy this project in server? Any IP address will be different in my development environment and production environment in server. Therefore I replace stupid Microsoft code to reading IP address from config file. This is line 727.
7. Include library with WCF reference to NET CORE VB project.
Than I simple set Wcf Client library as reference to may NET Core project.
This is definition of my WCF by definition of ServiceReference class.
1: Public Interface IAuWcf
2: Function CreateMD5(ByVal Input As String) As String
3: Function AuTest(Input As Integer) As String
4: Function AuAddTrace(Txt As String) As Integer
5: Function AuGetBlockIP() As ServiceReference1.RetBlockIP()
6: Function AuGetGrapHoperKey() As ServiceReference1.RetGraphHoperKey()
7: Function AuCheckIsUrlExist(Url As String) As Boolean
8: Function AuGetRoute(Url As String) As ServiceReference1.RetGraphHoperCache
9: Function AuAddRoute(Url As String, Route As String) As Long
10: End Interface
8. Create Authentication layer inside WCF communication to protect WCF server from rogue WCF client.
Than I created middleware - wrapper around WCF-function and protection, it will be communicate with my own library to identify client of WCF service - Protect WCF service by password
1: Imports ServiceReference1
2: Imports Newtonsoft.Json
3: Imports System.IO
4: Imports System.Text
5:
6: Public Class AuWcf
7: Implements IAuWcf
8:
9: Public WcfConfig As Dictionary(Of String, String)
10: Dim Wcf As ServiceReference1.Service1Client
11:
12: Public Sub New()
13: WcfConfig = JsonConvert.DeserializeObject(Of Dictionary(Of String, String))(File.ReadAllText(Path.Combine(Directory.GetCurrentDirectory(), "WcfConfig.json")))
14: Wcf = New ServiceReference1.Service1Client
15: End Sub
16:
17: Public Function CreateMD5(ByVal Input As String) As String Implements IAuWcf.CreateMD5
18: Dim Sb = New StringBuilder()
19: Using Md5 As System.Security.Cryptography.MD5 = System.Security.Cryptography.MD5.Create()
20: Dim InputBytes As Byte() = System.Text.Encoding.ASCII.GetBytes(Input)
21: Dim HashBytes As Byte() = Md5.ComputeHash(InputBytes)
22: For I As Integer = 0 To HashBytes.Length - 1
23: Sb.Append(HashBytes(I).ToString("X2"))
24: Next
25: Return Sb.ToString()
26: End Using
27: End Function
28:
29: 'Stateless requests
30: Public Function AuTest(Input As Integer) As String Implements IAuWcf.AuTest
31: Dim Bearer As String = Wcf.GetToken(New GetTokenRequest()).GetTokenResult
32: Dim Sign = CreateMD5(WcfConfig("Password") & Bearer)
33: Dim TestRequest As New TestRequest(Bearer, Sign, Input)
34: Return Wcf.Test(TestRequest).TestResult
35: End Function
36:
37: Public Function AuAddTrace(Txt As String) As Integer Implements IAuWcf.AuAddTrace
38: Dim Bearer As String = Wcf.GetToken(New GetTokenRequest()).GetTokenResult
39: Dim Sign = CreateMD5(WcfConfig("Password") & Bearer)
40: Dim RQ1 As New AddTraceRequest(Bearer, Sign, Now, "Headers", Txt)
41: Return Wcf.AddTrace(RQ1).AddTraceResult
42: End Function
43:
44: Public Function AuGetBlockIP() As ServiceReference1.RetBlockIP() Implements IAuWcf.AuGetBlockIP
45: Dim Bearer As String = Wcf.GetToken(New GetTokenRequest()).GetTokenResult
46: Dim Sign = CreateMD5(WcfConfig("Password") & Bearer)
47: Dim RQ1 As New GetBlockIPRequest(Bearer, Sign)
48: Return Wcf.GetBlockIP(RQ1).GetBlockIPResult
49: End Function
50:
51: Public Function AuGetGrapHoperKey() As RetGraphHoperKey() Implements IAuWcf.AuGetGrapHoperKey
52: Dim Bearer As String = Wcf.GetToken(New GetTokenRequest()).GetTokenResult
53: Dim Sign = CreateMD5(WcfConfig("Password") & Bearer)
54: Dim RQ1 As New GetGrapHoperKeyRequest(Bearer, Sign)
55: Return Wcf.GetGrapHoperKey(RQ1).GetGrapHoperKeyResult
56: End Function
57:
58: Public Function AuCheckIsUrlExist(Url As String) As Boolean Implements IAuWcf.AuCheckIsUrlExist
59: Dim Bearer As String = Wcf.GetToken(New GetTokenRequest()).GetTokenResult
60: Dim Sign = CreateMD5(WcfConfig("Password") & Bearer)
61: Dim RQ1 As New CheckIsUrlExistRequest(Bearer, Sign, Url)
62: Return Wcf.CheckIsUrlExist(RQ1).CheckIsUrlExistResult
63: End Function
64:
65: Public Function AuGetRoute(Url As String) As RetGraphHoperCache Implements IAuWcf.AuGetRoute
66: Dim Bearer As String = Wcf.GetToken(New GetTokenRequest()).GetTokenResult
67: Dim Sign = CreateMD5(WcfConfig("Password") & Bearer)
68: Dim RQ1 As New GetRouteRequest(Bearer, Sign, Url)
69: Return Wcf.GetRoute(RQ1).GetRouteResult
70: End Function
71:
72: Public Function AuAddRoute(Url As String, Route As String) As Long Implements IAuWcf.AuAddRoute
73: Dim Bearer As String = Wcf.GetToken(New GetTokenRequest()).GetTokenResult
74: Dim Sign = CreateMD5(WcfConfig("Password") & Bearer)
75: Dim RQ1 As New AddRouteRequest(Bearer, Sign, Url, Route)
76: Return Wcf.AddRoute(RQ1).AddRouteResult
77: End Function
78: End Class
9. Text test WCF client configuration and raw WCF communication (MS Unit test).
As next step I have created MS Unit test for all my remote methods:
1: Imports System.Text
2: Imports Microsoft.VisualStudio.TestTools.UnitTesting
3: Imports Newtonsoft.Json
4:
5: Namespace MsWcfReferenceUnitTest1
6: <TestClass>
7: Public Class WcfTest1
8:
9: Private testContextInstance As TestContext
10: Public Property TestContext As TestContext
11: Get
12: Return testContextInstance
13: End Get
14: Set(ByVal value As TestContext)
15: testContextInstance = value
16: End Set
17: End Property
18:
19: Dim WcfServices As CoreLinux.AuWcf 'link to project with service references to WCF
20:
21: <TestInitialize>
22: Sub Start()
23: WcfServices = New CoreLinux.AuWcf
24: TestContext.WriteLine(JsonConvert.SerializeObject(WcfServices.WcfConfig, Formatting.Indented))
25: End Sub
26:
27: <TestMethod>
28: Sub AuTest()
29: Dim AuTestResult As String = WcfServices.AuTest(10)
30: Assert.AreEqual("10", AuTestResult)
31: End Sub
32:
33: <TestMethod>
34: Sub AuGetBlockIP()
35: Dim Str1 As New StringBuilder
36: Dim AuTestResult As ServiceReference1.RetBlockIP() = WcfServices.AuGetBlockIP()
37: AuTestResult.ToList.ForEach(Sub(X)
38: Str1.Append(X.I)
39: Str1.AppendLine(X.BlockNet)
40: End Sub)
41: TestContext.WriteLine(Str1.ToString)
42: Assert.IsTrue(True)
43: End Sub
...
10. Inject WCF client with Authentication layer to Core DI container as Singleton service.
Than I have Injected dependency to ASP.MET Core DI container (in my case Singleton is enough).
...
19: Public Class Startup
...
26: Public Sub ConfigureServices(ByVal services As IServiceCollection)
...
35: services.Add(New ServiceDescriptor(GetType(IAuWcf), New AuWcf()))
36: 'or
37: services.AddSingleton(GetType(IAuWcf), New AuWcf())
...
And than receive reference in controller
11. Test my WCF client with AU layer with Mock and Real log (Nunit).
Than I create full test my middleware for DI container with separate test of my middleware (my wrapper around WCF reference to hide security with comunnication with server) what I add to project as Singlton, and than test controller used my middlware (with Mock and Real log).
1: Imports NUnit.Framework
2: Imports Moq
3: Imports Microsoft.AspNetCore.Hosting
4: Imports Microsoft.Extensions.DependencyInjection
5: Imports Microsoft.Extensions.Hosting
6: Imports Microsoft.Extensions.Logging
7: Imports Microsoft.Extensions.Logging.Abstractions
8: Imports CoreLinux
9: Imports Newtonsoft.Json
10: Imports Microsoft.AspNetCore.Mvc
11:
12: Namespace CoreLinuxNUnitTest1
13:
14: Public Class Tests
15: Property CoreDIserviceCollection As IServiceCollection
16: Property CoreDIserviceProvider As ServiceProvider
17: Property MockLog As ILogger(Of CoreLinux.TestController)
18: Property RealLog As ILogger(Of CoreLinux.TestController)
19: Property AuWcf1 As AuWcf
20:
21: <SetUp>
22: Public Sub Setup()
23: CoreDIserviceCollection = New ServiceCollection()
24: CoreDIserviceProvider = CoreDIserviceCollection.AddLogging.BuildServiceProvider()
25: End Sub
26:
27: <Test>
28: Public Sub ShowServive()
29: Dim Str1 As New Text.StringBuilder
30: CoreDIserviceCollection.ToList.ForEach(Sub(ServiceDescriptor)
31: Str1.Append(ServiceDescriptor.Lifetime.ToString & " : ")
32: Str1.AppendLine(ServiceDescriptor.ServiceType.FullName)
33: End Sub)
34: Assert.IsTrue(CoreDIserviceCollection.Count > 0)
35: TestContext.WriteLine("CoreDI builded " & CoreDIserviceCollection.Count & " services" & vbCrLf & Str1.ToString)
36: TestContext.WriteLine()
37: End Sub
38:
39: <Test>
40: Public Sub CreateMiddlwareInstance()
41: AuWcf1 = New AuWcf()
42: Assert.AreEqual(5, AuWcf1.WcfConfig.Count)
43: TestContext.WriteLine("WcfConfig" & vbCrLf & JsonConvert.SerializeObject(AuWcf1.WcfConfig, Formatting.Indented))
44: TestContext.WriteLine()
45: End Sub
46:
47: <Test>
48: Public Sub TestCoreSingletonServiceFactory()
49: ShowServive()
50: CreateMiddlwareInstance()
51: CoreDIserviceCollection.AddSingleton(GetType(IAuWcf), AuWcf1)
52: Dim Res As String = AuWcf1.AuTest(10)
53: Assert.AreEqual("10", Res)
54: ShowServive()
55: End Sub
56:
57: <Test>
58: Public Sub TestCoreControllerWithoutLog()
59: CreateMiddlwareInstance()
60: Dim Controller1 As New CoreLinux.TestController(AuWcf1)
61: Dim Response As IActionResult = Controller1.Index()
62: Dim Content As ContentResult = Response
63: TestContext.WriteLine(Content.Content)
64: Assert.AreEqual(Content.ContentType, "text/html")
65: End Sub
66:
67: <Test>
68: Public Sub AddMockLoggerWithOwnImpl()
69: ShowServive()
70: Dim _Mock = New Mock(Of ILogger(Of CoreLinux.TestController))
71: MockLog = _Mock.Object
72: Dim MockLogger1 As MockLogger = New MockLogger()
73: MockLogger1.LogLevel = LogLevel.Information Or LogLevel.Error Or LogLevel.Warning Or LogLevel.Trace Or LogLevel.Debug Or LogLevel.Trace
74: CoreDIserviceCollection.AddSingleton(Of ILoggerFactory)(Function(s)
75: Dim loggerFactoryMock = New Mock(Of ILoggerFactory)()
76: loggerFactoryMock.Setup(Function(m) m.CreateLogger(It.IsAny(Of String)())).Returns(MockLogger1)
77: Return loggerFactoryMock.Object
78: End Function)
79:
80: MockLog.Log(LogLevel.Information, "MockLog")
81: ShowServive()
82: End Sub
83:
84: <Test>
85: Public Sub AddMockLoggerSimple()
86: Dim _Mock = New Mock(Of ILogger(Of CoreLinux.TestController))
87: MockLog = _Mock.Object
88: CoreDIserviceCollection.AddSingleton(GetType(ILogger(Of TestController)), MockLog)
89: MockLog.Log(LogLevel.Information, "MockLog")
90: ShowServive()
91: End Sub
92:
93: <Test>
94: Public Sub TestCoreControllerWithMockLog()
95: AddMockLoggerSimple()
96: CreateMiddlwareInstance()
97: Dim Controller1 As New CoreLinux.TestController(AuWcf1, MockLog)
98: Dim Response As IActionResult = Controller1.Index()
99: Dim Content As ContentResult = Response
100: TestContext.WriteLine(Content.Content)
101: Assert.AreEqual(Content.ContentType, "text/html")
102: End Sub
103:
104: <Test>
105: Public Sub AddRealLogger()
106: CreateMiddlwareInstance()
107: Dim _LoggerFactory = LoggerFactory.Create(Sub(Builder) Builder.AddConsole())
108: RealLog = _LoggerFactory.CreateLogger(Of CoreLinux.TestController)
109: CoreDIserviceCollection.AddSingleton(GetType(ILogger(Of TestController)), RealLog)
110: RealLog.LogInformation("Test RealLog")
111: ShowServive()
112: End Sub
113:
114: <Test>
115: Public Sub TestCoreControllerWithRealLog()
116: CreateMiddlwareInstance()
117: AddRealLogger()
118: Dim Controller1 As New CoreLinux.TestController(AuWcf1, RealLog)
119: Dim Response As IActionResult = Controller1.Index()
120: Dim Content As ContentResult = Response
121: TestContext.WriteLine(Content.Content)
122: Assert.AreEqual(Content.ContentType, "text/html")
123: End Sub
124:
125: End Class
126:
127: End Namespace
12. Add memory cache layer (EF db definition).
Than. to improve prformance, I decide create additional layer, a memory cache in Linux machine for data reading from SQL2005. For this perpose, I define a DB:
1: Imports Microsoft.EntityFrameworkCore
2: Imports System
3: Imports System.Collections.Generic
4: Imports System.ComponentModel.DataAnnotations
5: Imports System.Linq
6: Public Class InMemoryDBContext
7: Inherits DbContext
8:
9: Public Sub New(ByVal options As DbContextOptions(Of InMemoryDBContext))
10: MyBase.New(options)
11: End Sub
12:
13: Public Property GraphHoperKeys As DbSet(Of RetGraphHoperKey)
14: Public Property BotIps As DbSet(Of RetBlockIP)
15:
16: Public Property LocaRoutesCache As DbSet(Of LocalCache)
17:
18: End Class
19:
20: Public Class RetBlockIP
21: <Key>
22: Public Property I As Long
23: Public Property BlockNet As String
24: End Class
25: Public Class RetGraphHoperKey
26: <Key>
27: Public Property I As Long
28: Public Property MasterKey As String
29: Public Property RealKey As String
30: End Class
31: Public Class LocalCache
32: <Key>
33: Public Property I As Long
34: Public URL As String
35: Public Property Route As String
36: Public Property AddDate As DateTime
37: End Class
Initially I want to define DB directly in type produced by ServiceReference1, but sorry there are no key for EntityFramework. I'm forced to create additional define of RetBlockIP and RetGraphHoperKey instead ServiceReference1.RetBlockIP and ServiceReference1.RetGraphHoperKey.
13. Add memory cache layer (add InMemoryDB service) and new service SQLCache.
Than I was add InMemoryDB.
And I have included db to project:
27: Public Sub ConfigureServices(ByVal services As IServiceCollection)
...
36: services.
37: AddDbContext(Of InMemoryDBContext)(Sub(opts) opts.UseInMemoryDatabase("DataFromSql2005"), ServiceLifetime.Singleton)
...
40: 'services.Add(New ServiceDescriptor(GetType(IAuWcf), New AuWcf()))
41: 'or
42: services.AddSingleton(GetType(IAuWcf), New AuWcf())
43:
44: services.AddSingleton(GetType(ISQLCache), New SQLCache())
14. Add memory cache layer.
1: Public Interface ISQLCache
2:
3: ReadOnly Property IsActivated As Boolean
4: Function Activate(_InMemoryDatabase As InMemoryDBContext, _AuWcf As IAuWcf) As ISQLCache
5: ReadOnly Property IsStaticDataLoaded As Boolean
6: Function LoadStaticDataToLocalCache() As (GraphHoperKeyCount As Integer, BotIp As Integer)
7: Function AddRouteToLocalCache(I As Long, CacheURL As String, Route As String) As Integer
8: Function GetRouteFromLocalCache(CacheURL As String) As String
9:
10: End Interface
Than I implemented this interface interface:
1: Imports Microsoft.AspNetCore.Http
2:
3: Public Class SQLCache
4: Implements ISQLCache
5:
6: Property InMemoryDatabase As InMemoryDBContext
7: Property AuWcf As IAuWcf
8:
9: Public ReadOnly Property IsActivated As Boolean Implements ISQLCache.IsActivated
10: Get
11: Return _IsActivated
12: End Get
13: End Property
14: Property _IsActivated As Boolean = False
15:
16: Public Function Activate(_InMemoryDatabase As InMemoryDBContext, _AuWcf As IAuWcf) As ISQLCache Implements ISQLCache.Activate
17: InMemoryDatabase = _InMemoryDatabase
18: AuWcf = _AuWcf
19: _IsActivated = True
20: Return Me
21: End Function
22: Public ReadOnly Property IsStaticDataLoaded As Boolean Implements ISQLCache.IsStaticDataLoaded
23: Get
24: Return _IsStaticDataLoaded
25: End Get
26: End Property
27: Property _IsStaticDataLoaded = False
28:
29: Public Async Function InvokeAsync(ByVal context As HttpContext, ByVal NextDelegate As RequestDelegate, _InMemoryDatabase As InMemoryDBContext, _AuWcf As IAuWcf) As Task
30: Await NextDelegate(context)
31: End Function
32:
33: Public Function LoadStaticDataToLocalCache() As (GraphHoperKeyCount As Integer, BotIp As Integer) Implements ISQLCache.LoadStaticDataToLocalCache
34: If Not InMemoryDatabase.GraphHoperKeys.Any Then
35: Dim Ret1 = AuWcf.AuGetGrapHoperKey()
36: Ret1.ToList.ForEach(Sub(One) InMemoryDatabase.GraphHoperKeys.Add(New RetGraphHoperKey With {.I = One.I, .MasterKey = One.MasterKey, .RealKey = One.RealKey}))
37: End If
38: If Not InMemoryDatabase.BotIps.Any Then
39: Dim Ret2 = AuWcf.AuGetBlockIP()
40: Ret2.ToList.ForEach(Sub(one) InMemoryDatabase.BotIps.AddRange(New RetBlockIP With {.I = one.I, .BlockNet = one.BlockNet}))
41: End If
42: InMemoryDatabase.SaveChanges()
43: _IsStaticDataLoaded = True
44: Return (InMemoryDatabase.GraphHoperKeys.Count, InMemoryDatabase.BotIps.Count)
45: End Function
46:
47: Public Function AddRouteToLocalCache(I As Long, CacheURL As String, Route As String) As Integer Implements ISQLCache.AddRouteToLocalCache
48: AddRouteToLocalCache = InMemoryDatabase.LocaRoutesCache.Count
49: If AddRouteToLocalCache >= 100 Then
50: Dim OldestRow = InMemoryDatabase.LocaRoutesCache.OrderByDescending(Of DateTime)(Function(X) X.AddDate).Take(1)
51: InMemoryDatabase.LocaRoutesCache.Remove(OldestRow)
52: InMemoryDatabase.SaveChanges()
53: End If
54: InMemoryDatabase.LocaRoutesCache.Add(New LocalCache With {.I = I, .AddDate = Now, .URL = CacheURL, .Route = Route})
55: End Function
56:
57: Public Function GetRouteFromLocalCache(CacheURL As String) As String Implements ISQLCache.GetRouteFromLocalCache
58: Return InMemoryDatabase.LocaRoutesCache.Where(Function(X) X.URL = CacheURL).FirstOrDefault.Route
59: End Function
60:
61: End Class
15. TestController code to call cache layer.
This way allow me to avoid activation middleware by Invoke and simplify my code.
1: Imports System
2: Imports System.Collections.Generic
3: Imports System.Linq
4: Imports System.Threading.Tasks
5: Imports Microsoft.AspNetCore.Http
6: Imports Microsoft.AspNetCore.Mvc
7: Imports Microsoft.AspNetCore.Authorization
8: Imports Newtonsoft.Json
9: Imports Microsoft.Extensions.Logging
10: Imports Microsoft.EntityFrameworkCore.InMemory.Storage.Internal
11:
12: <Route("[controller]")>
13: <ApiController>
14: <ServiceFilter(GetType(AuditAttribute))>
15: Public Class TestController
16: Inherits ControllerBase
17:
18: Property SQL2005 As IAuWcf
19: Property Logger As ILogger(Of TestController)
20: Property InMemoryDatabase As InMemoryDBContext
21: Property SQLCache As ISQLCache
22:
23: Public Sub New(_SQL2005 As IAuWcf, _Logger As ILogger(Of TestController), _InMemoryDatabase As InMemoryDBContext, _SQLCache As ISQLCache)
24: SQL2005 = _SQL2005
25: Logger = _Logger
26: InMemoryDatabase = _InMemoryDatabase
27: If Not _SQLCache.IsActivated Then _SQLCache.Activate(_InMemoryDatabase, _SQL2005)
28: If Not _SQLCache.IsStaticDataLoaded Then _SQLCache.LoadStaticDataToLocalCache()
29: SQLCache = _SQLCache
30: End Sub
31:
32: Public Function Index() As ActionResult
33: ' If Logger IsNot Nothing Then Logger.Log(LogLevel.Information, $"GraphHoperKeyCount={CacheCount.GraphHoperKeyCount}, BotIp={CacheCount.BotIp}")
34: Dim D As New ObjectDumper
35: Dim Str1 As String = D.Dump(3, Request)
36: SQL2005.AuAddTrace(Str1)
37: Return Content(String.Format("<html><body><img src='asp_net_core_3_1_vb_GDH_icon.ico'><pre>{0}</pre></body></html>", Str1), "text/html")
38: End Function
39:
40: End Class
16. Test memory cache layer (Nunit).
Than I have created test for my middleware. I made big mistake and spend for this test more times than to code, I was want receive dbContext as result of string 52, and finally I realized my mistake and create context for testing from scratch in line 53.
1: Imports NUnit.Framework
2: Imports Moq
3: Imports Microsoft.AspNetCore.Hosting
4: Imports Microsoft.Extensions.DependencyInjection
5: Imports Microsoft.Extensions.Hosting
6: Imports Microsoft.Extensions.Logging
7: Imports Microsoft.Extensions.Logging.Abstractions
8: Imports CoreLinux
9: Imports Newtonsoft.Json
10: Imports Microsoft.AspNetCore.Mvc
11: Imports Microsoft.EntityFrameworkCore
12:
13: Namespace CoreLinuxNUnitTest1
14:
15: Public Class Tests
16: Property CoreDIserviceCollection As IServiceCollection
17: Property CoreDIserviceProvider As ServiceProvider
18: Property MockLog As ILogger(Of CoreLinux.TestController)
19: Property RealLog As ILogger(Of CoreLinux.TestController)
20: Property AuWcf1 As AuWcf
21: Property InMemoryDBContext1 As InMemoryDBContext
22: Property SQLCache1 As ISQLCache
23:
24: <SetUp>
25: Public Sub Setup()
26: CoreDIserviceCollection = New ServiceCollection()
27: CoreDIserviceProvider = CoreDIserviceCollection.AddLogging.BuildServiceProvider()
28: End Sub
29:
30: <Test>
31: Public Sub ShowServive()
32: Dim Str1 As New Text.StringBuilder
33: CoreDIserviceCollection.ToList.ForEach(Sub(ServiceDescriptor)
34: Str1.Append(ServiceDescriptor.Lifetime.ToString & " : ")
35: Str1.AppendLine(ServiceDescriptor.ServiceType.FullName)
36: End Sub)
37: Assert.IsTrue(CoreDIserviceCollection.Count > 0)
38: TestContext.WriteLine("CoreDI builded " & CoreDIserviceCollection.Count & " services" & vbCrLf & Str1.ToString)
39: TestContext.WriteLine()
40: End Sub
41:
42: <Test>
43: Public Sub CreateAuWcfInstance()
44: AuWcf1 = New AuWcf()
45: Assert.AreEqual(5, AuWcf1.WcfConfig.Count)
46: TestContext.WriteLine("WcfConfig" & vbCrLf & JsonConvert.SerializeObject(AuWcf1.WcfConfig, Formatting.Indented))
47: TestContext.WriteLine()
48: End Sub
49:
50: <Test>
51: Public Sub TestAuWcfGetKeys()
52: CreateAuWcfInstance()
53: Dim x = AuWcf1.AuGetGrapHoperKey()
54: TestContext.WriteLine()
55: End Sub
56:
57: <Test>
58: Public Sub CreateInMemoryDbInstance()
59: 'wrong way
60: CoreDIserviceCollection.AddDbContext(Of InMemoryDBContext)(Sub(opts) opts.UseInMemoryDatabase("DataFromSql2005"), ServiceLifetime.Singleton)
61: Dim InMemoryDBContextService = CoreDIserviceCollection.Where(Function(y) y.ServiceType.FullName = "CoreLinux.InMemoryDBContext").First
62: ShowServive()
63: 'correct way
64: Dim DbOptions = New DbContextOptionsBuilder(Of InMemoryDBContext)().UseInMemoryDatabase(databaseName:="DataFromSql2005").Options
65: InMemoryDBContext1 = New InMemoryDBContext(DbOptions)
66: End Sub
67:
68: Public Sub CreateSQLCacheInstance()
69: CreateAuWcfInstance()
70: CreateInMemoryDbInstance()
71: SQLCache1 = New SQLCache()
72: If Not SQLCache1.IsActivated Then SQLCache1.Activate(InMemoryDBContext1, AuWcf1)
73: Dim CacheCount As ValueTuple(Of Integer, Integer)
74: If Not SQLCache1.IsStaticDataLoaded Then
75: CacheCount = SQLCache1.LoadStaticDataToLocalCache()
76: TestContext.WriteLine("WcfConfig" & $"GraphHoperKeyCount={CacheCount.Item1}, BotIp={CacheCount.Item2}")
77: End If
78: Assert.IsTrue(SQLCache1.IsActivated)
79: End Sub
80:
81: <Test>
82: Public Sub TestCoreSingletonServiceFactory()
83: ShowServive()
84: CreateAuWcfInstance()
85: CoreDIserviceCollection.AddSingleton(GetType(IAuWcf), AuWcf1)
86: Dim Res As String = AuWcf1.AuTest(10)
87: Assert.AreEqual("10", Res)
88: ShowServive()
89: End Sub
90:
91: <Test>
92: Public Sub AddMockLoggerWithOwnImpl()
93: ShowServive()
94: Dim _Mock = New Mock(Of ILogger(Of CoreLinux.TestController))
95: MockLog = _Mock.Object
96: Dim MockLogger1 As MockLogger = New MockLogger()
97: MockLogger1.LogLevel = LogLevel.Information Or LogLevel.Error Or LogLevel.Warning Or LogLevel.Trace Or LogLevel.Debug Or LogLevel.Trace
98: CoreDIserviceCollection.AddSingleton(Of ILoggerFactory)(Function(s)
99: Dim loggerFactoryMock = New Mock(Of ILoggerFactory)()
100: loggerFactoryMock.Setup(Function(m) m.CreateLogger(It.IsAny(Of String)())).Returns(MockLogger1)
101: Return loggerFactoryMock.Object
102: End Function)
103:
104: MockLog.Log(LogLevel.Information, "MockLog")
105: ShowServive()
106: End Sub
107:
108: <Test>
109: Public Sub AddMockLoggerSimple()
110: Dim _Mock = New Mock(Of ILogger(Of CoreLinux.TestController))
111: MockLog = _Mock.Object
112: CoreDIserviceCollection.AddSingleton(GetType(ILogger(Of TestController)), MockLog)
113: MockLog.Log(LogLevel.Information, "MockLog")
114: ShowServive()
115: End Sub
116:
117: <Test>
118: Public Sub TestCoreControllerWithMockLog()
119: AddMockLoggerSimple()
120: CreateSQLCacheInstance()
121: Dim Controller1 As New CoreLinux.TestController(AuWcf1, MockLog, InMemoryDBContext1, SQLCache1)
122: Dim Response As IActionResult = Controller1.Index()
123: Dim Content As ContentResult = Response
124: TestContext.WriteLine(Content.Content)
125: Assert.AreEqual(Content.ContentType, "text/html")
126: End Sub
127:
128: <Test>
129: Public Sub AddRealLogger()
130: CreateAuWcfInstance()
131: Dim _LoggerFactory = LoggerFactory.Create(Sub(Builder) Builder.AddConsole())
132: RealLog = _LoggerFactory.CreateLogger(Of CoreLinux.TestController)
133: CoreDIserviceCollection.AddSingleton(GetType(ILogger(Of TestController)), RealLog)
134: RealLog.LogInformation("Test RealLog")
135: ShowServive()
136: End Sub
137:
138: <Test>
139: Public Sub TestCoreControllerWithRealLog()
140: AddRealLogger()
141: CreateInMemoryDbInstance()
142: CreateSQLCacheInstance()
143: Dim Controller1 As New CoreLinux.TestController(AuWcf1, RealLog, InMemoryDBContext1, SQLCache1)
144: Dim Response As IActionResult = Controller1.Index()
145: Dim Content As ContentResult = Response
146: TestContext.WriteLine(Content.Content)
147: Assert.AreEqual(Content.ContentType, "text/html")
148: End Sub
149:
150: End Class
151:
152: End Namespace
As you can see, memory cache in Linux machine with data from SQL2005 working perfectly:
17. Integration test to write data to remote SQL2005.
And finally I want to return to my first screen on top of this post - this is my integration test to write data from Core Linux daemon to remote SQL2005.
Its a really fantastic - Linux daemon has permanent connection to MS SQL2005 and read (with cache) and write data to MS SQL2005. Also this project compose many different layer and each layer need to be testing separately, therefore I have decided write down particular post about TDD (test driven development) on the example of this project TDD in Core Linux (Middleware, IdentityServer, SignalR, Quartz, RabbitMQ, Redis and so on).
18. Remote debugging and monitoring
|