From cf21c6318367870359b09d63c2296d2248c15990 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Mon, 26 Oct 2020 18:28:35 +0200 Subject: [PATCH] v.vcache: extract v.vcache to a separate module, to test it and reuse it --- vlib/v/pref/default.v | 4 +- vlib/v/pref/pref.v | 3 +- vlib/v/{pref => vcache}/vcache.v | 14 +++++- vlib/v/vcache/vcache_test.v | 85 ++++++++++++++++++++++++++++++++ 4 files changed, 102 insertions(+), 4 deletions(-) rename vlib/v/{pref => vcache}/vcache.v (82%) create mode 100644 vlib/v/vcache/vcache_test.v diff --git a/vlib/v/pref/default.v b/vlib/v/pref/default.v index 5371a56ff5..772ec2fbec 100644 --- a/vlib/v/pref/default.v +++ b/vlib/v/pref/default.v @@ -4,6 +4,7 @@ module pref import os +import v.vcache pub const ( default_module_path = mpath() @@ -73,7 +74,8 @@ pub fn (mut p Preferences) fill_with_defaults() { } // Prepare the cache manager. All options that can affect the generated cached .c files // should go into res.cache_manager.vopts, which is used as a salt for the cache hash. - p.cache_manager = new_cache_manager([ + p.cache_manager = vcache.new_cache_manager([ + @VHASH, // ensure that different v versions use separate build artefacts '$p.backend | $p.os | $p.ccompiler', p.cflags.trim_space(), p.third_party_option.trim_space(), diff --git a/vlib/v/pref/pref.v b/vlib/v/pref/pref.v index f9a00011e9..b110438003 100644 --- a/vlib/v/pref/pref.v +++ b/vlib/v/pref/pref.v @@ -5,6 +5,7 @@ module pref import os.cmdline import os +import v.vcache pub enum BuildMode { // `v program.v' @@ -130,7 +131,7 @@ pub mut: is_apk bool // build as Android .apk format cleanup_files []string // list of temporary *.tmp.c and *.tmp.c.rsp files. Cleaned up on successfull builds. build_options []string // list of options, that should be passed down to `build-module`, if needed for -usecache - cache_manager CacheManager + cache_manager vcache.CacheManager } pub fn parse_args(args []string) (&Preferences, string) { diff --git a/vlib/v/pref/vcache.v b/vlib/v/vcache/vcache.v similarity index 82% rename from vlib/v/pref/vcache.v rename to vlib/v/vcache/vcache.v index eabaf258ef..6b170dacf9 100644 --- a/vlib/v/pref/vcache.v +++ b/vlib/v/vcache/vcache.v @@ -1,4 +1,4 @@ -module pref +module vcache import os import hash @@ -13,6 +13,7 @@ import hash // Cleanup of the cache is simple: just delete the $VCACHE folder. // The cache tree will look like this: // │ $VCACHE +// │ ├── README.md <-- a short description of the folder's purpose. // │ ├── 0f // │ │ ├── 0f004f983ab9c487b0d7c1a0a73840a5.txt // │ │ ├── 0f599edf5e16c2756fbcdd4c865087ac.description.txt <-- build details @@ -32,11 +33,20 @@ pub mut: k2cpath map[string]string // key -> filesystem cache path for the object } -fn new_cache_manager(opts []string) CacheManager { +pub fn new_cache_manager(opts []string) CacheManager { mut vcache_basepath := os.getenv('VCACHE') if vcache_basepath == '' { vcache_basepath = os.join_path(os.home_dir(), '.vmodules', 'cache') } + if !os.is_dir(vcache_basepath) { + os.mkdir_all(vcache_basepath) + readme_content := 'This folder contains cached build artifacts from the V build system. + |You can safely delete it, if it is getting too large. + |It will be recreated the next time you compile something with V. + |You can change its location with the VCACHE environment variable. + '.strip_margin() + os.write_file(os.join_path(vcache_basepath, 'README.md'), readme_content) + } return CacheManager{ basepath: vcache_basepath vopts: opts.join('|') diff --git a/vlib/v/vcache/vcache_test.v b/vlib/v/vcache/vcache_test.v new file mode 100644 index 0000000000..92b9877a55 --- /dev/null +++ b/vlib/v/vcache/vcache_test.v @@ -0,0 +1,85 @@ +import os +import v.vcache + +const ( + vcache_folder = os.join_path(os.temp_dir(), 'vcache_folder') +) + +fn check_cache_entry_fpath_invariants(x string, extension string) { + a := x.replace(vcache_folder + os.path_separator, '').split(os.path_separator) + assert a.len > 0 + assert a[0].len == 2 + assert a[1].len > 32 + assert os.file_ext(a[1]) == extension + assert a[1][0..2] == a[0] +} + +fn testsuite_begin() ? { + os.setenv('VCACHE', vcache_folder, true) + // eprintln('testsuite_begin, vcache_folder = $vcache_folder') + os.rmdir_all(vcache_folder) + vcache.new_cache_manager([]) + assert os.is_dir(vcache_folder) +} + +fn test_save_and_load() ? { + mut cm := vcache.new_cache_manager([]) + x := cm.save('.txt', 'first/cache/entry', 'hello') ? + check_cache_entry_fpath_invariants(x, '.txt') +} + +fn test_different_options_should_produce_different_cache_entries_for_same_key_and_content() ? { + mut cm1 := vcache.new_cache_manager([]) + mut cm2 := vcache.new_cache_manager(['-cc tcc']) + mut cm3 := vcache.new_cache_manager(['-cc gcc']) + x := cm1.save('.txt', 'first/cache/entry', 'hello') ? + y := cm2.save('.txt', 'first/cache/entry', 'hello') ? + z := cm3.save('.txt', 'first/cache/entry', 'hello') ? + check_cache_entry_fpath_invariants(x, '.txt') + check_cache_entry_fpath_invariants(y, '.txt') + check_cache_entry_fpath_invariants(z, '.txt') +} + +fn test_exists() ? { + mut cm := vcache.new_cache_manager([]) + cm.exists('.o', 'abc') or { + assert true + } + // + x := cm.save('.x', 'abc', '') ? + cm.exists('.o', 'abc') or { + assert true + } + // + y := cm.save('.o', 'zbc', '') ? + cm.exists('.o', 'abc') or { + assert true + } + // + z := cm.save('.o', 'abc', '') ? + cm.exists('.o', 'abc') or { + assert false + } + // + assert os.is_file(x) + assert os.is_file(y) + assert os.is_file(z) + assert x != y + assert x != z + assert y != z +} + +fn test_readme_exists_and_is_readable() ? { + vcache.new_cache_manager([]) + freadme := os.join_path(vcache_folder, 'README.md') + assert os.is_file(freadme) + x := os.read_file(freadme) ? + assert x.len > 0 + assert x.starts_with('This folder contains cached build artifacts') +} + +fn testsuite_end() { + os.chdir(os.wd_at_startup) + os.rmdir_all(vcache_folder) + assert !os.is_dir(vcache_folder) +}