@@ -3,8 +3,9 @@ import { assert, it } from "@effect/vitest";
33import * as Effect from "effect/Effect" ;
44import * as FileSystem from "effect/FileSystem" ;
55import * as Path from "effect/Path" ;
6+ import * as PlatformError from "effect/PlatformError" ;
67
7- import { resolveUserDataPath } from "./DesktopUserData.ts" ;
8+ import { clearStaleGpuCaches , resolveUserDataPath } from "./DesktopUserData.ts" ;
89
910it . effect . each ( [ "t3code" , "T3 Code (Alpha)" ] ) (
1011 "preserves Windows credential keys from %s without copying browser databases" ,
@@ -40,3 +41,100 @@ it.effect.each(["t3code", "T3 Code (Alpha)"])(
4041 ) ;
4142 } ) . pipe ( Effect . scoped , Effect . provide ( NodeServices . layer ) ) ,
4243) ;
44+
45+ const gpuCacheDirectories = [
46+ "GPUCache" ,
47+ "GrShaderCache" ,
48+ "ShaderCache" ,
49+ "DawnGraphiteCache" ,
50+ "DawnWebGPUCache" ,
51+ "GPUPersistentCache" ,
52+ ] ;
53+
54+ it . effect . each ( [
55+ { profile : "written by Electron 44.10.0" , marker : "44.10.0" } ,
56+ { profile : "with no recorded Electron version" , marker : undefined } ,
57+ ] ) ( "clears GPU caches $profile once when Electron 44.10.1 starts" , ( { marker } ) =>
58+ Effect . gen ( function * ( ) {
59+ const fs = yield * FileSystem . FileSystem ;
60+ const path = yield * Path . Path ;
61+ const userDataPath = yield * fs . makeTempDirectoryScoped ( { prefix : "t3-v2-gpu-cache-" } ) ;
62+ for ( const name of gpuCacheDirectories ) {
63+ yield * fs . makeDirectory ( path . join ( userDataPath , name ) , { recursive : true } ) ;
64+ yield * fs . writeFileString ( path . join ( userDataPath , name , "data_0" ) , "44.10.0 shaders" ) ;
65+ }
66+ yield * fs . makeDirectory ( path . join ( userDataPath , "Local Storage" ) , { recursive : true } ) ;
67+ yield * fs . writeFileString ( path . join ( userDataPath , "Local Storage" , "LOCK" ) , "profile" ) ;
68+ yield * fs . writeFileString ( path . join ( userDataPath , "Local State" ) , "profile" ) ;
69+ if ( marker !== undefined ) {
70+ yield * fs . writeFileString ( path . join ( userDataPath , "gpu-cache-electron-version" ) , marker ) ;
71+ }
72+
73+ yield * clearStaleGpuCaches ( { userDataPath, electronVersion : "44.10.1" } ) ;
74+
75+ const survivingCaches : Array < string > = [ ] ;
76+ for ( const name of gpuCacheDirectories ) {
77+ if ( yield * fs . exists ( path . join ( userDataPath , name ) ) ) survivingCaches . push ( name ) ;
78+ }
79+ assert . deepStrictEqual ( survivingCaches , [ ] ) ;
80+ assert . equal (
81+ yield * fs . readFileString ( path . join ( userDataPath , "Local Storage" , "LOCK" ) ) ,
82+ "profile" ,
83+ ) ;
84+ assert . equal ( yield * fs . readFileString ( path . join ( userDataPath , "Local State" ) ) , "profile" ) ;
85+
86+ yield * fs . makeDirectory ( path . join ( userDataPath , "GPUCache" ) ) ;
87+ yield * fs . writeFileString ( path . join ( userDataPath , "GPUCache" , "data_0" ) , "44.10.1 shaders" ) ;
88+ yield * clearStaleGpuCaches ( { userDataPath, electronVersion : "44.10.1" } ) ;
89+ assert . equal (
90+ yield * fs . readFileString ( path . join ( userDataPath , "GPUCache" , "data_0" ) ) ,
91+ "44.10.1 shaders" ,
92+ ) ;
93+ } ) . pipe ( Effect . scoped , Effect . provide ( NodeServices . layer ) ) ,
94+ ) ;
95+
96+ it . effect ( "keeps GPU caches built on the first launch of a fresh install" , ( ) =>
97+ Effect . gen ( function * ( ) {
98+ const fs = yield * FileSystem . FileSystem ;
99+ const path = yield * Path . Path ;
100+ const appData = yield * fs . makeTempDirectoryScoped ( { prefix : "t3-v2-fresh-" } ) ;
101+ const userDataPath = path . join ( appData , "t3code-v2" ) ;
102+
103+ yield * clearStaleGpuCaches ( { userDataPath, electronVersion : "44.10.1" } ) ;
104+ yield * fs . makeDirectory ( path . join ( userDataPath , "GPUCache" ) ) ;
105+ yield * fs . writeFileString ( path . join ( userDataPath , "GPUCache" , "data_0" ) , "44.10.1 shaders" ) ;
106+ yield * clearStaleGpuCaches ( { userDataPath, electronVersion : "44.10.1" } ) ;
107+
108+ assert . equal (
109+ yield * fs . readFileString ( path . join ( userDataPath , "GPUCache" , "data_0" ) ) ,
110+ "44.10.1 shaders" ,
111+ ) ;
112+ } ) . pipe ( Effect . scoped , Effect . provide ( NodeServices . layer ) ) ,
113+ ) ;
114+
115+ it . effect ( "retries on the next launch when a GPU cache cannot be removed" , ( ) =>
116+ Effect . gen ( function * ( ) {
117+ const writes : Array < string > = [ ] ;
118+ const fileSystem = FileSystem . makeNoop ( {
119+ remove : ( path ) =>
120+ Effect . fail (
121+ PlatformError . systemError ( {
122+ _tag : "PermissionDenied" ,
123+ module : "FileSystem" ,
124+ method : "remove" ,
125+ pathOrDescriptor : path ,
126+ } ) ,
127+ ) ,
128+ writeFileString : ( path ) =>
129+ Effect . sync ( ( ) => {
130+ writes . push ( path ) ;
131+ } ) ,
132+ } ) ;
133+
134+ yield * clearStaleGpuCaches ( { userDataPath : "/profile" , electronVersion : "44.10.1" } ) . pipe (
135+ Effect . provideService ( FileSystem . FileSystem , fileSystem ) ,
136+ ) ;
137+
138+ assert . deepStrictEqual ( writes , [ ] ) ;
139+ } ) . pipe ( Effect . provide ( NodeServices . layer ) ) ,
140+ ) ;
0 commit comments