1+ module TaskSeq.Tests.DebugUtils
2+
3+ open Xunit
4+ open FsUnit.Xunit
5+ open System
6+ open System.IO
7+ open System.Threading
8+ open FSharp.Control
9+
10+ //
11+ // Tests for FSharp.Control.Debug logging functionality
12+ //
13+
14+ module VerboseSettings =
15+ [<Fact>]
16+ let ``Debug verbose setting defaults to false when env var not set`` () =
17+ // Clear environment variable
18+ Environment.SetEnvironmentVariable( " TASKSEQ_LOG_VERBOSE" , null )
19+
20+ // Force reinit of the setting by accessing private field via reflection
21+ let debugType = typeof< Debug>
22+ let verboseField = debugType.GetField( " verbose" , System.Reflection.BindingFlags.NonPublic ||| System.Reflection.BindingFlags.Static)
23+ verboseField.SetValue( null , None)
24+
25+ // Test by calling logInfo and verifying no output in release builds
26+ Debug.logInfo( " test message" )
27+
28+ // In release builds, this should be a no-op
29+ // In debug builds, we can't easily capture console output, but the method should not throw
30+ Assert.True( true ) // Test passes if no exception thrown
31+
32+ [<Theory>]
33+ [<InlineData( " 1" , true ) >]
34+ [<InlineData( " true" , true ) >]
35+ [<InlineData( " TRUE" , true ) >]
36+ [<InlineData( " on" , true ) >]
37+ [<InlineData( " ON" , true ) >]
38+ [<InlineData( " yes" , true ) >]
39+ [<InlineData( " YES" , true ) >]
40+ [<InlineData( " 0" , false ) >]
41+ [<InlineData( " false" , false ) >]
42+ [<InlineData( " off" , false ) >]
43+ [<InlineData( " no" , false ) >]
44+ [<InlineData( " invalid" , false ) >]
45+ [<InlineData( " " , false ) >]
46+ [<InlineData( " 1 " , true ) >]
47+ let ``Debug verbose setting parses environment variable correctly`` envValue expectedResult =
48+ // Set environment variable
49+ Environment.SetEnvironmentVariable( " TASKSEQ_LOG_VERBOSE" , envValue)
50+
51+ try
52+ // Force reinit of the setting by accessing private field via reflection
53+ let debugType = typeof< Debug>
54+ let verboseField = debugType.GetField( " verbose" , System.Reflection.BindingFlags.NonPublic ||| System.Reflection.BindingFlags.Static)
55+ verboseField.SetValue( null , None)
56+
57+ // Test by calling getVerboseSetting via reflection
58+ let getVerboseMethod = debugType.GetMethod( " getVerboseSetting" , System.Reflection.BindingFlags.NonPublic ||| System.Reflection.BindingFlags.Static)
59+ let result = getVerboseMethod.Invoke( null , [||]) :?> bool
60+
61+ result |> should equal expectedResult
62+ finally
63+ // Clean up
64+ Environment.SetEnvironmentVariable( " TASKSEQ_LOG_VERBOSE" , null )
65+
66+ [<Fact>]
67+ let ``Debug verbose setting caches result after first call`` () =
68+ // Set environment variable
69+ Environment.SetEnvironmentVariable( " TASKSEQ_LOG_VERBOSE" , " 1" )
70+
71+ try
72+ // Force reinit of the setting
73+ let debugType = typeof< Debug>
74+ let verboseField = debugType.GetField( " verbose" , System.Reflection.BindingFlags.NonPublic ||| System.Reflection.BindingFlags.Static)
75+ verboseField.SetValue( null , None)
76+
77+ // Get verbose setting via reflection
78+ let getVerboseMethod = debugType.GetMethod( " getVerboseSetting" , System.Reflection.BindingFlags.NonPublic ||| System.Reflection.BindingFlags.Static)
79+ let result1 = getVerboseMethod.Invoke( null , [||]) :?> bool
80+
81+ // Change environment variable
82+ Environment.SetEnvironmentVariable( " TASKSEQ_LOG_VERBOSE" , " 0" )
83+
84+ // Call again - should return cached result
85+ let result2 = getVerboseMethod.Invoke( null , [||]) :?> bool
86+
87+ result1 |> should equal true
88+ result2 |> should equal true // Should be cached value, not re-read from env
89+ finally
90+ // Clean up
91+ Environment.SetEnvironmentVariable( " TASKSEQ_LOG_VERBOSE" , null )
92+
93+ module LoggingMethods =
94+ [<Fact>]
95+ let ``Debug logInfo with single parameter does not throw`` () =
96+ Debug.logInfo( " Simple log message" )
97+ // Test passes if no exception thrown
98+ Assert.True( true )
99+
100+ [<Fact>]
101+ let ``Debug logInfo with data parameter does not throw`` () =
102+ Debug.logInfo( " Log message with data: " , 42 )
103+ // Test passes if no exception thrown
104+ Assert.True( true )
105+
106+ [<Fact>]
107+ let ``Debug logInfo with null string does not throw`` () =
108+ Debug.logInfo( null )
109+ // Test passes if no exception thrown
110+ Assert.True( true )
111+
112+ [<Fact>]
113+ let ``Debug logInfo with empty string does not throw`` () =
114+ Debug.logInfo( " " )
115+ // Test passes if no exception thrown
116+ Assert.True( true )
117+
118+ [<Fact>]
119+ let ``Debug logInfo with complex data does not throw`` () =
120+ let complexData = {| Name = " test" ; Values = [ 1 ; 2 ; 3 ] |}
121+ Debug.logInfo( " Complex data: " , complexData)
122+ // Test passes if no exception thrown
123+ Assert.True( true )
124+
125+ module ExceptionHandling =
126+ [<Fact>]
127+ let ``Debug handles environment variable access exceptions gracefully`` () =
128+ // This test verifies that if Environment.GetEnvironmentVariable throws,
129+ // the Debug class handles it gracefully and defaults to false
130+ // We can't easily force an exception here, but we can test the method doesn't throw
131+ try
132+ // Force reinit and call getVerboseSetting
133+ let debugType = typeof< Debug>
134+ let verboseField = debugType.GetField( " verbose" , System.Reflection.BindingFlags.NonPublic ||| System.Reflection.BindingFlags.Static)
135+ verboseField.SetValue( null , None)
136+
137+ let getVerboseMethod = debugType.GetMethod( " getVerboseSetting" , System.Reflection.BindingFlags.NonPublic ||| System.Reflection.BindingFlags.Static)
138+ let result = getVerboseMethod.Invoke( null , [||]) :?> bool
139+
140+ // Should not throw and should return a boolean value
141+ result |> should be instanceOfType< bool>
142+ with
143+ | ex ->
144+ // Test should fail if an exception is thrown
145+ Assert.Fail( $" Debug.getVerboseSetting should not throw exceptions: {ex.Message}" )
0 commit comments