diff --git a/tests/misc/dune b/tests/misc/dune
new file mode 100644
index 0000000000000000000000000000000000000000..93eae8d4100a7dca3874f32ae2879a7bee91c003
--- /dev/null
+++ b/tests/misc/dune
@@ -0,0 +1,4 @@
+(cram
+  (applies_to user_directories.unix.t)
+  (enabled_if (and (= %{os_type} unix) (<> %{system} macos)))
+)
diff --git a/tests/misc/share_directory.t/directories.ml b/tests/misc/share_directory.t/directories.ml
new file mode 100644
index 0000000000000000000000000000000000000000..4b22ebb1bd6fcaefce14c8189f24f28505fba651
--- /dev/null
+++ b/tests/misc/share_directory.t/directories.ml
@@ -0,0 +1,46 @@
+let () = Plugin.is_share_visible ()
+module Self =
+  Plugin.Register
+    (struct
+      let name = "directories"
+      let shortname = "dirs"
+      let help = ""
+    end)
+
+module Share = Self.Share
+
+let never_fail_get f x =
+  try
+    let s = f x in
+    Self.feedback "Found: %a" Filepath.Normalized.pretty s
+  with _ -> ()
+
+let run_all () =
+  Kernel.feedback "IS_SET %b" (Share.is_set ()) ;
+
+  Self.feedback "path (dir)" ;
+  never_fail_get (Share.get_dir ~mode:`Must_exist) "path" ;
+  never_fail_get Share.get_dir "path" ;
+
+  Self.feedback "path/file.txt (file)" ;
+  never_fail_get (Share.get_file ~mode:`Must_exist) "path/file.txt" ;
+  never_fail_get Share.get_file "path/file.txt" ;
+
+  Self.feedback "foo (dir)" ;
+  never_fail_get (Share.get_dir ~mode:`Must_exist) "foo" ;
+  never_fail_get Share.get_dir "foo" ;
+
+  Self.feedback "foo.txt (file)" ;
+  never_fail_get (Share.get_file ~mode:`Must_exist) "foo.txt" ;
+  never_fail_get Share.get_file "foo.txt" ;
+
+  Self.feedback "path (file)" ;
+  never_fail_get (Share.get_file ~mode:`Must_exist) "path" ;
+  never_fail_get Share.get_file "path" ;
+
+  Self.feedback "path/file.txt" ;
+  never_fail_get (Share.get_dir ~mode:`Must_exist) "path/file.txt" ;
+  never_fail_get Share.get_dir "path/file.txt"
+
+
+let () = Boot.Main.extend run_all
diff --git a/tests/misc/share_directory.t/dune b/tests/misc/share_directory.t/dune
new file mode 100644
index 0000000000000000000000000000000000000000..ac507d4db539126a39a363ee88817bcc25a24083
--- /dev/null
+++ b/tests/misc/share_directory.t/dune
@@ -0,0 +1,18 @@
+(library
+ (name directories)
+ (public_name frama-c-directories.core)
+ (flags -open Frama_c_kernel :standard)
+ (libraries frama-c.kernel))
+
+(plugin
+ (optional)
+ (name directories)
+ (libraries frama-c-directories.core)
+ (site
+  (frama-c plugins)))
+
+(install
+ (package frama-c-directories)
+ (section (site (frama-c share)))
+ (files (share/path/file.txt as dirs/path/file.txt))
+)
diff --git a/tests/misc/share_directory.t/dune-project b/tests/misc/share_directory.t/dune-project
new file mode 100644
index 0000000000000000000000000000000000000000..e7f717f9d792787281dc6871500a2f4c7162ab5c
--- /dev/null
+++ b/tests/misc/share_directory.t/dune-project
@@ -0,0 +1,4 @@
+(lang dune 3.7)
+(using dune_site 0.1)
+(name frama-c-directories)
+(package (name frama-c-directories))
diff --git a/tests/misc/share_directory.t/run.t b/tests/misc/share_directory.t/run.t
new file mode 100644
index 0000000000000000000000000000000000000000..e6a93fda668b524e48239f87587a6eceafe968a9
--- /dev/null
+++ b/tests/misc/share_directory.t/run.t
@@ -0,0 +1,46 @@
+  $ dune build --root . @install
+
+Basic case
+  $ dune exec -- frama-c
+  [kernel] IS_SET false
+  [dirs] path (dir)
+  [dirs] Found: _build/install/default/share/frama-c/share/dirs/path
+  [dirs] Found: _build/install/default/share/frama-c/share/dirs/path
+  [dirs] path/file.txt (file)
+  [dirs] Found: _build/install/default/share/frama-c/share/dirs/path/file.txt
+  [dirs] Found: _build/install/default/share/frama-c/share/dirs/path/file.txt
+  [dirs] foo (dir)
+  [dirs] User Error: Could not find directory foo in Frama-C/directories share
+  [dirs] Found: _build/install/default/share/frama-c/share/dirs/foo
+  [dirs] foo.txt (file)
+  [dirs] User Error: Could not find file foo.txt in Frama-C/directories share
+  [dirs] Found: _build/install/default/share/frama-c/share/dirs/foo.txt
+  [dirs] path (file)
+  [dirs] User Error: _build/install/default/share/frama-c/share/dirs/path is expected to be a file
+  [dirs] User Error: _build/install/default/share/frama-c/share/dirs/path is expected to be a file
+  [dirs] path/file.txt
+  [dirs] User Error: _build/install/default/share/frama-c/share/dirs/path/file.txt is expected to be a directory
+  [dirs] User Error: _build/install/default/share/frama-c/share/dirs/path/file.txt is expected to be a directory
+
+With option
+  $ cp -r share copied
+  $ dune exec -- frama-c -dirs-share copied
+  [kernel] IS_SET true
+  [dirs] path (dir)
+  [dirs] Found: copied/path
+  [dirs] Found: copied/path
+  [dirs] path/file.txt (file)
+  [dirs] Found: copied/path/file.txt
+  [dirs] Found: copied/path/file.txt
+  [dirs] foo (dir)
+  [dirs] User Error: Could not find directory foo in Frama-C/directories share
+  [dirs] Found: copied/foo
+  [dirs] foo.txt (file)
+  [dirs] User Error: Could not find file foo.txt in Frama-C/directories share
+  [dirs] Found: copied/foo.txt
+  [dirs] path (file)
+  [dirs] User Error: copied/path is expected to be a file
+  [dirs] User Error: copied/path is expected to be a file
+  [dirs] path/file.txt
+  [dirs] User Error: copied/path/file.txt is expected to be a directory
+  [dirs] User Error: copied/path/file.txt is expected to be a directory
diff --git a/tests/misc/share_directory.t/share/path/file.txt b/tests/misc/share_directory.t/share/path/file.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/tests/misc/user_directories.unix.t/directories.ml b/tests/misc/user_directories.unix.t/directories.ml
new file mode 100644
index 0000000000000000000000000000000000000000..83d54bde7fcfd2e60214737bc3e6cab1dc63cc89
--- /dev/null
+++ b/tests/misc/user_directories.unix.t/directories.ml
@@ -0,0 +1,49 @@
+let () = Plugin.is_session_visible ()
+module Self =
+  Plugin.Register
+    (struct
+      let name = "directories"
+      let shortname = "dirs"
+      let help = ""
+    end)
+
+module OnlyCache = Self.False(struct
+    let option_name = "-dirs-cache-only"
+    let help = ""
+  end)
+
+module Cache = Self.Cache_dir ()
+module Config = Self.Config_dir ()
+module State = Self.State_dir ()
+module Session = Self.Session
+
+let run_all () =
+  if OnlyCache.get ()
+  then
+    ignore @@ Cache.get_dir ~mode:`Create_path "created"
+  else
+    try
+      ignore @@ Cache.get_dir ~mode:`Create_path "created" ;
+      ignore @@ Config.get_dir ~mode:`Create_path "created" ;
+      ignore @@ State.get_dir ~mode:`Create_path "created" ;
+      ignore @@ Session.get_dir ~mode:`Create_path "created" ;
+      ignore @@ Session.get_file ~mode:`Create_path "created_filepath/file" ;
+
+
+      (* Here: ~mode:`Normalize_only *)
+      let cache_dir = Cache.get_dir "not_created" in
+      let config_dir = Config.get_dir "not_created" in
+      let state_dir = State.get_dir "not_created" in
+      let session_dir = Session.get_dir "not_created" in
+      let session_file = Session.get_file "not_created_filepath/file" in
+
+      Self.feedback "Not created:" ;
+      Self.feedback "%a" Filepath.Normalized.pretty cache_dir ;
+      Self.feedback "%a" Filepath.Normalized.pretty config_dir ;
+      Self.feedback "%a" Filepath.Normalized.pretty state_dir ;
+      Self.feedback "%a" Filepath.Normalized.pretty session_dir ;
+      Self.feedback "%a" Filepath.Normalized.pretty session_file
+    with Not_found ->
+      Self.error "Failure when creating directories"
+
+let () = Boot.Main.extend run_all
diff --git a/tests/misc/user_directories.unix.t/dune b/tests/misc/user_directories.unix.t/dune
new file mode 100644
index 0000000000000000000000000000000000000000..1f56f8e1118d52a2bae86d9f5a3d4f74171d9883
--- /dev/null
+++ b/tests/misc/user_directories.unix.t/dune
@@ -0,0 +1,12 @@
+(library
+ (name directories)
+ (public_name frama-c-directories.core)
+ (flags -open Frama_c_kernel :standard)
+ (libraries frama-c.kernel))
+
+(plugin
+ (optional)
+ (name directories)
+ (libraries frama-c-directories.core)
+ (site
+  (frama-c plugins)))
diff --git a/tests/misc/user_directories.unix.t/dune-project b/tests/misc/user_directories.unix.t/dune-project
new file mode 100644
index 0000000000000000000000000000000000000000..e7f717f9d792787281dc6871500a2f4c7162ab5c
--- /dev/null
+++ b/tests/misc/user_directories.unix.t/dune-project
@@ -0,0 +1,4 @@
+(lang dune 3.7)
+(using dune_site 0.1)
+(name frama-c-directories)
+(package (name frama-c-directories))
diff --git a/tests/misc/user_directories.unix.t/run.t b/tests/misc/user_directories.unix.t/run.t
new file mode 100644
index 0000000000000000000000000000000000000000..ca5529bfe44258bde3bb36408fb0fe07e46ad79a
--- /dev/null
+++ b/tests/misc/user_directories.unix.t/run.t
@@ -0,0 +1,220 @@
+In all these tests please set HOME before executing commands so that it does not
+touch the actual user HOME.
+
+  $ dune build --root . @install
+
+Basic case
+  $ HOME=home dune exec -- frama-c
+  [dirs] Warning: created cache directory `home/.cache/frama-c/dirs/created'
+  [dirs] Warning: created config directory `home/.config/frama-c/dirs/created'
+  [dirs] Warning: created state directory `home/.local/state/frama-c/dirs/created'
+  [dirs] Warning: created session directory `.frama-c/dirs/created'
+  [dirs] Warning: created session directory `.frama-c/dirs/created_filepath'
+  [dirs] Not created:
+  [dirs] home/.cache/frama-c/dirs/not_created
+  [dirs] home/.config/frama-c/dirs/not_created
+  [dirs] home/.local/state/frama-c/dirs/not_created
+  [dirs] .frama-c/dirs/not_created
+  [dirs] .frama-c/dirs/not_created_filepath/file
+  $ find home
+  home
+  home/.cache
+  home/.cache/frama-c
+  home/.cache/frama-c/dirs
+  home/.cache/frama-c/dirs/created
+  home/.local
+  home/.local/state
+  home/.local/state/frama-c
+  home/.local/state/frama-c/dirs
+  home/.local/state/frama-c/dirs/created
+  home/.config
+  home/.config/frama-c
+  home/.config/frama-c/dirs
+  home/.config/frama-c/dirs/created
+  $ rm -rf home
+
+Customized via variables: XDG level
+  $ HOME=home XDG_CACHE_HOME=cache XDG_CONFIG_HOME=config XDG_STATE_HOME=state dune exec -- frama-c
+  [dirs] Warning: created cache directory `cache/frama-c/dirs/created'
+  [dirs] Warning: created config directory `config/frama-c/dirs/created'
+  [dirs] Warning: created state directory `state/frama-c/dirs/created'
+  [dirs] Not created:
+  [dirs] cache/frama-c/dirs/not_created
+  [dirs] config/frama-c/dirs/not_created
+  [dirs] state/frama-c/dirs/not_created
+  [dirs] .frama-c/dirs/not_created
+  [dirs] .frama-c/dirs/not_created_filepath/file
+  $ find home
+  find: 'home': No such file or directory
+  [1]
+  $ find cache
+  cache
+  cache/frama-c
+  cache/frama-c/dirs
+  cache/frama-c/dirs/created
+  $ find config
+  config
+  config/frama-c
+  config/frama-c/dirs
+  config/frama-c/dirs/created
+  $ find state
+  state
+  state/frama-c
+  state/frama-c/dirs
+  state/frama-c/dirs/created
+  $ rm -rf home cache config state
+
+Customized via variables: Kernel level
+  $ HOME=home FRAMAC_CACHE=cache FRAMAC_CONFIG=config FRAMAC_STATE=state FRAMAC_SESSION=session dune exec -- frama-c
+  [dirs] Warning: created cache directory `cache/dirs/created'
+  [dirs] Warning: created config directory `config/dirs/created'
+  [dirs] Warning: created state directory `state/dirs/created'
+  [dirs] Warning: created session directory `session/dirs/created'
+  [dirs] Warning: created session directory `session/dirs/created_filepath'
+  [dirs] Not created:
+  [dirs] cache/dirs/not_created
+  [dirs] config/dirs/not_created
+  [dirs] state/dirs/not_created
+  [dirs] session/dirs/not_created
+  [dirs] session/dirs/not_created_filepath/file
+  $ find home
+  find: 'home': No such file or directory
+  [1]
+  $ find cache
+  cache
+  cache/dirs
+  cache/dirs/created
+  $ find config
+  config
+  config/dirs
+  config/dirs/created
+  $ find state
+  state
+  state/dirs
+  state/dirs/created
+  $ rm -rf home cache config state
+
+Customized via variables: Plugin level
+  $ HOME=home FRAMAC_DIRS_CACHE=cache FRAMAC_DIRS_CONFIG=config FRAMAC_DIRS_STATE=state FRAMAC_DIRS_SESSION=session dune exec -- frama-c
+  [dirs] Warning: created cache directory `cache/created'
+  [dirs] Warning: created config directory `config/created'
+  [dirs] Warning: created state directory `state/created'
+  [dirs] Warning: created session directory `session/created'
+  [dirs] Warning: created session directory `session/created_filepath'
+  [dirs] Not created:
+  [dirs] cache/not_created
+  [dirs] config/not_created
+  [dirs] state/not_created
+  [dirs] session/not_created
+  [dirs] session/not_created_filepath/file
+  $ find home
+  find: 'home': No such file or directory
+  [1]
+  $ find cache
+  cache
+  cache/created
+  $ find config
+  config
+  config/created
+  $ find state
+  state
+  state/created
+  $ rm -rf home cache config state
+
+Customized via options kernel level
+  $ HOME=home dune exec -- frama-c -cache cache -config config -state state -session session
+  [dirs] Warning: created cache directory `cache/dirs/created'
+  [dirs] Warning: created config directory `config/dirs/created'
+  [dirs] Warning: created state directory `state/dirs/created'
+  [dirs] Not created:
+  [dirs] cache/dirs/not_created
+  [dirs] config/dirs/not_created
+  [dirs] state/dirs/not_created
+  [dirs] session/dirs/not_created
+  [dirs] session/dirs/not_created_filepath/file
+  $ find home
+  find: 'home': No such file or directory
+  [1]
+  $ find cache
+  cache
+  cache/dirs
+  cache/dirs/created
+  $ find config
+  config
+  config/dirs
+  config/dirs/created
+  $ find state
+  state
+  state/dirs
+  state/dirs/created
+  $ rm -rf home cache config state
+
+Customized via options plug-in level
+  $ HOME=home dune exec -- frama-c -dirs-cache cache -dirs-config config -dirs-state state -dirs-session session
+  [dirs] Warning: created cache directory `cache/created'
+  [dirs] Warning: created config directory `config/created'
+  [dirs] Warning: created state directory `state/created'
+  [dirs] Not created:
+  [dirs] cache/not_created
+  [dirs] config/not_created
+  [dirs] state/not_created
+  [dirs] session/not_created
+  [dirs] session/not_created_filepath/file
+  $ find home
+  find: 'home': No such file or directory
+  [1]
+  $ find cache
+  cache
+  cache/created
+  $ find config
+  config
+  config/created
+  $ find state
+  state
+  state/created
+  $ rm -rf home cache config state
+
+Customized plug-in option > plug-in var
+  $ HOME=home FRAMAC_DIRS_CACHE=cache_bad dune exec -- frama-c -dirs-cache-only -dirs-cache cache
+  [dirs] Warning: created cache directory `cache/created'
+  $ rm -rf home cache
+
+Customized plug-in var > kernel option
+  $ HOME=home FRAMAC_DIRS_CACHE=cache dune exec -- frama-c -dirs-cache-only -cache cache_bad
+  [dirs] Warning: created cache directory `cache/created'
+  $ rm -rf home cache
+
+Customized kernel option > kernel var
+  $ HOME=home FRAMAC_CACHE=cache_bad dune exec -- frama-c -dirs-cache-only -cache cache
+  [dirs] Warning: created cache directory `cache/dirs/created'
+  $ rm -rf home cache
+
+Customized kernel var > xdg var
+  $ HOME=home XDG_CACHE_HOME=cache_bad FRAMAC_CACHE=cache dune exec -- frama-c -dirs-cache-only
+  [dirs] Warning: created cache directory `cache/dirs/created'
+  $ rm -rf home cache
+
+Bad home value
+  $ HOME= dune exec -- frama-c
+  [dirs] User Error: Failure when creating directories
+  [dirs] User Error: Deferred error message was emitted during execution. See above messages for more information.
+  [kernel] Plug-in dirs aborted: invalid user input.
+  [1]
+
+Bad home permission
+  $ mkdir home
+  $ chmod -w home
+  $ HOME=home dune exec -- frama-c
+  [dirs] User Error: cannot create cache directory `home/.cache/frama-c/dirs/created'
+  [kernel] Plug-in dirs aborted: invalid user input.
+  [1]
+  $ rm -rf home
+
+File already exists were a directory is expected
+  $ mkdir cache
+  $ touch cache/created
+  $ HOME=home dune exec -- frama-c -dirs-cache cache
+  [dirs] User Error: cannot create directory as file cache/created already exists
+  [kernel] Plug-in dirs aborted: invalid user input.
+  [1]
+  $ rm -rf cache