Integrate typed SSD self-test fixtures

ober

c88dab64f3e722ce825e6132f0c93ae1d073c0f3

diff --git a/templates/ssd-review-parts/main-self-test.ss b/templates/ssd-review-parts/main-self-test.ss
new file mode 100644
index 0000000..a9d52bc
--- /dev/null
+++ b/templates/ssd-review-parts/main-self-test.ss
@@ -0,0 +1,413 @@
+(import (jerboa prelude))
+
+(def fragment
+  '((typed-kotlin-file "com/sfb/ssdreview/MainSelfTest.kt"
+      (kotlin-imports (android content Intent)
+                      (android graphics Bitmap)
+                      (android net Uri)
+                      (java lang IllegalStateException)
+                      (org json JSONObject))
+      (typed-library (com sfb ssdreview)
+        (export mainSelfTestInitialize mainSelfTestEnabled
+                mainSelfTestInstallFixture mainSelfTestLog)
+        (type Bitmap)
+        (type Exception)
+        (type IllegalStateException)
+        (type Int32)
+        (type Intent)
+        (type JSONObject)
+        (type MainActivity)
+        (type SfbServerCatalog)
+        (type SfbServerClient)
+        (type SfbServerInfo)
+        (type SfbServerPdf)
+        (type SsdReviewView)
+        (type SsdSelfTestFixture)
+        (type SsdSelfTestMode)
+        (type SsdSession)
+        (type TruthStore)
+        (type Uri)
+        (type ViewportState)
+        (extern (mainSelfTestIntent
+                  (activity : MainActivity)) : Intent
+          (kotlin-member-get intent))
+        (extern (mainSelfTestModeFromIntent
+                  (intent : Intent)) : SsdSelfTestMode
+          (kotlin-call ssdSelfTestModeFromIntent))
+        (extern (mainSelfTestMode
+                  (activity : MainActivity)) : SsdSelfTestMode
+          (kotlin-member-get selfTestModeState))
+        (extern (mainSelfTestModeSet
+                  (activity : MainActivity)
+                  (mode : SsdSelfTestMode)) : Unit
+          (kotlin-member-set selfTestModeState))
+        (extern (mainSelfTestModeEnabled
+                  (mode : SsdSelfTestMode)) : Bool
+          (kotlin-member-get enabled))
+        (extern (mainSelfTestModeServerLabels
+                  (mode : SsdSelfTestMode)) : Bool
+          (kotlin-member-get serverLabels))
+        (extern (mainSelfTestMakeFixture
+                  (mode : SsdSelfTestMode)) : SsdSelfTestFixture
+          (kotlin-call makeSelfTestFixture))
+        (extern (mainSelfTestFixtureKind
+                  (fixture : SsdSelfTestFixture)) : String
+          (kotlin-member-get kind))
+        (extern (mainSelfTestFixturePdfName
+                  (fixture : SsdSelfTestFixture)) : String
+          (kotlin-member-get pdfName))
+        (extern (mainSelfTestFixturePdfSha1
+                  (fixture : SsdSelfTestFixture)) : String
+          (kotlin-member-get pdfSha1))
+        (extern (mainSelfTestFixturePageIndex
+                  (fixture : SsdSelfTestFixture)) : Int32
+          (kotlin-member-get pageIndex))
+        (extern (mainSelfTestFixturePageCount
+                  (fixture : SsdSelfTestFixture)) : Int32
+          (kotlin-member-get pageCount))
+        (extern (mainSelfTestFixtureSourceUri
+                  (fixture : SsdSelfTestFixture)) : String
+          (kotlin-member-get sourceUri))
+        (extern (mainSelfTestFixtureBitmap
+                  (fixture : SsdSelfTestFixture)) : Bitmap
+          (kotlin-member-get bitmap))
+        (extern (mainSelfTestFixtureSession
+                  (fixture : SsdSelfTestFixture)) : SsdSession
+          (kotlin-member-get session))
+        (extern (mainSelfTestFixtureSelected
+                  (fixture : SsdSelfTestFixture)) : (Nullable String)
+          (kotlin-member-get selectedGroupId))
+        (extern (mainSelfTestFixtureStatus
+                  (fixture : SsdSelfTestFixture)) : String
+          (kotlin-member-get status))
+        (extern (mainSelfTestFixtureStage
+                  (fixture : SsdSelfTestFixture)) : String
+          (kotlin-member-get stage))
+        (extern (mainSelfTestUriParse (text : String)) : Uri
+          (kotlin-call Uri parse))
+        (extern (mainSelfTestTruthStore
+                  (activity : MainActivity)) : TruthStore
+          (kotlin-member-get truthStore))
+        (extern (mainSelfTestReviewView
+                  (activity : MainActivity)) : SsdReviewView
+          (kotlin-member-get reviewView))
+        (extern (mainSelfTestTruthApply
+                  (store : TruthStore)
+                  (session : SsdSession)) : Unit
+          (kotlin-member-call applyTruth))
+        (extern (mainSelfTestProposalJson
+                  (session : SsdSession)) : JSONObject
+          (kotlin-call selfTestProposalJson))
+        (extern (mainSelfTestSaveProposal
+                  (store : TruthStore)
+                  (proposal : JSONObject)) : File
+          (kotlin-call truthStoreSaveProposalSnapshotForSelfTest))
+        (type File)
+        (extern (mainSelfTestPdfUriSet
+                  (activity : MainActivity)
+                  (uri : (Nullable Uri))) : Unit
+          (kotlin-member-set pdfUri))
+        (extern (mainSelfTestPdfNameSet
+                  (activity : MainActivity)
+                  (name : String)) : Unit
+          (kotlin-member-set pdfName))
+        (extern (mainSelfTestPdfSha1Set
+                  (activity : MainActivity)
+                  (sha1 : String)) : Unit
+          (kotlin-member-set pdfSha1))
+        (extern (mainSelfTestPageIndexSet
+                  (activity : MainActivity)
+                  (page : Int32)) : Unit
+          (kotlin-member-set pageIndex))
+        (extern (mainSelfTestPageCountSet
+                  (activity : MainActivity)
+                  (count : Int32)) : Unit
+          (kotlin-member-set pageCount))
+        (extern (mainSelfTestBitmapSet
+                  (activity : MainActivity)
+                  (bitmap : (Nullable Bitmap))) : Unit
+          (kotlin-member-set currentBitmap))
+        (extern (mainSelfTestSessionSet
+                  (activity : MainActivity)
+                  (session : (Nullable SsdSession))) : Unit
+          (kotlin-member-set currentSession))
+        (extern (mainSelfTestSelectedSet
+                  (activity : MainActivity)
+                  (selected : (Nullable String))) : Unit
+          (kotlin-member-set selectedGroupId))
+        (extern (mainSelfTestServerPdfIdSet
+                  (activity : MainActivity)
+                  (pdfId : String)) : Unit
+          (kotlin-member-set serverPdfId))
+        (extern (mainSelfTestLoadGeneration
+                  (activity : MainActivity)) : Int32
+          (kotlin-member-get loadGeneration))
+        (extern (mainSelfTestLoadGenerationSet
+                  (activity : MainActivity)
+                  (generation : Int32)) : Unit
+          (kotlin-member-set loadGeneration))
+        (extern (mainSelfTestViewBitmapSet
+                  (view : SsdReviewView)
+                  (bitmap : (Nullable Bitmap))) : Unit
+          (kotlin-member-set bitmap))
+        (extern (mainSelfTestViewSessionSet
+                  (view : SsdReviewView)
+                  (session : (Nullable SsdSession))) : Unit
+          (kotlin-member-set session))
+        (extern (mainSelfTestViewSelectedSet
+                  (view : SsdReviewView)
+                  (selected : (Nullable String))) : Unit
+          (kotlin-member-set selectedGroupId))
+        (extern (mainSelfTestSessionArea
+                  (session : SsdSession)) : (Nullable FloatArray)
+          (kotlin-member-get ssdArea))
+        (type FloatArray)
+        (extern (mainSelfTestViewAreaSet
+                  (view : SsdReviewView)
+                  (area : (Nullable FloatArray))) : Unit
+          (kotlin-member-set ssdArea))
+        (extern (mainSelfTestViewInvalidate
+                  (view : SsdReviewView)) : Unit
+          (kotlin-member-call invalidate))
+        (extern (mainSelfTestViewSelectMode
+                  (view : SsdReviewView)) : Bool
+          (kotlin-member-get selectMode))
+        (extern (mainSelfTestViewViewport
+                  (view : SsdReviewView)) : (Nullable ViewportState)
+          (kotlin-member-call captureViewport))
+        (extern (mainSelfTestAppendMode
+                  (activity : MainActivity)) : Bool
+          (kotlin-member-get appendMode))
+        (extern (mainSelfTestSsdAreaMode
+                  (activity : MainActivity)) : Bool
+          (kotlin-member-get ssdAreaMode))
+        (extern (mainSelfTestCurrentSession
+                  (activity : MainActivity)) : (Nullable SsdSession)
+          (kotlin-member-get currentSession))
+        (extern (mainSelfTestSelected
+                  (activity : MainActivity)) : (Nullable String)
+          (kotlin-member-get selectedGroupId))
+        (extern (mainSelfTestCurrentBitmap
+                  (activity : MainActivity)) : (Nullable Bitmap)
+          (kotlin-member-get currentBitmap))
+        (extern (mainSelfTestSetStatus
+                  (activity : MainActivity)
+                  (status : String)) : Unit
+          (kotlin-call mainActivitySetStatusRaw))
+        (extern (mainSelfTestLogState
+                  (enabled : Bool)
+                  (stage : String)
+                  (session : (Nullable SsdSession))
+                  (selected : (Nullable String))
+                  (selectMode : Bool)
+                  (appendMode : Bool)
+                  (ssdAreaMode : Bool)
+                  (viewport : (Nullable ViewportState))
+                  (bitmap : (Nullable Bitmap))
+                  (logger : (-> String JSONObject Unit))) : Unit
+          (kotlin-call logSelfTestState))
+        (extern (mainSelfTestLogEvent
+                  (activity : MainActivity)
+                  (event : String)
+                  (fields : JSONObject)) : Unit
+          (kotlin-call mainActivityLogClientEvent))
+        (extern (mainSelfTestRunBackground
+                  (name : String)
+                  (action : (-> Unit))) : Unit
+          (kotlin-call runBackgroundNamed))
+        (extern (mainSelfTestRunOnUi
+                  (activity : MainActivity)
+                  (action : (-> Unit))) : Unit
+          (kotlin-member-call runOnUiThread))
+        (extern (mainSelfTestServerClient
+                  (activity : MainActivity)) : SfbServerClient
+          (kotlin-member-get serverClient))
+        (extern (mainSelfTestServerRefresh
+                  (client : SfbServerClient)) : SfbServerInfo
+          (kotlin-member-call refreshServerEndpoint))
+        (extern (mainSelfTestServerCatalog
+                  (client : SfbServerClient)) : SfbServerCatalog
+          (kotlin-member-call fetchServerPdfs))
+        (extern (mainSelfTestCatalogPdfs
+                  (catalog : SfbServerCatalog)) : (List SfbServerPdf)
+          (kotlin-member-get pdfs))
+        (extern (mainSelfTestServerPdfId
+                  (pdf : SfbServerPdf)) : String
+          (kotlin-member-get pdfId))
+        (extern (mainSelfTestServerPdfName
+                  (pdf : SfbServerPdf)) : String
+          (kotlin-member-get name))
+        (extern (mainSelfTestServerPdfPages
+                  (pdf : SfbServerPdf)) : Int32
+          (kotlin-member-get pageCount))
+        (extern (mainSelfTestRenderServerPage
+                  (activity : MainActivity)
+                  (uri : Uri)) : Unit
+          (kotlin-call mainServerRenderCurrentPage))
+        (extern (mainSelfTestException
+                  (message : String)) : IllegalStateException
+          (kotlin-call IllegalStateException))
+        (extern (mainSelfTestExceptionMessage
+                  (error : Exception)) : (Nullable String)
+          (kotlin-member-get message))
+        (def (mainSelfTestInitialize (activity : MainActivity)) : Unit
+          (mainSelfTestModeSet
+            activity
+            (mainSelfTestModeFromIntent (mainSelfTestIntent activity))))
+        (def (mainSelfTestEnabled (activity : MainActivity)) : Bool
+          (mainSelfTestModeEnabled (mainSelfTestMode activity)))
+        (def (mainSelfTestLog
+               (activity : MainActivity)
+               (stage : String)) : Unit
+          (let ((view (mainSelfTestReviewView activity)))
+            (mainSelfTestLogState
+              (mainSelfTestEnabled activity)
+              stage
+              (mainSelfTestCurrentSession activity)
+              (mainSelfTestSelected activity)
+              (mainSelfTestViewSelectMode view)
+              (mainSelfTestAppendMode activity)
+              (mainSelfTestSsdAreaMode activity)
+              (mainSelfTestViewViewport view)
+              (mainSelfTestCurrentBitmap activity)
+              (lambda ((event : String) (fields : JSONObject))
+                (mainSelfTestLogEvent activity event fields)))))
+        (def (mainSelfTestFindPdf
+               (pdfs : (List SfbServerPdf))
+               (name : String)) : (Nullable SfbServerPdf)
+          (for/fold
+            ((found (nullable-none SfbServerPdf)))
+            ((i (in-range (int32 0) (list-size pdfs))))
+            (if (not (nullable-null? found))
+              found
+              (let ((pdf (list-ref pdfs i)))
+                (if (equal?
+                      (string-lowercase (string-trim (mainSelfTestServerPdfName pdf)))
+                      (string-lowercase (string-trim name)))
+                  (nullable-some pdf)
+                  found)))))
+        (def (mainSelfTestErrorText (error : Exception)) : String
+          (let ((message (mainSelfTestExceptionMessage error)))
+            (if (nullable-null? message) "unknown" (nullable-get message))))
+        (def (mainSelfTestStartServerLabels
+               (activity : MainActivity)
+               (expectedName : String)) : Unit
+          (let ((generation (+ (mainSelfTestLoadGeneration activity) (int32 1))))
+            (begin
+              (mainSelfTestLoadGenerationSet activity generation)
+              (mainSelfTestRunBackground
+                "ssd-selftest-server-labels"
+                (lambda ()
+                  (try
+                    (let ((client (mainSelfTestServerClient activity)))
+                      (begin
+                        (mainSelfTestServerRefresh client)
+                        (let ((matched
+                                (mainSelfTestFindPdf
+                                  (mainSelfTestCatalogPdfs
+                                    (mainSelfTestServerCatalog client))
+                                  expectedName)))
+                          (if (nullable-null? matched)
+                            (throw
+                              (mainSelfTestException
+                                "Self-test server PDF was not found")
+                              Unit)
+                            (let ((pdf (nullable-get matched)))
+                              (mainSelfTestRunOnUi
+                                activity
+                                (lambda ()
+                                  (if (equal?
+                                        generation
+                                        (mainSelfTestLoadGeneration activity))
+                                    (let ((pdfId (mainSelfTestServerPdfId pdf))
+                                          (count
+                                            (if (> (mainSelfTestServerPdfPages pdf)
+                                                   (int32 0))
+                                              (mainSelfTestServerPdfPages pdf)
+                                              (int32 1))))
+                                      (let ((uri
+                                              (mainSelfTestUriParse
+                                                (string-append "sfbserver:" pdfId))))
+                                        (begin
+                                          (mainSelfTestServerPdfIdSet activity pdfId)
+                                          (mainSelfTestPdfNameSet
+                                            activity
+                                            (mainSelfTestServerPdfName pdf))
+                                          (mainSelfTestPdfSha1Set activity pdfId)
+                                          (mainSelfTestPageCountSet activity count)
+                                          (mainSelfTestPageIndexSet
+                                            activity
+                                            (if (> count (int32 1))
+                                              (int32 1)
+                                              (int32 0)))
+                                          (mainSelfTestPdfUriSet
+                                            activity
+                                            (nullable-some uri))
+                                          (mainSelfTestRenderServerPage
+                                            activity uri))))
+                                    (begin)))))))))
+                    (catch (error : Exception)
+                      (mainSelfTestRunOnUi
+                        activity
+                        (lambda ()
+                          (mainSelfTestSetStatus
+                            activity
+                            (string-append
+                              "SELFTEST_SERVER_PAGE_FAILED "
+                              (mainSelfTestErrorText error))))))))))))
+        (def (mainSelfTestInstallFixture
+               (activity : MainActivity)) : Bool
+          (if (not (mainSelfTestEnabled activity))
+            #f
+            (let ((fixture
+                    (mainSelfTestMakeFixture (mainSelfTestMode activity))))
+              (let ((session (mainSelfTestFixtureSession fixture))
+                    (bitmap (mainSelfTestFixtureBitmap fixture))
+                    (selected (mainSelfTestFixtureSelected fixture))
+                    (view (mainSelfTestReviewView activity)))
+                (begin
+                  (if (equal? (mainSelfTestFixtureKind fixture) "review")
+                    (mainSelfTestTruthApply
+                      (mainSelfTestTruthStore activity)
+                      session)
+                    (if (equal? (mainSelfTestFixtureKind fixture) "ocr")
+                      (begin
+                        (mainSelfTestSaveProposal
+                          (mainSelfTestTruthStore activity)
+                          (mainSelfTestProposalJson session))
+                        (begin))
+                      (begin)))
+                  (mainSelfTestPdfNameSet
+                    activity (mainSelfTestFixturePdfName fixture))
+                  (mainSelfTestPdfSha1Set
+                    activity (mainSelfTestFixturePdfSha1 fixture))
+                  (mainSelfTestPageIndexSet
+                    activity (mainSelfTestFixturePageIndex fixture))
+                  (mainSelfTestPageCountSet
+                    activity (mainSelfTestFixturePageCount fixture))
+                  (mainSelfTestPdfUriSet
+                    activity
+                    (nullable-some
+                      (mainSelfTestUriParse
+                        (mainSelfTestFixtureSourceUri fixture))))
+                  (mainSelfTestBitmapSet activity (nullable-some bitmap))
+                  (mainSelfTestSessionSet activity (nullable-some session))
+                  (mainSelfTestSelectedSet activity selected)
+                  (mainSelfTestViewBitmapSet view (nullable-some bitmap))
+                  (mainSelfTestViewSessionSet view (nullable-some session))
+                  (mainSelfTestViewSelectedSet view selected)
+                  (mainSelfTestViewAreaSet view (mainSelfTestSessionArea session))
+                  (mainSelfTestViewInvalidate view)
+                  (mainSelfTestSetStatus
+                    activity
+                    (mainSelfTestFixtureStatus fixture))
+                  (mainSelfTestLog
+                    activity
+                    (mainSelfTestFixtureStage fixture))
+                  (if (mainSelfTestModeServerLabels
+                        (mainSelfTestMode activity))
+                    (mainSelfTestStartServerLabels
+                      activity
+                      (mainSelfTestFixturePdfName fixture))
+                    (begin))
+                  #t)))))))))
diff --git a/templates/ssd-review-parts/main-server-pages.ss b/templates/ssd-review-parts/main-server-pages.ss
index 37190ab..675e63d 100644
--- a/templates/ssd-review-parts/main-server-pages.ss
+++ b/templates/ssd-review-parts/main-server-pages.ss
@@ -362,6 +362,10 @@
                   (activity : MainActivity)
                   (endpoint : String)) : Unit
           (kotlin-call mainServerSetEndpoint))
+        (extern (mainServerPageSelfTestLog
+                  (activity : MainActivity)
+                  (stage : String)) : Unit
+          (kotlin-call mainSelfTestLog))
         (def (mainServerPageErrorText (error : Exception)) : String
           (let ((message (mainServerPageExceptionMessage error)))
             (if (nullable-null? message)
@@ -729,7 +733,10 @@
                       (int32->string
                         (list-size
                           (mainServerPageSessionGroups session)))
-                      " groups")))))
+                      " groups")))
+                (mainServerPageSelfTestLog
+                  activity
+                  "server-labels-applied")))
             (begin)))
         (def (mainServerFetchRecognitionAsync
                (activity : MainActivity)
diff --git a/templates/ssd-review-parts/server-ai.ss b/templates/ssd-review-parts/server-ai.ss
index 86549ee..f0e6927 100644
--- a/templates/ssd-review-parts/server-ai.ss
+++ b/templates/ssd-review-parts/server-ai.ss
@@ -9,4 +9,9 @@
     (include-fragment "main-server-lifecycle.ss")
     (include-fragment "main-server-pages.ss")
     (include-fragment "main-server-detect.ss")
-    (include-fragment "main-ai-flow.ss")))
+    (include-fragment "main-ai-flow.ss")
+    (include-fragment "SsdSelfTestMode.ss")
+    (include-fragment "SsdSelfTestFixture.ss")
+    (include-fragment "SsdSelfTestTelemetry.ss")
+    (include-fragment "TruthStoreSelfTest.ss")
+    (include-fragment "main-self-test.ss")))
diff --git a/templates/ssd-review-selftest-test.ss b/templates/ssd-review-selftest-test.ss
index 5e4d66a..3c826b4 100644
--- a/templates/ssd-review-selftest-test.ss
+++ b/templates/ssd-review-selftest-test.ss
@@ -1,8 +1,4 @@
 (import (jerboa prelude))
 
 (def fragment
-  '((include-fragment "ssd-review.ss")
-    (include-fragment "ssd-review-parts/SsdSelfTestMode.ss")
-    (include-fragment "ssd-review-parts/SsdSelfTestFixture.ss")
-    (include-fragment "ssd-review-parts/SsdSelfTestTelemetry.ss")
-    (include-fragment "ssd-review-parts/TruthStoreSelfTest.ss")))
+  '((include-fragment "ssd-review.ss")))