<commit_before>﻿namespace EnumerableTest.Runner

open System
open System.IO
open System.Reactive.Disposables
open System.Reactive.Subjects
open System.Reflection
open System.Threading
open System.Threading.Tasks
open Basis.Core

module private OneshotTestAssemblyCore =
  let loadSchema (assemblyName: AssemblyName) () =
    Result.catch (fun () -> Assembly.Load(assemblyName))
    |> Result.map TestSuiteSchema.ofAssembly

  let load (assemblyName: AssemblyName) marshalValueRecursion observer () =
    MarshalValue.Recursion <- marshalValueRecursion
    try
      let assembly = Assembly.Load(assemblyName)
      let connectable =
        TestRunner.runTestAssembly assembly
      connectable.Subscribe(observer) |> ignore<IDisposable>
      connectable.Connect() |> ignore
      Success ()
    with
    | e ->
      Failure e

[<Sealed>]
type OneshotTestAssembly(assemblyName, domain, testSuiteSchema) =
  inherit TestAssembly()

  let resource =
    new CompositeDisposable()

  do resource.Add(domain)

  let testResults =
    new Subject<TestResult>()

  do
    Disposable.Create
      (fun () ->
        testResults.OnCompleted()
        testResults.Dispose()
      )
    |> resource.Add

  let mutable isTerminated = false

  do
    // When all tests terminated, dispose this itself.
    let period = TimeSpan.FromMilliseconds(17.0)
    let onTick _ = if isTerminated then resource.Dispose()
    let timer = new Timer(onTick, (), period, period)
    resource.Add(timer)

  let resultObserver =
    { new IObserver<TestResult> with
        override this.OnNext(value) =
          testResults.OnNext(value)
        override this.OnError(e) =
          isTerminated <- true
        override this.OnCompleted() =
          isTerminated <- true
    } |> MarshalByRefObserver.ofObserver

  let start () =
    let f =
      OneshotTestAssemblyCore.load assemblyName MarshalValue.Recursion resultObserver
    let result =
      (domain: AppDomain.DisposableAppDomain).Value |> AppDomain.run f
    match result with
    | Success () ->
      ()
    | Failure _ ->
      resource.Dispose()

  member this.AssemblyName =
    assemblyName

  member this.Schema =
    testSuiteSchema

  override this.TestCompleted =
    testResults :> IObservable<_>

  override this.Start() =
    start ()

  override this.Dispose() =
    resource.Dispose()

[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]  
module OneshotTestAssembly =
  let ofFile (file: FileInfo) =
    result {
      let! assemblyName =
        Result.catch (fun () -> AssemblyName.GetAssemblyName(file.FullName))
      let domain =
        sprintf "EnumerableTest.Runner[%s]#%d" assemblyName.Name (Counter.generate ())
        |> AppDomain.create
      let! schema = domain.Value |> AppDomain.run (OneshotTestAssemblyCore.loadSchema assemblyName)
      return new OneshotTestAssembly(assemblyName, domain, schema)
    }<commit_msg>Rename a field<commit_after>﻿namespace EnumerableTest.Runner

open System
open System.IO
open System.Reactive.Disposables
open System.Reactive.Subjects
open System.Reflection
open System.Threading
open System.Threading.Tasks
open Basis.Core

module private OneshotTestAssemblyCore =
  let loadSchema (assemblyName: AssemblyName) () =
    Result.catch (fun () -> Assembly.Load(assemblyName))
    |> Result.map TestSuiteSchema.ofAssembly

  let load (assemblyName: AssemblyName) marshalValueRecursion observer () =
    MarshalValue.Recursion <- marshalValueRecursion
    try
      let assembly = Assembly.Load(assemblyName)
      let connectable =
        TestRunner.runTestAssembly assembly
      connectable.Subscribe(observer) |> ignore<IDisposable>
      connectable.Connect() |> ignore
      Success ()
    with
    | e ->
      Failure e

[<Sealed>]
type OneshotTestAssembly(assemblyName, domain, testSuiteSchema) =
  inherit TestAssembly()

  let resource =
    new CompositeDisposable()

  do resource.Add(domain)

  let testCompleted =
    new Subject<TestResult>()

  do
    Disposable.Create
      (fun () ->
        testCompleted.OnCompleted()
        testCompleted.Dispose()
      )
    |> resource.Add

  let mutable isTerminated = false

  do
    // When all tests terminated, dispose this itself.
    let period = TimeSpan.FromMilliseconds(17.0)
    let onTick _ = if isTerminated then resource.Dispose()
    let timer = new Timer(onTick, (), period, period)
    resource.Add(timer)

  let resultObserver =
    { new IObserver<TestResult> with
        override this.OnNext(value) =
          testCompleted.OnNext(value)
        override this.OnError(e) =
          isTerminated <- true
        override this.OnCompleted() =
          isTerminated <- true
    } |> MarshalByRefObserver.ofObserver

  let start () =
    let f =
      OneshotTestAssemblyCore.load assemblyName MarshalValue.Recursion resultObserver
    let result =
      (domain: AppDomain.DisposableAppDomain).Value |> AppDomain.run f
    match result with
    | Success () ->
      ()
    | Failure _ ->
      resource.Dispose()

  member this.AssemblyName =
    assemblyName

  member this.Schema =
    testSuiteSchema

  override this.TestCompleted =
    testCompleted :> IObservable<_>

  override this.Start() =
    start ()

  override this.Dispose() =
    resource.Dispose()

[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]  
module OneshotTestAssembly =
  let ofFile (file: FileInfo) =
    result {
      let! assemblyName =
        Result.catch (fun () -> AssemblyName.GetAssemblyName(file.FullName))
      let domain =
        sprintf "EnumerableTest.Runner[%s]#%d" assemblyName.Name (Counter.generate ())
        |> AppDomain.create
      let! schema = domain.Value |> AppDomain.run (OneshotTestAssemblyCore.loadSchema assemblyName)
      return new OneshotTestAssembly(assemblyName, domain, schema)
    }
{'fraction_non_alphanumeric': 0.09154808846219784, 'fraction_numerical': 0.001028630207440425, 'mean_word_length': 3.182078853046595, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1680405', 'n_tokens_mistral': 1700, 'n_tokens_neox': 1636, 'n_words': 382}